From 3e5d7a994e117b2758906154433a1aac860cc845 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 24 Mar 2021 16:12:25 +0100 Subject: [PATCH 001/306] Prepare for Apache NimBLE 1.4.0 release --- NOTICE | 2 +- README.md | 1 + RELEASE_NOTES.md | 25 +++++++------------------ repository.yml | 4 ++++ 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/NOTICE b/NOTICE index 84ecb14d9f..90952ecc53 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache Mynewt NimBLE -Copyright 2015-2020 The Apache Software Foundation +Copyright 2015-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md index 37103be08e..96c636634c 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Features highlight: - Support for up to 32 simultaneous connections. - Legacy and SC (secure connections) SMP support (pairing and bonding). - Advertising Extensions. + - Periodic Advertising. - Coded (aka Long Range) and 2M PHYs. - Bluetooth Mesh. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3bdd31ad05..99810a718d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # RELEASE NOTES -18 March 2020 - Apache NimBLE v1.3.0 +24 March 2021 - Apache NimBLE v1.4.0 For full release notes, please visit the [Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes). @@ -10,23 +10,12 @@ replaces the proprietary SoftDevice on Nordic chipsets. New features in this version of NimBLE include: -* Support for Bluetooth Core Specification 5.1 -* New blestress test application -* Dialog DA1469x CMAC driver -* Support for LE Secure Connections out-of-band (OOB) association model -* Support for automated generation of syscfg for ports -* Qualification related bugfixes -* BLE Mesh improvements - fixes and resync with latest Zephyr code -* RIOT OS port fixes and improvements -* btshell sample application improvements -* improvements for bttester application -* Controller duplicates filtering improvements -* Multi PHY support improvements -* Memory and CPU usage optimizations -* Use of packed structs for HCI (code size reduction) -* Linux sample improvements -* PTS test instructions updates -* Clock managements improvements in controller +* Support for PHY on Dialog Configurable MAC (CMAC) +* Support for PHY on Nordic nRF5340 +* Support for Apache NuttX port of NimBLE +* Controller-to-host flow control support +* Support for USB transport +* Various bugfixes If working on next-generation RTOS and Bluetooth protocol stack sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt diff --git a/repository.yml b/repository.yml index 4a097d39a5..64315b76f8 100644 --- a/repository.yml +++ b/repository.yml @@ -29,11 +29,13 @@ repo.versions: "1.1.0": "nimble_1_1_0_tag" "1.2.0": "nimble_1_2_0_tag" "1.3.0": "nimble_1_3_0_tag" + "1.4.0": "nimble_1_4_0_tag" "1.0-latest": "1.0.0" "1.1-latest": "1.1.0" "1.2-latest": "1.2.0" "1.3-latest": "1.3.0" + "1.4-latest": "1.4.0" repo.newt_compatibility: 0.0.0: @@ -46,3 +48,5 @@ repo.newt_compatibility: 1.7.0: good 1.3.0: 1.8.0: good + 1.4.0: + 1.9.0: good From 8cd76e5dfddc3e365b10769987b3948b9cadc2fe Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 26 Mar 2021 19:54:04 +0100 Subject: [PATCH 002/306] nimble/hs: Fix mbuf allocation for combined build In combined build we need to allocate mbufs with user header since LL needs extra space to keep txinfo. This works so far only because txinfo has 4 bytes and it overwrites omp_next in packet header which is only used when mbuf is enqueued. Once dequeued, we don't use so it's "ok" to overwrite it. However if txinfo is extended with some extra data we will start overwriting PDU data when writing to txinfo. --- nimble/host/src/ble_hs_mbuf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nimble/host/src/ble_hs_mbuf.c b/nimble/host/src/ble_hs_mbuf.c index d938d34806..6e920f94fe 100644 --- a/nimble/host/src/ble_hs_mbuf.c +++ b/nimble/host/src/ble_hs_mbuf.c @@ -29,7 +29,11 @@ ble_hs_mbuf_gen_pkt(uint16_t leading_space) struct os_mbuf *om; int rc; +#if MYNEWT_VAL(BLE_CONTROLLER) + om = os_msys_get_pkthdr(0, sizeof(struct ble_mbuf_hdr)); +#else om = os_msys_get_pkthdr(0, 0); +#endif if (om == NULL) { return NULL; } From f0a5e96db2026c1178ee5e76a2eb0a4fd78b487c Mon Sep 17 00:00:00 2001 From: Niklas Casaril Date: Fri, 19 Mar 2021 17:30:06 +1000 Subject: [PATCH 003/306] nimble/ll: Fix for frag tx of mbufs >255 bytes --- nimble/controller/src/ble_ll_conn.c | 19 +++++++++---------- nimble/controller/src/ble_ll_conn_priv.h | 2 +- nimble/include/nimble/ble.h | 4 ++-- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index b8352f4aa2..7da71479fe 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -959,8 +959,8 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) uint8_t hdr_byte; uint8_t end_transition; uint8_t cur_txlen; - uint8_t next_txlen; - uint8_t cur_offset; + uint16_t next_txlen; + uint16_t cur_offset; uint16_t pktlen; uint32_t next_event_time; uint32_t ticks; @@ -1129,11 +1129,10 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) if ((cur_offset + cur_txlen) < pktlen) { next_txlen = pktlen - (cur_offset + cur_txlen); } else { - if (nextpkthdr->omp_len > connsm->eff_max_tx_octets) { - next_txlen = connsm->eff_max_tx_octets; - } else { - next_txlen = nextpkthdr->omp_len; - } + next_txlen = connsm->eff_max_tx_octets; + } + if (next_txlen > connsm->eff_max_tx_octets) { + next_txlen = connsm->eff_max_tx_octets; } /* @@ -1491,7 +1490,7 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime, uint32_t add_usecs) { int rc; - uint8_t rem_bytes; + uint16_t rem_bytes; uint32_t ticks; uint32_t usecs; uint32_t next_sched_time; @@ -3791,7 +3790,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) uint8_t conn_sn; uint8_t conn_nesn; uint8_t reply; - uint8_t rem_bytes; + uint16_t rem_bytes; uint8_t opcode = 0; uint8_t rx_pyld_len; uint32_t begtime; @@ -4074,7 +4073,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) */ void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, - uint8_t hdr_byte, uint8_t length) + uint8_t hdr_byte, uint16_t length) { os_sr_t sr; struct os_mbuf_pkthdr *pkthdr; diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h index 53358c4a0d..915a4d2a62 100644 --- a/nimble/controller/src/ble_ll_conn_priv.h +++ b/nimble/controller/src/ble_ll_conn_priv.h @@ -120,7 +120,7 @@ struct hci_create_conn void ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm); void ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err); void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, - uint8_t hdr_byte, uint8_t length); + uint8_t hdr_byte, uint16_t length); struct ble_ll_conn_sm *ble_ll_conn_sm_get(void); void ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, struct hci_create_conn *hcc); diff --git a/nimble/include/nimble/ble.h b/nimble/include/nimble/ble.h index 248e8ae834..1ddd5773d0 100644 --- a/nimble/include/nimble/ble.h +++ b/nimble/include/nimble/ble.h @@ -109,9 +109,9 @@ struct ble_mbuf_hdr_rxinfo struct ble_mbuf_hdr_txinfo { uint8_t flags; - uint8_t offset; - uint8_t pyld_len; uint8_t hdr_byte; + uint16_t offset; + uint16_t pyld_len; }; struct ble_mbuf_hdr From 4fae6e1ab723c8a94b58e1a30818d8862b2e59fd Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Thu, 25 Mar 2021 13:06:38 +0100 Subject: [PATCH 004/306] npl/riot: enable BLE_HCI_VS in default config --- porting/npl/riot/include/syscfg/syscfg.h | 44 ++++++++++++++++++++++++ porting/targets/riot/syscfg.yml | 1 + 2 files changed, 45 insertions(+) diff --git a/porting/npl/riot/include/syscfg/syscfg.h b/porting/npl/riot/include/syscfg/syscfg.h index 816f410ac5..f7406f076a 100644 --- a/porting/npl/riot/include/syscfg/syscfg.h +++ b/porting/npl/riot/include/syscfg/syscfg.h @@ -15,6 +15,45 @@ #define MYNEWT_VAL(_name) MYNEWT_VAL_ ## _name #define MYNEWT_VAL_CHOICE(_name, _val) MYNEWT_VAL_ ## _name ## __ ## _val + +/*** Repository @apache-mynewt-core info */ +#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE ("6b205affd69a6f05787264fa2c70c621bbbdd325") +#endif + +#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE +#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE ("0.0.0") +#endif + +/*** Repository @apache-mynewt-mcumgr info */ +#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR ("64f5060bd8bb466367e0da94da8b425d5b9f6388") +#endif + +#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR +#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR ("0.0.0") +#endif + +/*** Repository @apache-mynewt-nimble info */ +#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE ("3e5d7a994e117b2758906154433a1aac860cc845-dirty") +#endif + +#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE +#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE ("0.0.0") +#endif + +/*** Repository @mcuboot info */ +#ifndef MYNEWT_VAL_REPO_HASH_MCUBOOT +#define MYNEWT_VAL_REPO_HASH_MCUBOOT ("579b30c29999860f9f7d843a25ff5453b6542cce") +#endif + +#ifndef MYNEWT_VAL_REPO_VERSION_MCUBOOT +#define MYNEWT_VAL_REPO_VERSION_MCUBOOT ("0.0.0") +#endif + + + /*** @apache-mynewt-core/compiler/arm-none-eabi-m4 */ #ifndef MYNEWT_VAL_HARDFLOAT #define MYNEWT_VAL_HARDFLOAT (0) @@ -775,6 +814,11 @@ #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) #endif +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble) */ +#ifndef MYNEWT_VAL_BLE_HCI_VS +#define MYNEWT_VAL_BLE_HCI_VS (1) +#endif + #ifndef MYNEWT_VAL_BLE_ISO #define MYNEWT_VAL_BLE_ISO (0) #endif diff --git a/porting/targets/riot/syscfg.yml b/porting/targets/riot/syscfg.yml index d6ee102bf9..8359eaa7c9 100644 --- a/porting/targets/riot/syscfg.yml +++ b/porting/targets/riot/syscfg.yml @@ -18,6 +18,7 @@ syscfg.vals: BLE_ACL_BUF_COUNT: 24 + BLE_HCI_VS: 1 BLE_HCI_EVT_HI_BUF_COUNT: 2 BLE_HW_WHITELIST_ENABLE: 0 BLE_LL_CFG_FEAT_DATA_LEN_EXT: 0 From 1b09cf2a7624d5f3f83d3d922113a094efb00aeb Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sat, 20 Mar 2021 14:30:29 +0100 Subject: [PATCH 005/306] nimble/phy/cmac: Fix return value for RX late start This does not affect current code, but we should return proper code if RX was late anyway. --- nimble/drivers/dialog_cmac/src/ble_phy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nimble/drivers/dialog_cmac/src/ble_phy.c b/nimble/drivers/dialog_cmac/src/ble_phy.c index ab0f88505f..74c67b68b5 100644 --- a/nimble/drivers/dialog_cmac/src/ble_phy.c +++ b/nimble/drivers/dialog_cmac/src/ble_phy.c @@ -1369,6 +1369,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) { uint32_t ll_val32; int32_t time_till_start; + int rc = 0; MCU_DIAG_SER('r'); @@ -1404,11 +1405,12 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) /* We missed start. Start now */ CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_ASAP_Msk; + rc = BLE_PHY_ERR_RX_LATE; } } __enable_irq(); - return 0; + return rc; } int From d3a63cdefd2434b7b8dd2ba112ea24b60dfdbb0d Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 31 Mar 2021 19:33:11 +0200 Subject: [PATCH 006/306] nimble/ll: Remove unused function This is leftover after 11f16896 removed code that used this callback. --- nimble/controller/src/ble_ll_conn.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 7da71479fe..af610b50ba 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -1568,22 +1568,6 @@ ble_ll_conn_auth_pyld_timer_cb(struct ble_npl_event *ev) ble_ll_conn_auth_pyld_timer_start(connsm); } -void -ble_ll_conn_rd_features_timer_cb(struct ble_npl_event *ev) -{ - struct ble_ll_conn_sm *connsm; - - connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); - - if (!connsm->csmflags.cfbit.pending_hci_rd_features || - !connsm->csmflags.cfbit.rxd_features) { - return; - } - - ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; -} - /** * Start (or restart) the authenticated payload timer * From c5d7eb550d77cf09510d27ee8ac1591c3af65ef5 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 1 Apr 2021 15:47:52 +0200 Subject: [PATCH 007/306] nimble/ll: Remove unused adv_sm member This is leftover after some code was removed in cb93173f. --- nimble/controller/src/ble_ll_adv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 72c4e7d67d..092e813c25 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -110,7 +110,6 @@ struct ble_ll_adv_sm uint32_t adv_event_start_time; uint32_t adv_pdu_start_time; uint32_t adv_end_time; - uint32_t adv_rpa_timer; uint8_t adva[BLE_DEV_ADDR_LEN]; uint8_t adv_rpa[BLE_DEV_ADDR_LEN]; uint8_t peer_addr[BLE_DEV_ADDR_LEN]; From 250cd70c6b2c27b2ce9ee083186511c6aaa96e80 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 7 Apr 2021 10:28:01 +0200 Subject: [PATCH 008/306] Apache NimBLE 1.4.0 release --- repository.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/repository.yml b/repository.yml index 64315b76f8..9f112a825e 100644 --- a/repository.yml +++ b/repository.yml @@ -22,8 +22,8 @@ repo.versions: "0.0.0": "master" "0-dev": "0.0.0" - "0-latest": "1.3.0" - "1-latest": "1.3.0" + "0-latest": "1.4.0" + "1-latest": "1.4.0" "1.0.0": "nimble_1_0_0_tag" "1.1.0": "nimble_1_1_0_tag" From dd7ebf179f351a403027d1b216049d1a5b88e2cd Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 12 Apr 2021 00:13:05 +0200 Subject: [PATCH 009/306] porting: Fix mempool initialization This fix crash on init due to changes in mmepool init after recent sync with core. --- porting/examples/linux/main.c | 2 +- porting/examples/linux_blemesh/main.c | 2 +- porting/examples/nuttx/main.c | 5 +++-- porting/nimble/src/nimble_port.c | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/porting/examples/linux/main.c b/porting/examples/linux/main.c index 86b6fb9559..a2e255d083 100644 --- a/porting/examples/linux/main.c +++ b/porting/examples/linux/main.c @@ -65,8 +65,8 @@ int main(int argc, char *argv[]) ble_hci_sock_set_device(atoi(argv[1])); } - ble_hci_sock_init(); nimble_port_init(); + ble_hci_sock_init(); /* This example provides GATT Alert service */ ble_svc_gap_init(); diff --git a/porting/examples/linux_blemesh/main.c b/porting/examples/linux_blemesh/main.c index 0913551e8c..f5c5e4f04f 100644 --- a/porting/examples/linux_blemesh/main.c +++ b/porting/examples/linux_blemesh/main.c @@ -77,8 +77,8 @@ int main(int argc, char *argv[]) ble_hci_sock_set_device(atoi(argv[1])); } - ble_hci_sock_init(); nimble_port_init(); + ble_hci_sock_init(); ble_svc_gap_init(); ble_svc_gatt_init(); diff --git a/porting/examples/nuttx/main.c b/porting/examples/nuttx/main.c index acfc9fcd18..82582573ad 100644 --- a/porting/examples/nuttx/main.c +++ b/porting/examples/nuttx/main.c @@ -71,11 +71,12 @@ int main(int argc, char *argv[]) ble_hci_sock_set_device(atoi(argv[1])); } - printf("hci init\n"); - ble_hci_sock_init(); printf("port init\n"); nimble_port_init(); + printf("hci init\n"); + ble_hci_sock_init(); + /* This example provides GATT Alert service */ printf("gap init\n"); ble_svc_gap_init(); diff --git a/porting/nimble/src/nimble_port.c b/porting/nimble/src/nimble_port.c index 06b5f6df91..484e37995c 100644 --- a/porting/nimble/src/nimble_port.c +++ b/porting/nimble/src/nimble_port.c @@ -30,6 +30,7 @@ static struct ble_npl_eventq g_eventq_dflt; extern void os_msys_init(void); +extern void os_mempool_module_init(void); void nimble_port_init(void) @@ -37,6 +38,7 @@ nimble_port_init(void) /* Initialize default event queue */ ble_npl_eventq_init(&g_eventq_dflt); /* Initialize the global memory pool */ + os_mempool_module_init(); os_msys_init(); /* Initialize the host */ ble_hs_init(); From 1d073cc84d5e387dcca250ff75d77c20f735ced0 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 13 Apr 2021 14:36:29 +0200 Subject: [PATCH 010/306] transport/cmac: Fix race on LL event write HCI commands are processed in LL task context and thus CS/CC events are written to mbox in the same context. This can lead to following race: - CS/CC is written to mbox - interrupt in handled on CMAC *before* command buffer is freed - M33 reads CS/CC and writes next command to mbox - CMAC reads new command This triggers an assert in code because we do not have free buffer for new command because we were busy handling interrupts and did not free it yet. To fix this we should write and free in critical section. --- nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c b/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c index 3531529c71..6b49158ad9 100644 --- a/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c +++ b/nimble/transport/dialog_cmac/src/ble_hci_cmac_ll.c @@ -92,12 +92,17 @@ int ble_hci_trans_ll_evt_tx(uint8_t *evt) { uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_EVT; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); cmac_mbox_write(&pkt_type, sizeof(pkt_type)); cmac_mbox_write(evt, evt[1] + 2); ble_hci_trans_buf_free(evt); + OS_EXIT_CRITICAL(sr); + return 0; } From 940cc0b4a81295305ceead15928da24fe6e6f603 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Wed, 3 Feb 2021 10:48:48 +0100 Subject: [PATCH 011/306] npl/riot: rework to use RIOTs ztimer ztimer is a new high-level timer API in RIOT that was introcuced a while ago to be the successor of xtimer. This commit reworks the RIOT NPL implementation to use ztimer instead of xtimer. This simplifies the NPL implementation and it allows for significant energy savings. For the xtimer switch the implemenation further switches from RIOTs `posix_semaphore` module to the slimmer `sema` module, as the prior indirectly pulls in xtimer as dependency. --- .../npl/riot/include/nimble/nimble_npl_os.h | 45 ++++++++----------- porting/npl/riot/src/npl_os_riot.c | 27 ++++------- 2 files changed, 26 insertions(+), 46 deletions(-) diff --git a/porting/npl/riot/include/nimble/nimble_npl_os.h b/porting/npl/riot/include/nimble/nimble_npl_os.h index 854fd06c13..d279d250a8 100644 --- a/porting/npl/riot/include/nimble/nimble_npl_os.h +++ b/porting/npl/riot/include/nimble/nimble_npl_os.h @@ -24,8 +24,8 @@ #include #include "event/callback.h" #include "mutex.h" -#include "semaphore.h" -#include "xtimer.h" +#include "sema.h" +#include "ztimer.h" #ifdef __cplusplus extern "C" { @@ -50,8 +50,8 @@ struct ble_npl_eventq { }; struct ble_npl_callout { - xtimer_t timer; - uint64_t target_us; + ztimer_t timer; + ble_npl_time_t ticks; struct ble_npl_event e; event_queue_t *q; }; @@ -61,7 +61,7 @@ struct ble_npl_mutex { }; struct ble_npl_sem { - sem_t sem; + sema_t sem; }; static inline bool @@ -100,8 +100,9 @@ ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) } else if (tmo == BLE_NPL_TIME_FOREVER) { return (struct ble_npl_event *)event_wait(&evq->q); } else { - return (struct ble_npl_event *)event_wait_timeout64(&evq->q, - tmo * US_PER_MS); + return (struct ble_npl_event *)event_wait_timeout_ztimer(&evq->q, + ZTIMER_MSEC, + (uint32_t)tmo); } } @@ -174,49 +175,39 @@ ble_npl_mutex_release(struct ble_npl_mutex *mu) static inline ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) { - int rc; - - rc = sem_init(&sem->sem, 0, tokens); - - return rc == 0 ? BLE_NPL_OK : BLE_NPL_ERROR; + sema_create(&sem->sem, (unsigned)tokens); + return BLE_NPL_OK; } static inline ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem) { - int rc; - - rc = sem_post(&sem->sem); - - return rc == 0 ? BLE_NPL_OK : BLE_NPL_ERROR; + int rc = sema_post(&sem->sem); + return (rc == 0) ? BLE_NPL_OK : BLE_NPL_ERROR; } static inline uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem) { - int val = 0; - - sem_getvalue(&sem->sem, &val); - - return (uint16_t)val; + return (uint16_t)sema_get_value(&sem->sem); } static inline void ble_npl_callout_stop(struct ble_npl_callout *co) { - xtimer_remove(&co->timer); + ztimer_remove(ZTIMER_MSEC, &co->timer); } static inline bool ble_npl_callout_is_active(struct ble_npl_callout *c) { - return (c->timer.offset || c->timer.long_offset); + return ztimer_is_set(ZTIMER_MSEC, &c->timer); } static inline ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *co) { - return (ble_npl_time_t)(co->target_us / US_PER_MS); + return co->ticks; } static inline void @@ -228,7 +219,7 @@ ble_npl_callout_set_arg(struct ble_npl_callout *co, void *arg) static inline ble_npl_time_t ble_npl_time_get(void) { - return (ble_npl_time_t)(xtimer_now_usec64() / US_PER_MS); + return (ble_npl_time_t)ztimer_now(ZTIMER_MSEC); } static inline ble_npl_error_t @@ -260,7 +251,7 @@ ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) static inline void ble_npl_time_delay(ble_npl_time_t ticks) { - xtimer_usleep64(ticks * US_PER_MS); + ztimer_sleep(ZTIMER_MSEC, (uint32_t)ticks); } static inline uint32_t diff --git a/porting/npl/riot/src/npl_os_riot.c b/porting/npl/riot/src/npl_os_riot.c index 2f4efd8ba5..71c130f198 100644 --- a/porting/npl/riot/src/npl_os_riot.c +++ b/porting/npl/riot/src/npl_os_riot.c @@ -35,18 +35,8 @@ _callout_fire(void *arg) ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) { - int rc; - struct timespec abs; - uint64_t time; - - time = xtimer_now_usec64() + - (ble_npl_time_ticks_to_ms32(timeout) * US_PER_MS); - abs.tv_sec = (time_t)(time / US_PER_SEC); - abs.tv_nsec = (long)((time % US_PER_SEC) * NS_PER_US); - - rc = sem_timedwait(&sem->sem, &abs); - - return rc == 0 ? BLE_NPL_OK : BLE_NPL_ENOENT; + int rc = sema_wait_timed_ztimer(&sem->sem, ZTIMER_MSEC, timeout); + return (rc == 0) ? BLE_NPL_OK : BLE_NPL_ENOENT; } void @@ -62,19 +52,18 @@ ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq, ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *c, ble_npl_time_t ticks) { - /* Use critical section to ensure matching target_us and xtimer value. */ + /* Use critical section to ensure matching target_us and ztimer value. */ uint32_t crit_state = ble_npl_hw_enter_critical(); - uint64_t now = xtimer_now_usec64(); - c->target_us = now + ticks * US_PER_MS; - xtimer_set64(&c->timer, ticks * US_PER_MS); + c->ticks = ztimer_now(ZTIMER_MSEC) + ticks; + ztimer_set(ZTIMER_MSEC, &c->timer, ticks); ble_npl_hw_exit_critical(crit_state); return BLE_NPL_OK; } -uint32_t +ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *co, ble_npl_time_t time) { - uint64_t now = xtimer_now_usec64(); - return (uint32_t)((co->target_us - now) / US_PER_MS); + ztimer_now_t now = ztimer_now(ZTIMER_MSEC); + return (ble_npl_time_t)(co->ticks - now); } From 87bfc8e8ca94e826a8f04d041495fe01890fcbf8 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 12 Apr 2021 17:35:17 +0200 Subject: [PATCH 012/306] nimble/transport: Improve nrf5340 transport This allows to use it regardless of IPC buffer size. --- .../transport/nrf5340/src/nrf5340_ble_hci.c | 92 +++++++++++++------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c index 3f113e1175..8f91983499 100644 --- a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c +++ b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c @@ -270,15 +270,29 @@ nrf5340_ble_hci_trans_rx_process(int channel) break; #if MYNEWT_VAL(BLE_CONTROLLER) case HCI_PKT_CMD: - /* commands are sent complete over IPC */ - rxd->len = ipc_nrf5340_read(channel, rxd->hdr, 3); - assert(rxd->len == 3); + /* header */ + if (rxd->len < 3) { + rxd->len += ipc_nrf5340_read(channel, &rxd->hdr[rxd->len], + 3 - rxd->len); + if (rxd->len < 3) { + break; + } + } - rxd->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); - memcpy(rxd->buf, rxd->hdr, rxd->len); + if (rxd->expected_len == 0) { + rxd->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); + memcpy(rxd->buf, rxd->hdr, rxd->len); + + rxd->expected_len = 3 + rxd->hdr[2]; + } - rxd->len += ipc_nrf5340_read(channel, &rxd->buf[rxd->len], rxd->hdr[2]); - assert(rxd->len == 3 + rxd->hdr[2]); + if (rxd->len < rxd->expected_len) { + rxd->len += ipc_nrf5340_read(channel, &rxd->buf[rxd->len], + rxd->expected_len - rxd->len); + if (rxd->len < rxd->expected_len) { + break; + } + } rc = nrf5340_ble_hci_api.cmd_cb(rxd->buf, nrf5340_ble_hci_api.cmd_arg); if (rc != 0) { @@ -290,14 +304,23 @@ nrf5340_ble_hci_trans_rx_process(int channel) #endif #if MYNEWT_VAL(BLE_HOST) case HCI_PKT_EVT: - /* events are sent complete over IPC */ - rxd->len = ipc_nrf5340_read(channel, rxd->hdr, 2); - assert(rxd->len == 2); + /* header */ + if (rxd->len < 2) { + rxd->len += ipc_nrf5340_read(channel, &rxd->hdr[rxd->len], + 2 - rxd->len); + if (rxd->len < 2) { + break; + } + } if (rxd->hdr[0] == BLE_HCI_EVCODE_LE_META) { - /* For LE Meta event we need 3 bytes to parse header */ - rxd->len += ipc_nrf5340_read(channel, rxd->hdr + 2, 1); - assert(rxd->len == 3); + if (rxd->len < 3) { + /* For LE Meta event we need 3 bytes to parse header */ + rxd->len += ipc_nrf5340_read(channel, &rxd->hdr[rxd->len], 1); + if (rxd->len < 3) { + break; + } + } /* Advertising reports shall be allocated from low-prio pool */ if ((rxd->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) || @@ -306,26 +329,33 @@ nrf5340_ble_hci_trans_rx_process(int channel) } } - rxd->buf = ble_hci_trans_buf_alloc(pool); - if (!rxd->buf) { - /* - * Only care about valid buffer when shall be allocated from - * high-prio pool, otherwise NULL is fine and we'll just skip - * this event. - */ - if (pool != BLE_HCI_TRANS_BUF_EVT_LO) { - rxd->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (rxd->expected_len == 0) { + rxd->buf = ble_hci_trans_buf_alloc(pool); + if (!rxd->buf) { + /* + * Only care about valid buffer when shall be allocated from + * high-prio pool, otherwise NULL is fine and we'll just skip + * this event. + */ + if (pool != BLE_HCI_TRANS_BUF_EVT_LO) { + rxd->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + } } - } - rxd->expected_len = 2 + rxd->hdr[1]; + rxd->expected_len = 2 + rxd->hdr[1]; - if (rxd->buf) { - memcpy(rxd->buf, rxd->hdr, rxd->len); + /* copy header */ + if (rxd->buf) { + memcpy(rxd->buf, rxd->hdr, rxd->len); + } + } + if (rxd->buf) { rxd->len += ipc_nrf5340_read(channel, &rxd->buf[rxd->len], rxd->expected_len - rxd->len); - assert(rxd->expected_len == rxd->len); + if (rxd->len < rxd->expected_len) { + break; + } rc = nrf5340_ble_hci_api.evt_cb(rxd->buf, nrf5340_ble_hci_api.evt_arg); @@ -335,7 +365,9 @@ nrf5340_ble_hci_trans_rx_process(int channel) } else { rxd->len += ipc_nrf5340_consume(channel, rxd->expected_len - rxd->len); - assert(rxd->expected_len == rxd->len); + if (rxd->len < rxd->expected_len) { + break; + } } rxd->type = HCI_PKT_NONE; @@ -343,8 +375,8 @@ nrf5340_ble_hci_trans_rx_process(int channel) #endif case HCI_PKT_ACL: if (rxd->len < 4) { - rxd->len += ipc_nrf5340_read(channel, rxd->hdr, 4 - rxd->len); - + rxd->len += ipc_nrf5340_read(channel, &rxd->hdr[rxd->len], + 4 - rxd->len); if (rxd->len < 4) { break; } From 3a77b6f019412720c7ad83a45af9a7cd74eb5217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 19 Apr 2021 13:32:55 +0200 Subject: [PATCH 013/306] host/mesh: fix paths in persistent storage All paths should be using bt_mesh instead of bt/mesh --- nimble/host/mesh/src/settings.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index 30fbf5a014..193cc0b2c4 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -1239,7 +1239,7 @@ static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data) return; } - snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src); + snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src); err = settings_save_one(path, NULL); if (err) { BT_ERR("Failed to clear RPL"); @@ -1388,7 +1388,7 @@ static void store_subnet(uint16_t net_idx) BT_DBG("NetKeyIndex 0x%03x", net_idx); - snprintk(path, sizeof(path), "bt/mesh/NetKey/%x", net_idx); + snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", net_idx); memcpy(&key.val[0], sub->keys[0].net, 16); memcpy(&key.val[1], sub->keys[1].net, 16); @@ -1418,7 +1418,7 @@ static void store_app(uint16_t app_idx) char *str; int err; - snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app_idx); + snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx); app = bt_mesh_app_key_get(app_idx); if (!app) { @@ -1532,7 +1532,7 @@ static void store_cdb_node(const struct bt_mesh_cdb_node *node) memcpy(val.uuid, node->uuid, 16); memcpy(val.dev_key, node->dev_key, 16); - snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", node->addr); + snprintk(path, sizeof(path), "bt_mesh/cdb/Node/%x", node->addr); str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); if (!str) { From 7823a64caf2bcf4c291c5c8b5ed698ada6e1b51b Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 9 Apr 2021 09:52:49 +0200 Subject: [PATCH 014/306] targets: Add sample target for controller on NRF5340 bsp This adds sample target for building NimBLE controller (blehci app) for Nordic NRF5340. It is used by default when combine image build is used for nordic_pca10095 bsp. Sample target should be used as a base for creating customized targets. This targets nordic_pca10095_net bsp, custom targets should point to appropriate BSP. --- targets/nordic_pca10095-blehci/pkg.yml | 24 +++++++++++++ targets/nordic_pca10095-blehci/syscfg.yml | 42 +++++++++++++++++++++++ targets/nordic_pca10095-blehci/target.yml | 22 ++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 targets/nordic_pca10095-blehci/pkg.yml create mode 100644 targets/nordic_pca10095-blehci/syscfg.yml create mode 100644 targets/nordic_pca10095-blehci/target.yml diff --git a/targets/nordic_pca10095-blehci/pkg.yml b/targets/nordic_pca10095-blehci/pkg.yml new file mode 100644 index 0000000000..3b72abe1bc --- /dev/null +++ b/targets/nordic_pca10095-blehci/pkg.yml @@ -0,0 +1,24 @@ +# +# 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. +# + +pkg.name: targets/nordic_pca10095-blehci +pkg.type: target +pkg.description: Sample target for BLE controller on NRF5340 +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" diff --git a/targets/nordic_pca10095-blehci/syscfg.yml b/targets/nordic_pca10095-blehci/syscfg.yml new file mode 100644 index 0000000000..4a4a1ba069 --- /dev/null +++ b/targets/nordic_pca10095-blehci/syscfg.yml @@ -0,0 +1,42 @@ +# +# 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. +# + +syscfg.vals: + BLE_HCI_TRANSPORT: nrf5340 + + MSYS_1_BLOCK_COUNT: 12 + MSYS_1_BLOCK_SIZE: 292 + BLE_LL_CFG_FEAT_DATA_LEN_EXT: 1 + BLE_LL_CFG_FEAT_LE_2M_PHY: 1 + BLE_LL_CFG_FEAT_LE_CODED_PHY: 1 + BLE_LL_CFG_FEAT_LL_PRIVACY: 1 + BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL: 1 + BLE_LL_CONN_INIT_MAX_TX_BYTES: 251 + BLE_LL_CONN_INIT_SLOTS: 4 + BLE_LL_DTM: 1 + BLE_LL_DTM_EXTENSIONS: 1 + BLE_LL_VND_EVENT_ON_ASSERT: 1 + BLE_MAX_CONNECTIONS: 5 + BLE_EXT_ADV: 1 + BLE_EXT_ADV_MAX_SIZE: 1650 + BLE_MAX_PERIODIC_SYNCS: 5 + BLE_MULTI_ADV_INSTANCES: 5 + BLE_PERIODIC_ADV: 1 + BLE_PERIODIC_ADV_SYNC_TRANSFER: 1 + BLE_VERSION: 51 diff --git a/targets/nordic_pca10095-blehci/target.yml b/targets/nordic_pca10095-blehci/target.yml new file mode 100644 index 0000000000..4d2641b77c --- /dev/null +++ b/targets/nordic_pca10095-blehci/target.yml @@ -0,0 +1,22 @@ +# +# 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. +# + +target.app: "@apache-mynewt-nimble/apps/blehci" +target.bsp: "@apache-mynewt-core/hw/bsp/nordic_pca10095_net" +target.build_profile: debug From 015bac780d662c4745f1b2961171715c6d06dc40 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 26 Apr 2021 18:14:55 +0200 Subject: [PATCH 015/306] transport/nrf5340: Add support for host to controller flow control --- .../transport/nrf5340/src/nrf5340_ble_hci.c | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c index 8f91983499..c0276c324c 100644 --- a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c +++ b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c @@ -73,8 +73,20 @@ struct nrf5340_ble_hci_pool_cmd { bool allocated; }; -/* (Pseudo)pool for HCI commands */ -static struct nrf5340_ble_hci_pool_cmd nrf5340_ble_hci_pool_cmd; +/* + * If controller-to-host flow control is enabled we need to hold an extra command + * buffer for HCI_Host_Number_Of_Completed_Packets which can be sent at any time. + */ +#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) || MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) +#define HCI_CMD_COUNT 2 +#else +#define HCI_CMD_COUNT 1 +#endif + +static uint8_t nrf5340_ble_hci_pool_cmd_mempool_buf[OS_MEMPOOL_BYTES( + HCI_CMD_COUNT, + BLE_HCI_TRANS_CMD_SZ)]; +static struct os_mempool nrf5340_ble_hci_pool_cmd_mempool; /* Pools for HCI events (high and low priority) */ static uint8_t nrf5340_ble_hci_pool_evt_hi_buf[OS_MEMPOOL_BYTES( @@ -90,7 +102,7 @@ static struct os_mempool nrf5340_ble_hci_pool_evt_lo; static uint8_t nrf5340_ble_hci_pool_acl_buf[OS_MEMPOOL_BYTES( MYNEWT_VAL(BLE_ACL_BUF_COUNT), POOL_ACL_BLOCK_SIZE)]; -static struct os_mempool nrf5340_ble_hci_pool_acl; +static struct os_mempool_ext nrf5340_ble_hci_pool_acl; static struct os_mbuf_pool nrf5340_ble_hci_pool_acl_mbuf; /* Interface to host/ll */ @@ -207,9 +219,7 @@ ble_hci_trans_buf_alloc(int type) switch (type) { case BLE_HCI_TRANS_BUF_CMD: - assert(!nrf5340_ble_hci_pool_cmd.allocated); - nrf5340_ble_hci_pool_cmd.allocated = 1; - buf = nrf5340_ble_hci_pool_cmd.cmd; + buf = os_memblock_get(&nrf5340_ble_hci_pool_cmd_mempool); break; case BLE_HCI_TRANS_BUF_EVT_HI: buf = os_memblock_get(&nrf5340_ble_hci_pool_evt_hi); @@ -233,9 +243,9 @@ ble_hci_trans_buf_free(uint8_t *buf) { int rc; - if (buf == nrf5340_ble_hci_pool_cmd.cmd) { - assert(nrf5340_ble_hci_pool_cmd.allocated); - nrf5340_ble_hci_pool_cmd.allocated = 0; + if (os_memblock_from(&nrf5340_ble_hci_pool_cmd_mempool, buf)) { + rc = os_memblock_put(&nrf5340_ble_hci_pool_cmd_mempool, buf); + assert(rc == 0); } else if (os_memblock_from(&nrf5340_ble_hci_pool_evt_hi, buf)) { rc = os_memblock_put(&nrf5340_ble_hci_pool_evt_hi, buf); assert(rc == 0); @@ -387,7 +397,7 @@ nrf5340_ble_hci_trans_rx_process(int channel) rxd->om = os_mbuf_get_pkthdr(&nrf5340_ble_hci_pool_acl_mbuf, sizeof(struct ble_mbuf_hdr)); if (!rxd->om) { - /* not much we can do here... */ + /* TODO not much we can do here... */ assert(0); } @@ -423,6 +433,15 @@ nrf5340_ble_hci_trans_rx(int channel, void *user_data) } } +int +ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg) +{ + nrf5340_ble_hci_pool_acl.mpe_put_cb = cb; + nrf5340_ble_hci_pool_acl.mpe_put_arg = arg; + + return 0; +} + void nrf5340_ble_hci_init(void) { @@ -430,13 +449,14 @@ nrf5340_ble_hci_init(void) SYSINIT_ASSERT_ACTIVE(); - rc = os_mempool_init(&nrf5340_ble_hci_pool_acl, MYNEWT_VAL(BLE_ACL_BUF_COUNT), - POOL_ACL_BLOCK_SIZE, nrf5340_ble_hci_pool_acl_buf, - "nrf5340_ble_hci_pool_acl"); + rc = os_mempool_ext_init(&nrf5340_ble_hci_pool_acl, + MYNEWT_VAL(BLE_ACL_BUF_COUNT), POOL_ACL_BLOCK_SIZE, + nrf5340_ble_hci_pool_acl_buf, + "nrf5340_ble_hci_pool_acl"); SYSINIT_PANIC_ASSERT(rc == 0); rc = os_mbuf_pool_init(&nrf5340_ble_hci_pool_acl_mbuf, - &nrf5340_ble_hci_pool_acl, POOL_ACL_BLOCK_SIZE, + &nrf5340_ble_hci_pool_acl.mpe_mp, POOL_ACL_BLOCK_SIZE, MYNEWT_VAL(BLE_ACL_BUF_COUNT)); SYSINIT_PANIC_ASSERT(rc == 0); @@ -454,5 +474,11 @@ nrf5340_ble_hci_init(void) "nrf5340_ble_hci_pool_evt_lo"); SYSINIT_PANIC_ASSERT(rc == 0); + rc = os_mempool_init(&nrf5340_ble_hci_pool_cmd_mempool, + HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ, + nrf5340_ble_hci_pool_cmd_mempool_buf, + "nrf5340_ble_hci_pool_cmd_mempool"); + SYSINIT_PANIC_ASSERT(rc == 0); + ipc_nrf5340_recv(IPC_RX_CHANNEL, nrf5340_ble_hci_trans_rx, NULL); } From 68c259464a36b0609fe0e0fbdf13efa160d9820c Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Mon, 19 Apr 2021 17:26:39 +0200 Subject: [PATCH 016/306] host/gap: fix doxygen for ble_gap_ext_disc() Documentation for the parameters `filter_duplicates` and `filter_policy` for ble_gap_ext_disc() was missing. --- nimble/host/include/host/ble_gap.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index ec795f0e21..fa7ee562df 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -1592,6 +1592,16 @@ int ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms, * its last Scan Duration until it begins the * subsequent Scan Duration. Specify 0 to scan * continuously. Units are 1.28 second. + * @param filter_duplicates Set to enable packet filtering in the + * controller + * @param filter_policy Set the used filter policy. Valid values are: + * - BLE_HCI_SCAN_FILT_NO_WL + * - BLE_HCI_SCAN_FILT_USE_WL + * - BLE_HCI_SCAN_FILT_NO_WL_INITA + * - BLE_HCI_SCAN_FILT_USE_WL_INITA + * - BLE_HCI_SCAN_FILT_MAX + * This parameter is ignored unless + * @p filter_duplicates is set. * @param limited If limited discovery procedure should be used. * @param uncoded_params Additional arguments specifying the particulars * of the discovery procedure for uncoded PHY. From 6bb3c0c66839b6422e7eeb69f56733dcaa4b656b Mon Sep 17 00:00:00 2001 From: Prasad Alatkar Date: Wed, 14 Apr 2021 20:55:41 +0530 Subject: [PATCH 017/306] nimble/host: Fix MITM vulnerability during public key exchange in secure connection --- nimble/host/src/ble_sm_sc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nimble/host/src/ble_sm_sc.c b/nimble/host/src/ble_sm_sc.c index 7fae5b1c94..162a4a2ba1 100644 --- a/nimble/host/src/ble_sm_sc.c +++ b/nimble/host/src/ble_sm_sc.c @@ -612,6 +612,13 @@ ble_sm_sc_public_key_rx(uint16_t conn_handle, struct os_mbuf **om, } cmd = (struct ble_sm_public_key *)(*om)->om_data; + /* Check if the peer public key is same as our generated public key. + * Return fail if the public keys match. */ + if (memcmp(cmd, ble_sm_sc_pub_key, 64) == 0) { + res->enc_cb = 1; + res->sm_err = BLE_SM_ERR_AUTHREQ; + return; + } ble_hs_lock(); proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PUBLIC_KEY, -1, From b106ddbdd4ddbdefae8cef2692cf2ea268fed870 Mon Sep 17 00:00:00 2001 From: Prasad Alatkar Date: Mon, 3 May 2021 20:20:14 +0530 Subject: [PATCH 018/306] nimble/test: Add SC unit test to flag error on same public key --- nimble/host/test/src/ble_sm_sc_test.c | 606 ++++++++++++++++++++++++ nimble/host/test/src/ble_sm_test_util.c | 106 ++++- nimble/host/test/src/ble_sm_test_util.h | 1 + 3 files changed, 708 insertions(+), 5 deletions(-) diff --git a/nimble/host/test/src/ble_sm_sc_test.c b/nimble/host/test/src/ble_sm_sc_test.c index c3d195503c..cd453e023c 100644 --- a/nimble/host/test/src/ble_sm_sc_test.c +++ b/nimble/host/test/src/ble_sm_sc_test.c @@ -2285,6 +2285,612 @@ TEST_CASE_SELF(ble_sm_sc_us_pk_iio2_rio4_b1_iat0_rat0_ik7_rk5) ble_hs_test_util_assert_mbufs_freed(NULL); } +/** + * Secure connections pairing + * Master: us + * Pair algorithm: passkey entry + * Initiator IO capabilities: 2 + * Responder IO capabilities: 4 + * Bonding: true + * Initiator address type: 0 + * Responder address type: 0 + * Initiator key distribution: 7 + * Responder key distribution: 5 + * Peer responds with same public key + */ +TEST_CASE_SELF(ble_sm_sc_us_pk_iio2_rio4_b1_iat0_rat0_ik7_rk5_peer_same_pk) { + struct ble_sm_test_params params; + + params = (struct ble_sm_test_params) { + .init_id_addr = { + 0x01, 0x01, 0x01, 0x07, 0x08, 0x01, + }, + .resp_id_addr = { + 0xca, 0x61, 0xa0, 0x67, 0x94, 0xe0, + }, + .pair_req = { + .io_cap = 0x02, + .oob_data_flag = 0x00, + .authreq = 0x0d, + .max_enc_key_size = 0x10, + .init_key_dist = 0x07, + .resp_key_dist = 0x07, + }, + .pair_rsp = { + .io_cap = 0x04, + .oob_data_flag = 0x00, + .authreq = 0x0d, + .max_enc_key_size = 0x10, + .init_key_dist = 0x07, + .resp_key_dist = 0x05, + }, + .our_priv_key = { + 0xb1, 0x6b, 0x4f, 0x81, 0xbc, 0xe3, 0x60, 0x9e, + 0x00, 0x20, 0xf1, 0x73, 0x3e, 0xfb, 0xcc, 0x6e, + 0x8c, 0xb6, 0xd2, 0x51, 0xd9, 0x36, 0x8a, 0x6d, + 0xca, 0x8c, 0xd7, 0xbe, 0x96, 0x03, 0xdf, 0xd6, + }, + .public_key_req = { + .x = { + 0xe5, 0x0f, 0x02, 0x0a, 0x37, 0x90, 0x94, 0x5a, + 0x06, 0x21, 0xf7, 0xbc, 0xd5, 0xbe, 0xb9, 0x24, + 0x8a, 0x35, 0xfd, 0xf8, 0x5e, 0xe2, 0x70, 0xd5, + 0x5a, 0xe8, 0xe7, 0xdd, 0x13, 0x90, 0xeb, 0xd4, + }, + .y = { + 0x41, 0xc8, 0x51, 0x1a, 0x25, 0x44, 0x01, 0x53, + 0x42, 0x74, 0x07, 0x9c, 0x18, 0xe6, 0x3b, 0x8a, + 0xce, 0x7a, 0x37, 0x1f, 0x18, 0x5c, 0x02, 0x7c, + 0x67, 0x16, 0xf5, 0x30, 0x2b, 0x31, 0xa9, 0xc7, + }, + }, + .public_key_rsp = { + .x = { + 0xe5, 0x0f, 0x02, 0x0a, 0x37, 0x90, 0x94, 0x5a, + 0x06, 0x21, 0xf7, 0xbc, 0xd5, 0xbe, 0xb9, 0x24, + 0x8a, 0x35, 0xfd, 0xf8, 0x5e, 0xe2, 0x70, 0xd5, + 0x5a, 0xe8, 0xe7, 0xdd, 0x13, 0x90, 0xeb, 0xd4, + }, + .y = { + 0x41, 0xc8, 0x51, 0x1a, 0x25, 0x44, 0x01, 0x53, + 0x42, 0x74, 0x07, 0x9c, 0x18, 0xe6, 0x3b, 0x8a, + 0xce, 0x7a, 0x37, 0x1f, 0x18, 0x5c, 0x02, 0x7c, + 0x67, 0x16, 0xf5, 0x30, 0x2b, 0x31, 0xa9, 0xc7, + }, + }, + .confirm_req[0] = { + .value = { + 0x55, 0x2c, 0xaa, 0x41, 0x59, 0x42, 0x4d, 0xfe, + 0x47, 0x74, 0xcd, 0x2b, 0x11, 0xab, 0x21, 0xe6, + }, + }, + .confirm_rsp[0] = { + .value = { + 0x6a, 0x3c, 0x45, 0xf5, 0xb2, 0xe2, 0x04, 0x30, + 0xde, 0xd6, 0x3c, 0x6d, 0x85, 0x00, 0x00, 0x2c, + }, + }, + .random_req[0] = { + .value = { + 0x78, 0x06, 0x04, 0x60, 0x76, 0xe9, 0xc4, 0x5a, + 0xfb, 0x34, 0x44, 0xae, 0x45, 0xa0, 0x84, 0xde, + }, + }, + .random_rsp[0] = { + .value = { + 0x91, 0xc8, 0xfd, 0x1b, 0xb2, 0x85, 0x08, 0x76, + 0xd3, 0xf1, 0xc4, 0xa0, 0xfa, 0x92, 0x8c, 0x94, + }, + }, + .confirm_req[1] = { + .value = { + 0xb1, 0x2f, 0x68, 0x35, 0xa1, 0xa5, 0x84, 0xb1, + 0x4f, 0x1a, 0xb1, 0xb5, 0xf0, 0xb2, 0xbe, 0x61, + }, + }, + .confirm_rsp[1] = { + .value = { + 0x07, 0xd8, 0x43, 0x74, 0xe8, 0x42, 0xf3, 0xf1, + 0x87, 0x3d, 0x9e, 0x92, 0xea, 0x33, 0xe8, 0x54, + }, + }, + .random_req[1] = { + .value = { + 0x4c, 0xb7, 0xcc, 0x6d, 0x90, 0x9f, 0x1e, 0x2d, + 0x9d, 0x1e, 0x52, 0xa7, 0xe0, 0x0c, 0x7b, 0xf7, + }, + }, + .random_rsp[1] = { + .value = { + 0x5c, 0x32, 0x82, 0xc8, 0x76, 0x17, 0x3b, 0x18, + 0x66, 0xda, 0xbf, 0xc3, 0x13, 0x49, 0x05, 0xfb, + }, + }, + .confirm_req[2] = { + .value = { + 0x27, 0x61, 0x4d, 0x04, 0x64, 0xa9, 0x58, 0xf1, + 0xe0, 0xf9, 0xe5, 0x78, 0x0b, 0x54, 0x89, 0x0a, + }, + }, + .confirm_rsp[2] = { + .value = { + 0xe4, 0x8f, 0xdb, 0xc8, 0x35, 0xed, 0x4e, 0x7d, + 0xbc, 0x92, 0x7f, 0x58, 0x02, 0xaa, 0xbf, 0x6b, + }, + }, + .random_req[2] = { + .value = { + 0xfe, 0x85, 0x08, 0xe0, 0x35, 0x90, 0x13, 0xa9, + 0xd3, 0xcf, 0xb6, 0x6d, 0x36, 0xaf, 0xbd, 0x59, + }, + }, + .random_rsp[2] = { + .value = { + 0x47, 0x40, 0x8e, 0x97, 0xe3, 0xfe, 0x8f, 0x52, + 0x29, 0x5e, 0x6b, 0x44, 0xdf, 0x0d, 0x60, 0xf4, + }, + }, + .confirm_req[3] = { + .value = { + 0xac, 0xab, 0x13, 0x7c, 0x1a, 0x6e, 0x7a, 0xdb, + 0xf6, 0xe8, 0x72, 0x9f, 0xc5, 0xc3, 0x99, 0x1b, + }, + }, + .confirm_rsp[3] = { + .value = { + 0x79, 0xf2, 0xd1, 0x89, 0x5e, 0xa5, 0xa2, 0x90, + 0xee, 0x25, 0x36, 0x81, 0x5a, 0x87, 0x20, 0x82, + }, + }, + .random_req[3] = { + .value = { + 0xd4, 0x46, 0xa0, 0xc4, 0x3d, 0xae, 0x22, 0x06, + 0xaf, 0x5d, 0x93, 0x96, 0xb7, 0x06, 0xc3, 0x61, + }, + }, + .random_rsp[3] = { + .value = { + 0x5f, 0x81, 0x97, 0x8b, 0x52, 0x87, 0x1c, 0x67, + 0xe0, 0x04, 0xcc, 0x50, 0xd9, 0x2b, 0x16, 0xb5, + }, + }, + .confirm_req[4] = { + .value = { + 0x6c, 0x51, 0xc3, 0x61, 0x77, 0x7f, 0xf1, 0x05, + 0x9e, 0x0f, 0xba, 0xfd, 0x32, 0x02, 0x09, 0x45, + }, + }, + .confirm_rsp[4] = { + .value = { + 0x54, 0xe5, 0x24, 0x81, 0x62, 0x68, 0xe2, 0x45, + 0x86, 0x2c, 0x11, 0x28, 0x15, 0xa8, 0x8e, 0x5b, + }, + }, + .random_req[4] = { + .value = { + 0xbb, 0x29, 0x3a, 0xba, 0xe6, 0x4f, 0x06, 0xcf, + 0xa3, 0x13, 0x27, 0xf2, 0xcb, 0xe4, 0xd2, 0xe6, + }, + }, + .random_rsp[4] = { + .value = { + 0x50, 0xba, 0xd0, 0x0e, 0x26, 0xab, 0x04, 0xf8, + 0xa2, 0x03, 0x1e, 0x63, 0x9a, 0xf7, 0x15, 0xdc, + }, + }, + .confirm_req[5] = { + .value = { + 0x12, 0x3e, 0xfe, 0x5a, 0xb1, 0x09, 0x6f, 0x17, + 0xb7, 0x77, 0x7e, 0x65, 0x88, 0xd4, 0x95, 0x56, + }, + }, + .confirm_rsp[5] = { + .value = { + 0xc6, 0x9b, 0xac, 0xde, 0x7e, 0x03, 0x7a, 0xd3, + 0xf1, 0xff, 0x3c, 0x4f, 0x4a, 0x85, 0xba, 0x73, + }, + }, + .random_req[5] = { + .value = { + 0x17, 0xd5, 0x5e, 0x69, 0x30, 0x2c, 0x1f, 0x01, + 0x87, 0x9c, 0xd6, 0xd2, 0xe4, 0x48, 0x8c, 0x84, + }, + }, + .random_rsp[5] = { + .value = { + 0x9d, 0x54, 0x83, 0x4a, 0xcd, 0x93, 0x7c, 0x1e, + 0x5b, 0xaf, 0xd2, 0x66, 0x8c, 0x2d, 0xaa, 0xc3, + }, + }, + .confirm_req[6] = { + .value = { + 0xdc, 0x24, 0x69, 0xa8, 0xd3, 0xa9, 0x17, 0x11, + 0x08, 0x37, 0x1a, 0x1e, 0x92, 0x03, 0xee, 0x36, + }, + }, + .confirm_rsp[6] = { + .value = { + 0x98, 0xf8, 0x72, 0x71, 0x99, 0xa0, 0xbd, 0xcd, + 0xb1, 0x97, 0x4c, 0x8a, 0xb8, 0xa8, 0x1a, 0x52, + }, + }, + .random_req[6] = { + .value = { + 0xbf, 0xb1, 0x8e, 0xa5, 0x14, 0xe3, 0xeb, 0x9e, + 0x29, 0x27, 0xe0, 0x19, 0xb1, 0xb2, 0x5c, 0xfe, + }, + }, + .random_rsp[6] = { + .value = { + 0xae, 0x8a, 0x92, 0x78, 0x53, 0x7b, 0xdb, 0x8c, + 0xec, 0x3a, 0x99, 0x2b, 0x94, 0xf1, 0x17, 0xfe, + }, + }, + .confirm_req[7] = { + .value = { + 0xcf, 0xaf, 0x70, 0x73, 0x53, 0x65, 0x89, 0x57, + 0x36, 0x98, 0xd2, 0x28, 0x86, 0x79, 0xfe, 0x85, + }, + }, + .confirm_rsp[7] = { + .value = { + 0x0d, 0x2d, 0x77, 0x8a, 0x21, 0x11, 0xd9, 0x61, + 0x9f, 0x80, 0x32, 0x8a, 0x32, 0x09, 0x42, 0x42, + }, + }, + .random_req[7] = { + .value = { + 0x8b, 0xd2, 0x53, 0xcd, 0x96, 0xd1, 0x14, 0xb5, + 0xea, 0x17, 0xb1, 0xa3, 0xa8, 0xfc, 0x3c, 0x2b, + }, + }, + .random_rsp[7] = { + .value = { + 0xc2, 0x4f, 0x84, 0x60, 0x54, 0x79, 0x16, 0xed, + 0x1a, 0x6e, 0x78, 0xa0, 0x99, 0x58, 0xf2, 0x94, + }, + }, + .confirm_req[8] = { + .value = { + 0x9a, 0x4c, 0xbc, 0x9c, 0x55, 0x15, 0xa2, 0x4f, + 0xa2, 0x5d, 0x3b, 0xa7, 0x43, 0xb3, 0x9c, 0x63, + }, + }, + .confirm_rsp[8] = { + .value = { + 0xa3, 0xb1, 0x88, 0xa5, 0x70, 0xca, 0xa3, 0xa9, + 0x67, 0x2a, 0xac, 0x99, 0x5e, 0x61, 0x68, 0xa0, + }, + }, + .random_req[8] = { + .value = { + 0xcf, 0xcf, 0x5b, 0x94, 0xe0, 0xb2, 0x9d, 0x5a, + 0x86, 0x71, 0x45, 0xce, 0xd9, 0xce, 0x13, 0xba, + }, + }, + .random_rsp[8] = { + .value = { + 0x10, 0x96, 0x8a, 0x50, 0xa4, 0xd0, 0xaa, 0x5f, + 0xd6, 0x32, 0xdb, 0x09, 0x7e, 0x22, 0x96, 0x42, + }, + }, + .confirm_req[9] = { + .value = { + 0xf0, 0x90, 0x61, 0x25, 0x04, 0x29, 0x4f, 0xb6, + 0x8b, 0xd5, 0x73, 0x49, 0xbd, 0xf7, 0x9b, 0xe7, + }, + }, + .confirm_rsp[9] = { + .value = { + 0x5b, 0xe6, 0xb4, 0x3f, 0x1b, 0x77, 0x12, 0x75, + 0x84, 0x94, 0xc6, 0x07, 0xfa, 0xa1, 0x41, 0x94, + }, + }, + .random_req[9] = { + .value = { + 0x3d, 0x1a, 0xa3, 0x95, 0xec, 0x72, 0x84, 0xf4, + 0xc5, 0xcd, 0xaa, 0x48, 0xe9, 0x0c, 0x0f, 0xe3, + }, + }, + .random_rsp[9] = { + .value = { + 0x8a, 0x5a, 0x53, 0xfc, 0x07, 0x52, 0x01, 0xb9, + 0xe9, 0x2d, 0xe7, 0x9d, 0x8c, 0x7c, 0xc7, 0xb3, + }, + }, + .confirm_req[10] = { + .value = { + 0xe7, 0x8e, 0xc5, 0x08, 0x7f, 0x7e, 0xb8, 0xdc, + 0x05, 0x88, 0x3a, 0x92, 0x5a, 0xf5, 0x9b, 0xa9, + }, + }, + .confirm_rsp[10] = { + .value = { + 0xf7, 0xa2, 0xb6, 0xec, 0xcd, 0xef, 0xcb, 0xb7, + 0x6f, 0xc3, 0xac, 0x17, 0xe2, 0xfd, 0xfa, 0x42, + }, + }, + .random_req[10] = { + .value = { + 0x0d, 0xd1, 0xa2, 0x1d, 0xff, 0x74, 0xc5, 0x99, + 0xe0, 0x67, 0x07, 0x99, 0x95, 0x75, 0x39, 0x76, + }, + }, + .random_rsp[10] = { + .value = { + 0x2f, 0x13, 0xd1, 0x59, 0xfe, 0x20, 0x60, 0xf0, + 0x02, 0x0c, 0xea, 0x79, 0xd7, 0x40, 0x86, 0x85, + }, + }, + .confirm_req[11] = { + .value = { + 0x8b, 0x57, 0x87, 0xdd, 0xb1, 0xcc, 0x2d, 0x65, + 0xc1, 0xba, 0xac, 0x88, 0x48, 0x23, 0xda, 0xe7, + }, + }, + .confirm_rsp[11] = { + .value = { + 0xb3, 0xc4, 0x2e, 0xea, 0x33, 0xaf, 0x12, 0x9c, + 0xb5, 0xab, 0xa1, 0x95, 0x30, 0xca, 0x46, 0x48, + }, + }, + .random_req[11] = { + .value = { + 0x35, 0x57, 0xcd, 0xd5, 0xd2, 0xf8, 0xd7, 0xf2, + 0x7b, 0xe3, 0xd7, 0xba, 0x31, 0xa5, 0xca, 0xfd, + }, + }, + .random_rsp[11] = { + .value = { + 0xe2, 0x3b, 0x20, 0xbe, 0xec, 0xa5, 0x34, 0x3b, + 0x76, 0x23, 0x53, 0x28, 0x36, 0xc4, 0x60, 0x13, + }, + }, + .confirm_req[12] = { + .value = { + 0xc9, 0xfe, 0x03, 0x49, 0xe4, 0xff, 0x7e, 0xf7, + 0x00, 0xd1, 0x2b, 0x13, 0xb1, 0x15, 0x6e, 0x92, + }, + }, + .confirm_rsp[12] = { + .value = { + 0xbc, 0xa2, 0xf2, 0x03, 0x5c, 0xfd, 0x20, 0x7b, + 0xd0, 0x1f, 0xd6, 0x50, 0xec, 0xc6, 0x7b, 0x31, + }, + }, + .random_req[12] = { + .value = { + 0x04, 0x50, 0xea, 0xb8, 0xca, 0x36, 0x1a, 0x61, + 0x92, 0xed, 0xa0, 0x67, 0x78, 0x15, 0x10, 0xb5, + }, + }, + .random_rsp[12] = { + .value = { + 0x0c, 0x8e, 0x9d, 0x7b, 0x9d, 0x7e, 0xda, 0x23, + 0xbb, 0x61, 0xd9, 0xff, 0x46, 0x77, 0x33, 0x1b, + }, + }, + .confirm_req[13] = { + .value = { + 0x9a, 0xff, 0xd6, 0xe5, 0x1a, 0xc3, 0xd3, 0x37, + 0x34, 0xeb, 0x3e, 0x3a, 0x8e, 0x0b, 0x86, 0xb4, + }, + }, + .confirm_rsp[13] = { + .value = { + 0xf6, 0x32, 0x19, 0xb4, 0x08, 0x6b, 0x8a, 0x0f, + 0xc9, 0x9c, 0x1b, 0x68, 0xb8, 0xa0, 0xd0, 0xc9, + }, + }, + .random_req[13] = { + .value = { + 0x86, 0xeb, 0x5c, 0xf9, 0x33, 0x54, 0x7d, 0xe4, + 0xa4, 0xe2, 0xe1, 0xf6, 0x6b, 0xea, 0x34, 0xed, + }, + }, + .random_rsp[13] = { + .value = { + 0xad, 0x53, 0xa0, 0x6e, 0xde, 0x1d, 0xda, 0x99, + 0x31, 0x45, 0xe5, 0x3a, 0x73, 0xa1, 0x5e, 0xe1, + }, + }, + .confirm_req[14] = { + .value = { + 0x93, 0xd4, 0xe0, 0xaa, 0x0c, 0x91, 0xba, 0xde, + 0xc9, 0x5c, 0x68, 0xb0, 0xce, 0xb6, 0x84, 0xcd, + }, + }, + .confirm_rsp[14] = { + .value = { + 0x85, 0xc7, 0x05, 0x02, 0x21, 0x9d, 0x4c, 0x4c, + 0x16, 0xf7, 0x8f, 0x7b, 0xaa, 0xb4, 0x8f, 0x37, + }, + }, + .random_req[14] = { + .value = { + 0x84, 0xfd, 0xf1, 0x39, 0x1a, 0x9a, 0xa5, 0xb8, + 0x49, 0xc0, 0x66, 0xdc, 0x33, 0x71, 0x32, 0x87, + }, + }, + .random_rsp[14] = { + .value = { + 0x5d, 0xaf, 0x38, 0xcd, 0xb5, 0x83, 0xaa, 0xa0, + 0xab, 0x30, 0x82, 0xed, 0x6f, 0xd2, 0x75, 0xe7, + }, + }, + .confirm_req[15] = { + .value = { + 0x88, 0x12, 0xe8, 0x89, 0xd4, 0x52, 0x6d, 0xac, + 0x61, 0x2a, 0x85, 0x85, 0x1e, 0x9c, 0x82, 0x21, + }, + }, + .confirm_rsp[15] = { + .value = { + 0xc1, 0xe9, 0xcd, 0x21, 0x29, 0x6a, 0x78, 0xe4, + 0x7b, 0x7d, 0x73, 0x25, 0x9e, 0x9b, 0x95, 0x8b, + }, + }, + .random_req[15] = { + .value = { + 0x95, 0x87, 0x9d, 0x5a, 0x10, 0x14, 0xa0, 0xdf, + 0x5e, 0x02, 0x22, 0x39, 0x23, 0xc9, 0xbc, 0xba, + }, + }, + .random_rsp[15] = { + .value = { + 0x1b, 0x91, 0xe2, 0xdf, 0xca, 0xfe, 0x2b, 0x61, + 0x33, 0x8c, 0x83, 0xbf, 0xcf, 0xc3, 0x72, 0xcc, + }, + }, + .confirm_req[16] = { + .value = { + 0xce, 0xc9, 0x68, 0xf7, 0xea, 0x41, 0x18, 0x5c, + 0x16, 0x6a, 0x98, 0x13, 0x0c, 0x10, 0xc2, 0xa3, + }, + }, + .confirm_rsp[16] = { + .value = { + 0x97, 0x73, 0xc9, 0x72, 0x68, 0x99, 0x63, 0xed, + 0x81, 0x3b, 0x5c, 0xee, 0x37, 0xfc, 0xca, 0xae, + }, + }, + .random_req[16] = { + .value = { + 0x5b, 0x85, 0xb0, 0x1b, 0xc3, 0xde, 0x18, 0xba, + 0xc1, 0xc7, 0x89, 0x99, 0xfe, 0xcd, 0xdb, 0x6a, + }, + }, + .random_rsp[16] = { + .value = { + 0x5e, 0x1a, 0xcb, 0xbc, 0xda, 0x41, 0x06, 0x5a, + 0x14, 0x34, 0x3a, 0xb1, 0xa1, 0x6f, 0xb2, 0xd8, + }, + }, + .confirm_req[17] = { + .value = { + 0x1d, 0x59, 0x8a, 0xb0, 0x19, 0xe5, 0xff, 0x45, + 0xb6, 0xc3, 0x33, 0x64, 0xd1, 0x6e, 0xee, 0xdd, + }, + }, + .confirm_rsp[17] = { + .value = { + 0x4c, 0x9b, 0xe8, 0x68, 0x52, 0x34, 0xef, 0xe1, + 0x84, 0xbd, 0x37, 0x85, 0x53, 0x0d, 0xd5, 0xc1, + }, + }, + .random_req[17] = { + .value = { + 0xa6, 0xf7, 0x97, 0x18, 0x9a, 0x3e, 0x9d, 0xcf, + 0x91, 0xa3, 0xa3, 0x8e, 0xda, 0x8f, 0x8f, 0x90, + }, + }, + .random_rsp[17] = { + .value = { + 0x94, 0x10, 0x19, 0x17, 0x8d, 0x0a, 0x72, 0xfd, + 0x24, 0x9d, 0xfd, 0x37, 0x4e, 0xdf, 0x4c, 0x30, + }, + }, + .confirm_req[18] = { + .value = { + 0xfc, 0x64, 0x8a, 0x8b, 0x37, 0x17, 0x90, 0x6d, + 0x25, 0x0e, 0xc6, 0x18, 0xc9, 0xc9, 0xc2, 0x2a, + }, + }, + .confirm_rsp[18] = { + .value = { + 0x50, 0x98, 0x86, 0xf5, 0xc0, 0xda, 0x45, 0x2d, + 0xea, 0xc8, 0x9d, 0x28, 0x04, 0xd8, 0x73, 0x6f, + }, + }, + .random_req[18] = { + .value = { + 0x13, 0x10, 0x38, 0xe8, 0x17, 0x6d, 0x72, 0xd5, + 0x94, 0xaf, 0xed, 0x4f, 0x23, 0xa0, 0x41, 0xfc, + }, + }, + .random_rsp[18] = { + .value = { + 0xdf, 0xed, 0xf7, 0x08, 0xce, 0x64, 0xbc, 0x11, + 0x41, 0x7a, 0xd9, 0xf7, 0x4a, 0xd9, 0x4a, 0x15, + }, + }, + .confirm_req[19] = { + .value = { + 0xae, 0x24, 0x8f, 0xdf, 0xb0, 0x57, 0xc4, 0x9c, + 0xe6, 0xae, 0x9b, 0xc2, 0x4d, 0x3d, 0x1c, 0xcb, + }, + }, + .confirm_rsp[19] = { + .value = { + 0xcc, 0x5c, 0xa3, 0xbe, 0xd7, 0x83, 0xee, 0x60, + 0x80, 0xff, 0x5f, 0x1a, 0x07, 0xbf, 0x4c, 0x33, + }, + }, + .random_req[19] = { + .value = { + 0x93, 0xc3, 0x62, 0x06, 0xcb, 0xe5, 0xb0, 0x01, + 0x02, 0x18, 0xa2, 0x50, 0x4c, 0x73, 0xa2, 0x27, + }, + }, + .random_rsp[19] = { + .value = { + 0x11, 0x2a, 0xd3, 0x06, 0x28, 0x9c, 0xdf, 0x73, + 0xa5, 0xa4, 0xe5, 0x1e, 0x07, 0xcf, 0xee, 0x71, + }, + }, + .dhkey_check_req = { + .value = { + 0x73, 0xa0, 0x40, 0x58, 0x78, 0x20, 0x5f, 0x2c, + 0xf4, 0x19, 0x23, 0xa8, 0x74, 0xbd, 0xc2, 0x3e, + }, + }, + .dhkey_check_rsp = { + .value = { + 0x5a, 0x30, 0xbc, 0xce, 0xec, 0xdf, 0xf0, 0x32, + 0x3c, 0x18, 0xa3, 0xd3, 0x3f, 0x20, 0x87, 0x10, + }, + }, + .sign_info_req = { + .sig_key = { + 0x2e, 0x81, 0x09, 0xde, 0x32, 0xc5, 0x28, 0x34, + 0xe1, 0x45, 0x4a, 0x35, 0x49, 0xef, 0xa2, 0xed, + }, + }, + .id_info_rsp = { + .irk = { + 0xef, 0x8d, 0xe2, 0x16, 0x4f, 0xec, 0x43, 0x0d, + 0xbf, 0x5b, 0xdd, 0x34, 0xc0, 0x53, 0x1e, 0xb8, + }, + }, + .id_addr_info_rsp = { + .addr_type = 0, + .bd_addr = { + 0x01, 0x01, 0x01, 0x07, 0x08, 0x01, + }, + }, + .sign_info_rsp = { + .sig_key = { + 0x90, 0x3d, 0x26, 0x65, 0xc1, 0xd1, 0x5a, 0x9d, + 0xda, 0xab, 0x0d, 0x00, 0x05, 0x0e, 0x6c, 0x5d, + }, + }, + .ltk = { + 0xf1, 0x41, 0x1a, 0x5b, 0x60, 0xc1, 0x43, 0xc6, + 0x80, 0x34, 0x5e, 0x7f, 0xd8, 0x0c, 0x75, 0xdc, + }, + .pair_alg = BLE_SM_PAIR_ALG_PASSKEY, + .authenticated = 1, + .passkey_info = { + .passkey = { + .action = BLE_SM_IOACT_INPUT, + .passkey = 516645, + }, + }, + }; + ble_sm_test_util_us_sc_bad(¶ms); + + ble_hs_test_util_assert_mbufs_freed(NULL); +} /** * Secure connections pairing * Master: us diff --git a/nimble/host/test/src/ble_sm_test_util.c b/nimble/host/test/src/ble_sm_test_util.c index 6170371f51..bad473f178 100644 --- a/nimble/host/test/src/ble_sm_test_util.c +++ b/nimble/host/test/src/ble_sm_test_util.c @@ -844,6 +844,35 @@ ble_sm_test_util_rx_public_key(uint16_t conn_handle, TEST_ASSERT_FATAL(rc == 0); } +static void +ble_sm_test_util_rx_public_key_bad(uint16_t conn_handle, + struct ble_sm_public_key *cmd) +{ + struct hci_data_hdr hci_hdr; + struct os_mbuf *om; + void *v; + int payload_len; + int rc; + + hci_hdr = BLE_SM_TEST_UTIL_HCI_HDR( + 2, BLE_HCI_PB_FIRST_FLUSH, + BLE_L2CAP_HDR_SZ + sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_public_key)); + + om = ble_hs_mbuf_l2cap_pkt(); + TEST_ASSERT_FATAL(om != NULL); + + payload_len = sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_public_key); + + v = os_mbuf_extend(om, payload_len); + TEST_ASSERT_FATAL(v != NULL); + + ble_sm_public_key_write(v, payload_len, cmd); + + rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SM, + &hci_hdr, om); + TEST_ASSERT_FATAL(rc != 0); +} + static void ble_sm_test_util_rx_dhkey_check(uint16_t conn_handle, struct ble_sm_dhkey_check *cmd, @@ -2567,6 +2596,52 @@ ble_sm_test_util_us_sc_good_once_no_init( ble_hs_test_util_conn_disconnect(2); } +static void +ble_sm_test_util_us_sc_bad_once_no_init(struct ble_sm_test_params *params, + struct ble_hs_conn *conn, + struct ble_sm_test_util_entity *our_entity, + struct ble_sm_test_util_entity *peer_entity) +{ + int rc; + + TEST_ASSERT(!conn->bhc_sec_state.encrypted); + TEST_ASSERT(ble_sm_num_procs() == 0); + + ble_hs_test_util_hci_ack_set( + ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_START_ENCRYPT), 0); + if (params->sec_req.authreq != 0) { + ble_sm_test_util_rx_sec_req(2, ¶ms->sec_req, 0); + } else { + /* Initiate the pairing procedure. */ + rc = ble_gap_security_initiate(2); + TEST_ASSERT_FATAL(rc == 0); + } + + /* Ensure we sent the expected pair request. */ + ble_sm_test_util_verify_tx_pair_req(our_entity->pair_cmd); + TEST_ASSERT(!conn->bhc_sec_state.encrypted); + TEST_ASSERT(ble_sm_num_procs() == 1); + ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action); + + /* Receive a pair response from the peer. */ + ble_sm_test_util_rx_pair_rsp(2, peer_entity->pair_cmd, 0); + TEST_ASSERT(!conn->bhc_sec_state.encrypted); + TEST_ASSERT(ble_sm_num_procs() == 1); + ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action); + + /* Ensure we sent the expected public key. */ + ble_sm_test_util_verify_tx_public_key(our_entity->public_key); + TEST_ASSERT(!conn->bhc_sec_state.encrypted); + TEST_ASSERT(ble_sm_num_procs() == 1); + ble_sm_test_util_io_inject_bad(2, params->passkey_info.passkey.action); + + /* Receive a wrong public key from the peer. */ + ble_sm_test_util_rx_public_key_bad(2, peer_entity->public_key); + TEST_ASSERT(!conn->bhc_sec_state.encrypted); + TEST_ASSERT(ble_sm_num_procs() == 1); +} + static void ble_sm_test_util_us_sc_good_once(struct ble_sm_test_params *params) { @@ -2579,6 +2654,17 @@ ble_sm_test_util_us_sc_good_once(struct ble_sm_test_params *params) params, conn, &our_entity, &peer_entity); } +static void +ble_sm_test_util_us_sc_bad_once(struct ble_sm_test_params *params) +{ + struct ble_sm_test_util_entity peer_entity; + struct ble_sm_test_util_entity our_entity; + struct ble_hs_conn *conn; + + ble_sm_test_util_init_good(params, 1, &conn, &our_entity, &peer_entity); + ble_sm_test_util_us_sc_bad_once_no_init( + params, conn, &our_entity, &peer_entity); +} void ble_sm_test_util_us_sc_good(struct ble_sm_test_params *params) { @@ -2610,12 +2696,22 @@ ble_sm_test_util_us_sc_good(struct ble_sm_test_params *params) TEST_ASSERT(ble_hs_test_util_num_peer_secs() == 0); } +void +ble_sm_test_util_us_sc_bad(struct ble_sm_test_params *params) +{ + /*** We are master. */ + + /* We initiate pairing. */ + params->passkey_info.io_before_rx = 0; + params->sec_req.authreq = 0; + ble_sm_test_util_us_sc_bad_once(params); +} + static void -ble_sm_test_util_peer_sc_good_once_no_init( - struct ble_sm_test_params *params, - struct ble_hs_conn *conn, - struct ble_sm_test_util_entity *our_entity, - struct ble_sm_test_util_entity *peer_entity) +ble_sm_test_util_peer_sc_good_once_no_init(struct ble_sm_test_params *params, + struct ble_hs_conn *conn, + struct ble_sm_test_util_entity *our_entity, + struct ble_sm_test_util_entity *peer_entity) { int num_iters; int rc; diff --git a/nimble/host/test/src/ble_sm_test_util.h b/nimble/host/test/src/ble_sm_test_util.h index d8629b60c0..d9aa3805c7 100644 --- a/nimble/host/test/src/ble_sm_test_util.h +++ b/nimble/host/test/src/ble_sm_test_util.h @@ -119,6 +119,7 @@ void ble_sm_test_util_peer_lgcy_good(struct ble_sm_test_params *params); void ble_sm_test_util_peer_bonding_bad(uint16_t ediv, uint64_t rand_num); void ble_sm_test_util_peer_sc_good(struct ble_sm_test_params *params); void ble_sm_test_util_us_sc_good(struct ble_sm_test_params *params); +void ble_sm_test_util_us_sc_bad(struct ble_sm_test_params *params); void ble_sm_test_util_us_fail_inval(struct ble_sm_test_params *params); #ifdef __cplusplus From 4ad4395d7ca0de9607f766700f5b85708ae7b7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 18 Mar 2021 13:15:02 +0100 Subject: [PATCH 019/306] ble_sm: add Secure Connections Only mode Added mode allowing to enforce pairing only in SC mode 1 level 4. This mode is required to pass GAP/SEC/SEM/BI testcases. Added BLE_SM_SC_LVL config to allow pairing only in selected levels. --- nimble/host/src/ble_att_svr.c | 10 +++++++ nimble/host/src/ble_sm.c | 25 +++++++++++++++-- nimble/host/syscfg.yml | 28 +++++++++++++++++++ .../examples/linux/include/syscfg/syscfg.h | 8 ++++++ .../linux_blemesh/include/syscfg/syscfg.h | 8 ++++++ .../examples/nuttx/include/syscfg/syscfg.h | 8 ++++++ porting/nimble/include/syscfg/syscfg.h | 8 ++++++ porting/npl/riot/include/syscfg/syscfg.h | 8 ++++++ 8 files changed, 101 insertions(+), 2 deletions(-) diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index 0cfbc7d96b..7b2611accf 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -284,6 +284,16 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read, } ble_att_svr_get_sec_state(conn_handle, &sec_state); + /* In SC Only mode all characteristics requiring security + * require it on level 4 + */ + if (MYNEWT_VAL(BLE_SM_SC_ONLY)) { + if (sec_state.key_size != 128 || + !sec_state.authenticated || + !sec_state.encrypted) { + return BLE_ATT_ERR_INSUFFICIENT_KEY_SZ; + } + } if ((enc || authen) && !sec_state.encrypted) { ble_hs_lock(); conn = ble_hs_conn_find(conn_handle); diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index b4e8096a57..c63af4087c 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -1726,17 +1726,23 @@ ble_sm_pair_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, } static bool -ble_sm_verify_auth_requirements(uint8_t authreq) +ble_sm_verify_auth_requirements(uint8_t cmd) { /* For now we check only SC only mode. I.e.: when remote indicates * to not support SC pairing, let us make sure legacy pairing is supported * on our side. If not, we can fail right away. */ - if (!(authreq & BLE_SM_PAIR_AUTHREQ_SC)) { + if (!(cmd & BLE_SM_PAIR_AUTHREQ_SC)) { if (MYNEWT_VAL(BLE_SM_LEGACY) == 0) { return false; } } + /* Fail if Secure Connections level forces MITM protection and remote does not + * support it + */ + if (MYNEWT_VAL(BLE_SM_SC_LVL) >= 3 && !(cmd & BLE_SM_PAIR_AUTHREQ_MITM)) { + return false; + } return true; } @@ -1817,12 +1823,21 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om, if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) { res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP); + } else if (MYNEWT_VAL(BLE_SM_SC_LVL) == 1) { + res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP); } else if (req->max_enc_key_size < BLE_SM_PAIR_KEY_SZ_MIN) { res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); } else if (req->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); + } else if (MYNEWT_VAL(BLE_SM_SC_ONLY) && (req->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { + /* Fail if Secure Connections Only mode is on and remote does not meet + * key size requirements - MITM was checked in last step + */ + res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); } else if (!ble_sm_verify_auth_requirements(req->authreq)) { res->sm_err = BLE_SM_ERR_AUTHREQ; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); @@ -1886,6 +1901,12 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om, } else if (rsp->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); + } else if (MYNEWT_VAL(BLE_SM_SC_ONLY) && (rsp->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { + /* Fail if Secure Connections Only mode is on and remote does not meet + * key size requirements - MITM was checked in last step + */ + res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); } else if (!ble_sm_verify_auth_requirements(rsp->authreq)) { res->sm_err = BLE_SM_ERR_AUTHREQ; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); diff --git a/nimble/host/syscfg.yml b/nimble/host/syscfg.yml index e72e8d529e..c814ba5695 100644 --- a/nimble/host/syscfg.yml +++ b/nimble/host/syscfg.yml @@ -133,6 +133,34 @@ syscfg.defs: description: 'Security manager secure connections (4.2).' value: 0 + BLE_SM_SC_ONLY: + description: > + Force global Secure Connections Pairing Only mode. This means + that only SC pairing mode 1 level 4 shall be used, and all + characteristics will require it to access, except these + requiring mode 1 level 1. + value: 0 + restrictions: + - 'BLE_SM_SC_LVL == 4 if 1' + + BLE_SM_SC_LVL: + description: > + Force global Secure Connections mode 1 level. This level + describes requirements for pairing response/request received + to accept pairing: + - 1 - do not pair; only access to characteristics with no + authentication requirements is granted + - 2 - allow to pair despite MITM being on or off + - 3 - allow to pair only when MITM protection is on + - 4 - allow to pair only when 128 bit key is used and MITM is on + When set to 0 level is no forced and pairing is allowed for all + requests/responses with valid values (for example pairing will be + rejected with key longer than 128 bits). Successful pairing with + insufficient security will still cause denying access to protected + GATT characteristics. + value: 0 + range: 0..4 + BLE_SM_MAX_PROCS: description: > The maximum number of concurrent security manager procedures. diff --git a/porting/examples/linux/include/syscfg/syscfg.h b/porting/examples/linux/include/syscfg/syscfg.h index 99939f2b41..8363336eed 100644 --- a/porting/examples/linux/include/syscfg/syscfg.h +++ b/porting/examples/linux/include/syscfg/syscfg.h @@ -735,6 +735,14 @@ #define MYNEWT_VAL_BLE_SM_SC (0) #endif +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SC_LVL +#define MYNEWT_VAL_BLE_SM_SC_LVL (0) +#endif + #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS #define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index 9aac1068ab..a3df8b6ea0 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -738,6 +738,14 @@ #define MYNEWT_VAL_BLE_SM_SC (1) #endif +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SC_LVL +#define MYNEWT_VAL_BLE_SM_SC_LVL (0) +#endif + #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS #define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif diff --git a/porting/examples/nuttx/include/syscfg/syscfg.h b/porting/examples/nuttx/include/syscfg/syscfg.h index ff73312e13..c8ad4e4976 100644 --- a/porting/examples/nuttx/include/syscfg/syscfg.h +++ b/porting/examples/nuttx/include/syscfg/syscfg.h @@ -785,6 +785,14 @@ #define MYNEWT_VAL_BLE_SM_SC (1) #endif +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SC_LVL +#define MYNEWT_VAL_BLE_SM_SC_LVL (0) +#endif + #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS #define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif diff --git a/porting/nimble/include/syscfg/syscfg.h b/porting/nimble/include/syscfg/syscfg.h index c4b70db4bc..cfc10edb54 100644 --- a/porting/nimble/include/syscfg/syscfg.h +++ b/porting/nimble/include/syscfg/syscfg.h @@ -734,6 +734,14 @@ #define MYNEWT_VAL_BLE_SM_SC (0) #endif +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SC_LVL +#define MYNEWT_VAL_BLE_SM_SC_LVL (0) +#endif + #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS #define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif diff --git a/porting/npl/riot/include/syscfg/syscfg.h b/porting/npl/riot/include/syscfg/syscfg.h index f7406f076a..e3d282e1d8 100644 --- a/porting/npl/riot/include/syscfg/syscfg.h +++ b/porting/npl/riot/include/syscfg/syscfg.h @@ -1487,6 +1487,14 @@ #define MYNEWT_VAL_BLE_SM_SC (0) #endif +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SC_LVL +#define MYNEWT_VAL_BLE_SM_SC_LVL (0) +#endif + #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS #define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif From 83ea568cb867c4fbf24a49070d731457d4808dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 12 May 2021 10:12:00 +0200 Subject: [PATCH 020/306] ble_att_svr: fix keysize check for SC Only mode Keysize is kept in bytes and not bits --- nimble/host/src/ble_att_svr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index 7b2611accf..4fdf27e843 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -288,7 +288,7 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read, * require it on level 4 */ if (MYNEWT_VAL(BLE_SM_SC_ONLY)) { - if (sec_state.key_size != 128 || + if (sec_state.key_size != 16 || !sec_state.authenticated || !sec_state.encrypted) { return BLE_ATT_ERR_INSUFFICIENT_KEY_SZ; From be97b7370e2b9ed5ae184eed667940903d51e1db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 16 Mar 2021 10:26:25 +0100 Subject: [PATCH 021/306] mesh: BLE_MESH_RELAY_ENABLED should have BLE_MESH_RELAY as default value --- nimble/host/mesh/syscfg.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index cf0c7f7505..9683df432b 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -311,13 +311,6 @@ syscfg.defs: value: 4 retrictions: 'BLE_MESH_SEG_RETRANSMIT_ATTEMPTS > 1' - BLE_MESH_RELAY: - description: > - Controls the initial number of retransmissions of original messages, - in addition to the first transmission. Can be changed through runtime - configuration. - value: 2 - BLE_MESH_NETWORK_TRANSMIT_COUNT: description: > Controls the initial number of retransmissions of original messages, @@ -332,7 +325,7 @@ syscfg.defs: configuration. value: 20 - BT_MESH_RELAY: + BLE_MESH_RELAY: description: > Support for acting as a Mesh Relay Node. value: 1 @@ -341,14 +334,13 @@ syscfg.defs: description: > Controls whether the Mesh Relay feature is enabled by default. Can be changed through runtime configuration. - value: 1 + value: MYNEWT_VAL(BLE_MESH_RELAY) BLE_MESH_RELAY_RETRANSMIT_COUNT: description: > Controls the initial number of retransmissions of relayed messages, in addition to the first transmission. Can be changed through runtime configuration. - value: 2 BLE_MESH_RELAY_RETRANSMIT_INTERVAL: From cd8ab38c3da91b71dd428979153a408f38d3b02e Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Thu, 20 May 2021 15:43:50 +0800 Subject: [PATCH 022/306] nuttx: fix error: use of undeclared identifier 'ENOMEM' Signed-off-by: Xiang Xiao --- porting/npl/nuttx/src/os_task.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/porting/npl/nuttx/src/os_task.c b/porting/npl/nuttx/src/os_task.c index ab535a36c5..40f8c8c7ba 100644 --- a/porting/npl/nuttx/src/os_task.c +++ b/porting/npl/nuttx/src/os_task.c @@ -18,6 +18,8 @@ */ #include +#include + #include "os/os.h" #include "nimble/nimble_npl.h" From aeb1adb59bf0b64956eb28596b6fff4b26aed0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 25 May 2021 12:11:09 +0200 Subject: [PATCH 023/306] bttester: handle special PSMs in l2cap Added special PSM that identify channels requireing security. These PSMs correspond to TSPX_psm_authentication_required, TSPX_psm_authorization_required, TSPX_psm_encryption_key_size_required. When connection is accepted on these PSMs, link security is checked and appropriate error is returned when condition is not met. This affects tests L2CAP/LE/CFC/BV-{11, 13, 15}-C --- apps/bttester/src/l2cap.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/apps/bttester/src/l2cap.c b/apps/bttester/src/l2cap.c index 5c4fc71297..b9b97ec199 100644 --- a/apps/bttester/src/l2cap.c +++ b/apps/bttester/src/l2cap.c @@ -249,6 +249,7 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg) { struct ble_l2cap_chan_info chan_info; int accept_response; + struct ble_gap_conn_desc conn; switch (event->type) { case BLE_L2CAP_EVENT_COC_CONNECTED: @@ -288,6 +289,28 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg) event->disconnect.chan, &chan_info, arg); return 0; case BLE_L2CAP_EVENT_COC_ACCEPT: + ble_l2cap_get_chan_info(event->accept.chan, &chan_info); + if (chan_info.psm == 0x00F2) { + /* TSPX_psm_authentication_required */ + ble_gap_conn_find(event->accept.conn_handle, &conn); + if (!conn.sec_state.authenticated) { + return BLE_HS_EAUTHEN; + } + } else if (chan_info.psm == 0x00F3) { + /* TSPX_psm_authorization_required */ + ble_gap_conn_find(event->accept.conn_handle, &conn); + if (!conn.sec_state.encrypted) { + return BLE_HS_EAUTHOR; + } + return BLE_HS_EAUTHOR; + } else if (chan_info.psm == 0x00F4) { + /* TSPX_psm_encryption_key_size_required */ + ble_gap_conn_find(event->accept.conn_handle, &conn); + if (conn.sec_state.key_size < 16) { + return BLE_HS_EENCRYPT_KEY_SZ; + } + } + accept_response = POINTER_TO_INT(arg); if (accept_response) { return accept_response; From 77a1779a53a4c18d18804900988ffac437800d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 10:39:57 +0200 Subject: [PATCH 024/306] mesh: Fix typo when deleting app key in CDB This commit sets `net_idx` to `BT_MESH_KEY_UNUSED` when deleting app key in cdb. this is port of d593af30db1c9164db35ccc28862b06718440cad --- nimble/host/mesh/src/cdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/cdb.c b/nimble/host/mesh/src/cdb.c index 459730ee76..f0c2e5f975 100644 --- a/nimble/host/mesh/src/cdb.c +++ b/nimble/host/mesh/src/cdb.c @@ -359,7 +359,7 @@ void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store) bt_mesh_clear_cdb_app_key(key); } - key->net_idx = BT_MESH_ADDR_UNASSIGNED; + key->net_idx = BT_MESH_KEY_UNUSED; memset(key->keys, 0, sizeof(key->keys)); } From 8becf2a64f0659d431685e5f39f8fbfa2aa2404b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 10:44:43 +0200 Subject: [PATCH 025/306] mesh: Fix heartbeat subscription tests MESH/NODE/CFG/HBS/BV-01-C expects the MinHops to be 0x7f after disabling subscription, but 0x00 for subsequent Get requests. MESH/NODE/CFG/HBS/BV-02-C expects us to return previous count value and then reset it to 0. this is port of 419d2aa85b3e2656ac8bdd99875313e9f4b4720c --- nimble/host/mesh/src/cfg_srv.c | 10 +++++++++- nimble/host/mesh/src/heartbeat.c | 5 +++++ nimble/host/mesh/src/heartbeat.h | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 8a085bd710..404f7318d4 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -2387,11 +2387,19 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, /* MESH/NODE/CFG/HBS/BV-01-C expects the MinHops to be 0x7f after * disabling subscription, but 0x00 for subsequent Get requests. */ - if (!period_log) { + if (sub.src == BT_MESH_ADDR_UNASSIGNED || !period_log) { sub.min_hops = BT_MESH_TTL_MAX; } hb_sub_send_status(model, ctx, &sub); + + /* MESH/NODE/CFG/HBS/BV-02-C expects us to return previous + * count value and then reset it to 0. + */ + if (sub.src != BT_MESH_ADDR_UNASSIGNED && + sub.dst != BT_MESH_ADDR_UNASSIGNED && !period) { + bt_mesh_hb_sub_reset_count(); + } } const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = { diff --git a/nimble/host/mesh/src/heartbeat.c b/nimble/host/mesh/src/heartbeat.c index 538a1cb662..f990dc0c12 100644 --- a/nimble/host/mesh/src/heartbeat.c +++ b/nimble/host/mesh/src/heartbeat.c @@ -303,6 +303,11 @@ uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period) return STATUS_SUCCESS; } +void bt_mesh_hb_sub_reset_count(void) +{ + sub.count = 0; +} + void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get) { *get = sub; diff --git a/nimble/host/mesh/src/heartbeat.h b/nimble/host/mesh/src/heartbeat.h index c43683fef0..92b0cae9e4 100644 --- a/nimble/host/mesh/src/heartbeat.h +++ b/nimble/host/mesh/src/heartbeat.h @@ -38,3 +38,4 @@ void bt_mesh_hb_feature_changed(uint16_t features); uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *hb_pub); uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period); +void bt_mesh_hb_sub_reset_count(void); From 15d9fd610b046f9c72e6766326d9536cdc3d155c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 12:04:32 +0200 Subject: [PATCH 026/306] mesh: Add net transmit status rx in config client Adds an opcode handler for the network transmit status opcode. this is port of 66699b81708a257f41a3a4572cd67b904b511d01 --- nimble/host/mesh/src/cfg_cli.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index a87cd7bb9f..104d4e6a74 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -136,6 +136,27 @@ static void relay_status(struct bt_mesh_model *model, k_sem_give(&cli->op_sync); } +static void net_transmit_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + uint8_t *status; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (cli->op_pending != OP_NET_TRANSMIT_STATUS) { + BT_WARN("Unexpected Net Transmit Status message"); + return; + } + + status = cli->op_param; + *status = net_buf_simple_pull_u8(buf); + + k_sem_give(&cli->op_sync); +} + struct net_key_param { uint8_t *status; uint16_t net_idx; @@ -693,6 +714,7 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { { OP_FRIEND_STATUS, 1, friend_status }, { OP_GATT_PROXY_STATUS, 1, gatt_proxy_status }, { OP_RELAY_STATUS, 2, relay_status }, + { OP_NET_TRANSMIT_STATUS, 1, net_transmit_status }, { OP_NET_KEY_STATUS, 3, net_key_status }, { OP_NET_KEY_LIST, 0, net_key_list }, { OP_APP_KEY_STATUS, 4, app_key_status }, From 299b2ebe9ab2ac6c9cb85cffb0f10e18428212e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 12:15:23 +0200 Subject: [PATCH 027/306] mesh: Check response address in Configuration Client The Configuration Client doesn't check the address in a received response. This means that a response from any device will be accepted. This change ensures that the correct response will be accepted. this is port of 8bcc85b38cccf1f36e769e907f43137f68305aa7 --- nimble/host/mesh/include/mesh/cfg_cli.h | 3 +- nimble/host/mesh/src/cfg_cli.c | 91 +++++++++++++------------ 2 files changed, 51 insertions(+), 43 deletions(-) diff --git a/nimble/host/mesh/include/mesh/cfg_cli.h b/nimble/host/mesh/include/mesh/cfg_cli.h index bd2f9fe5bb..368bdfc344 100644 --- a/nimble/host/mesh/include/mesh/cfg_cli.h +++ b/nimble/host/mesh/include/mesh/cfg_cli.h @@ -26,8 +26,9 @@ struct bt_mesh_cfg_cli { struct bt_mesh_model *model; struct k_sem op_sync; - uint32_t op_pending; + uint32_t op_pending; void *op_param; + uint16_t op_addr; }; extern const struct bt_mesh_model_op bt_mesh_cfg_cli_op[]; diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index 104d4e6a74..2df7d70271 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -33,6 +33,11 @@ static int32_t msg_timeout = K_SECONDS(5); static struct bt_mesh_cfg_cli *cli; +static inline bool cli_response_check(uint32_t resp_opcode, uint16_t resp_addr) +{ + return cli->op_pending == resp_opcode && cli->op_addr == resp_addr; +} + static void comp_data_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) @@ -44,7 +49,7 @@ static void comp_data_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_DEV_COMP_DATA_STATUS) { + if (!cli_response_check(OP_DEV_COMP_DATA_STATUS, ctx->addr)) { BT_WARN("Unexpected Composition Data Status"); return; } @@ -69,7 +74,7 @@ static void state_status_u8(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != expect_status) { + if (!cli_response_check(expect_status, ctx->addr)) { BT_WARN("Unexpected Status (0x%08x != 0x%08x)", (unsigned) cli->op_pending, (unsigned) expect_status); return; @@ -124,7 +129,7 @@ static void relay_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_RELAY_STATUS) { + if (!cli_response_check(OP_RELAY_STATUS, ctx->addr)) { BT_WARN("Unexpected Relay Status message"); return; } @@ -146,7 +151,7 @@ static void net_transmit_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_NET_TRANSMIT_STATUS) { + if (!cli_response_check(OP_NET_TRANSMIT_STATUS, ctx->addr)) { BT_WARN("Unexpected Net Transmit Status message"); return; } @@ -174,7 +179,7 @@ static void net_key_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_NET_KEY_STATUS) { + if (!cli_response_check(OP_NET_KEY_STATUS, ctx->addr)) { BT_WARN("Unexpected Net Key Status message"); return; } @@ -211,7 +216,7 @@ static void net_key_list(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_NET_KEY_LIST) { + if (!cli_response_check(OP_NET_KEY_LIST, ctx->addr)) { BT_WARN("Unexpected Net Key List message"); return; } @@ -238,7 +243,7 @@ static void node_reset_status(struct bt_mesh_model *model, BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - if (cli->op_pending != OP_NODE_RESET_STATUS) { + if (!cli_response_check(OP_NODE_RESET_STATUS, ctx->addr)) { BT_WARN("Unexpected Node Reset Status message"); return; } @@ -269,7 +274,7 @@ static void app_key_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_APP_KEY_STATUS) { + if (!cli_response_check(OP_APP_KEY_STATUS, ctx->addr)) { BT_WARN("Unexpected App Key Status message"); return; } @@ -310,7 +315,7 @@ static void app_key_list(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_APP_KEY_LIST) { + if (!cli_response_check(OP_APP_KEY_LIST, ctx->addr)) { BT_WARN("Unexpected App Key List message"); return; } @@ -360,7 +365,7 @@ static void mod_app_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_MOD_APP_STATUS) { + if (!cli_response_check(OP_MOD_APP_STATUS, ctx->addr)) { BT_WARN("Unexpected Model App Status message"); return; } @@ -449,7 +454,7 @@ static void mod_app_list(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_SIG_MOD_APP_LIST) { + if (!cli_response_check(OP_SIG_MOD_APP_LIST, ctx->addr)) { BT_WARN("Unexpected Model App List message"); return; } @@ -465,7 +470,7 @@ static void mod_app_list_vnd(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_VND_MOD_APP_LIST) { + if (!cli_response_check(OP_VND_MOD_APP_LIST, ctx->addr)) { BT_WARN("Unexpected Model App List Vendor message"); return; } @@ -493,7 +498,7 @@ static void mod_pub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_MOD_PUB_STATUS) { + if (!cli_response_check(OP_MOD_PUB_STATUS, ctx->addr)) { BT_WARN("Unexpected Model Pub Status message"); return; } @@ -569,7 +574,7 @@ static void mod_sub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_MOD_SUB_STATUS) { + if (!cli_response_check(OP_MOD_SUB_STATUS, ctx->addr)) { BT_WARN("Unexpected Model Subscription Status message"); return; } @@ -613,7 +618,7 @@ static void mod_sub_list(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_MOD_SUB_LIST) { + if (!cli_response_check(OP_MOD_SUB_LIST, ctx->addr)) { BT_WARN("Unexpected Model Subscription List message"); return; } @@ -629,7 +634,7 @@ static void mod_sub_list_vnd(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_MOD_SUB_LIST_VND) { + if (!cli_response_check(OP_MOD_SUB_LIST_VND, ctx->addr)) { BT_WARN("Unexpected Model Subscription List Vendor message"); return; } @@ -652,7 +657,7 @@ static void hb_sub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_HEARTBEAT_SUB_STATUS) { + if (!cli_response_check(OP_HEARTBEAT_SUB_STATUS, ctx->addr)) { BT_WARN("Unexpected Heartbeat Subscription Status message"); return; } @@ -686,7 +691,7 @@ static void hb_pub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (cli->op_pending != OP_HEARTBEAT_PUB_STATUS) { + if (!cli_response_check(OP_HEARTBEAT_PUB_STATUS, ctx->addr)) { BT_WARN("Unexpected Heartbeat Publication Status message"); return; } @@ -764,7 +769,7 @@ const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = { .init = cfg_cli_init, }; -static int cli_prepare(void *param, uint32_t op) +static int cli_prepare(void *param, uint32_t op, uint16_t addr) { if (!cli) { BT_ERR("No available Configuration Client context!"); @@ -778,6 +783,7 @@ static int cli_prepare(void *param, uint32_t op) cli->op_param = param; cli->op_pending = op; + cli->op_addr = addr; return 0; } @@ -786,6 +792,7 @@ static void cli_reset(void) { cli->op_pending = 0; cli->op_param = NULL; + cli->op_addr = BT_MESH_ADDR_UNASSIGNED; } static int cli_wait(void) @@ -815,7 +822,7 @@ int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, }; int err; - err = cli_prepare(¶m, OP_DEV_COMP_DATA_STATUS); + err = cli_prepare(¶m, OP_DEV_COMP_DATA_STATUS, addr); if (err) { goto done; } @@ -848,7 +855,7 @@ static int get_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t r }; int err; - err = cli_prepare(val, rsp); + err = cli_prepare(val, rsp, addr); if (err) { goto done; } @@ -880,7 +887,7 @@ static int set_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t r }; int err; - err = cli_prepare(val, rsp); + err = cli_prepare(val, rsp, addr); if (err) { goto done; } @@ -980,7 +987,7 @@ int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status, }; int err; - err = cli_prepare(¶m, OP_RELAY_STATUS); + err = cli_prepare(¶m, OP_RELAY_STATUS, addr); if (err) { goto done; } @@ -1016,7 +1023,7 @@ int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay, }; int err; - err = cli_prepare(¶m, OP_RELAY_STATUS); + err = cli_prepare(¶m, OP_RELAY_STATUS, addr); if (err) { goto done; } @@ -1054,7 +1061,7 @@ int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_id }; int err; - err = cli_prepare(¶m, OP_NET_KEY_STATUS); + err = cli_prepare(¶m, OP_NET_KEY_STATUS, addr); if (err) { goto done; } @@ -1097,7 +1104,7 @@ int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys, }; int err; - err = cli_prepare(¶m, OP_NET_KEY_LIST); + err = cli_prepare(¶m, OP_NET_KEY_LIST, addr); if (err) { return err; } @@ -1131,7 +1138,7 @@ int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr, }; int err; - err = cli_prepare(¶m, OP_NET_KEY_STATUS); + err = cli_prepare(¶m, OP_NET_KEY_STATUS, addr); if (err) { goto done; } @@ -1175,7 +1182,7 @@ int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_id }; int err; - err = cli_prepare(¶m, OP_APP_KEY_STATUS); + err = cli_prepare(¶m, OP_APP_KEY_STATUS, addr); if (err) { goto done; } @@ -1218,7 +1225,7 @@ int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status) *status = false; } - err = cli_prepare(status, OP_NODE_RESET_STATUS); + err = cli_prepare(status, OP_NODE_RESET_STATUS, addr); if (err) { goto done; } @@ -1265,7 +1272,7 @@ int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_id }; int err; - err = cli_prepare(¶m, OP_APP_KEY_LIST); + err = cli_prepare(¶m, OP_APP_KEY_LIST, addr); if (err) { os_mbuf_free_chain(msg); return err; @@ -1303,7 +1310,7 @@ int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr, }; int err; - err = cli_prepare(¶m, OP_APP_KEY_STATUS); + err = cli_prepare(¶m, OP_APP_KEY_STATUS, addr); if (err) { os_mbuf_free_chain(msg); return err; @@ -1350,7 +1357,7 @@ static int mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, }; int err; - err = cli_prepare(¶m, OP_MOD_APP_STATUS); + err = cli_prepare(¶m, OP_MOD_APP_STATUS, addr); if (err) { goto done; } @@ -1422,7 +1429,7 @@ static int mod_app_unbind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, }; int err; - err = cli_prepare(¶m, OP_MOD_APP_STATUS); + err = cli_prepare(¶m, OP_MOD_APP_STATUS, addr); if (err) { goto done; } @@ -1501,7 +1508,7 @@ static int mod_member_list_get(uint32_t op, uint32_t expect_op, uint16_t net_idx }; int err; - err = cli_prepare(¶m, expect_op); + err = cli_prepare(¶m, expect_op, addr); if (err) { goto done; } @@ -1573,7 +1580,7 @@ static int mod_sub(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_a }; int err; - err = cli_prepare(¶m, OP_MOD_SUB_STATUS); + err = cli_prepare(¶m, OP_MOD_SUB_STATUS, addr); if (err) { goto done; } @@ -1684,7 +1691,7 @@ static int mod_sub_va(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t ele }; int err; - err = cli_prepare(¶m, OP_MOD_SUB_STATUS); + err = cli_prepare(¶m, OP_MOD_SUB_STATUS, addr); if (err) { goto done; } @@ -1825,7 +1832,7 @@ static int mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, }; int err; - err = cli_prepare(¶m, OP_MOD_PUB_STATUS); + err = cli_prepare(¶m, OP_MOD_PUB_STATUS, addr); if (err) { goto done; } @@ -1897,7 +1904,7 @@ static int mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, }; int err; - err = cli_prepare(¶m, OP_MOD_PUB_STATUS); + err = cli_prepare(¶m, OP_MOD_PUB_STATUS, addr); if (err) { goto done; } @@ -1970,7 +1977,7 @@ int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr, }; int err; - err = cli_prepare(¶m, OP_HEARTBEAT_SUB_STATUS); + err = cli_prepare(¶m, OP_HEARTBEAT_SUB_STATUS, addr); if (err) { goto done; } @@ -2014,7 +2021,7 @@ int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr, }; int err; - err = cli_prepare(¶m, OP_HEARTBEAT_SUB_STATUS); + err = cli_prepare(¶m, OP_HEARTBEAT_SUB_STATUS, addr); if (err) { goto done; } @@ -2054,7 +2061,7 @@ int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr, }; int err; - err = cli_prepare(¶m, OP_HEARTBEAT_PUB_STATUS); + err = cli_prepare(¶m, OP_HEARTBEAT_PUB_STATUS, addr); if (err) { goto done; } @@ -2101,7 +2108,7 @@ int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr, }; int err; - err = cli_prepare(¶m, OP_HEARTBEAT_PUB_STATUS); + err = cli_prepare(¶m, OP_HEARTBEAT_PUB_STATUS, addr); if (err) { goto done; } From 68c409ab57b351e4161c33b2d2775a41f2289bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 12:29:23 +0200 Subject: [PATCH 028/306] mesh: Verify network buffer max len As network_decode needs a target buffer for decoding, the max PDU length must be checked to prevent overflow on the target buffer. When receiving a proxy configuration message with excessive length, there's no previous check for this. Also pulls the NET PDU length defines out into net.h, so they can be used when defining the target buffers. this is port of 2bd5b63dfd1cba183f2c20af5ff497346827087f --- nimble/host/mesh/src/net.c | 15 ++++++--------- nimble/host/mesh/src/net.h | 13 +++++++++++++ nimble/host/mesh/src/proxy.c | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 8b86935d31..2e1d6dc7f4 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -34,14 +34,6 @@ #include "mesh/glue.h" #include "mesh/slist.h" -/* Minimum valid Mesh Network PDU length. The Network headers - * themselves take up 9 bytes. After that there is a minumum of 1 byte - * payload for both CTL=1 and CTL=0 PDUs (smallest OpCode is 1 byte). CTL=1 - * PDUs must use a 64-bit (8 byte) NetMIC, whereas CTL=0 PDUs have at least - * a 32-bit (4 byte) NetMIC and AppMIC giving again a total of 8 bytes. - */ -#define BT_MESH_NET_MIN_PDU_LEN (BT_MESH_NET_HDR_LEN + 1 + 8) - #define LOOPBACK_MAX_PDU_LEN (BT_MESH_NET_HDR_LEN + 16) #define LOOPBACK_USER_DATA_SIZE sizeof(struct bt_mesh_subnet *) #define LOOPBACK_BUF_SUB(buf) (*(struct bt_mesh_subnet **)net_buf_user_data(buf)) @@ -702,6 +694,11 @@ int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if, return -EINVAL; } + if (in->om_len > BT_MESH_NET_MAX_PDU_LEN) { + BT_WARN("Dropping too long mesh packet (len %u)", in->om_len); + return -EINVAL; + } + if (net_if == BT_MESH_NET_IF_ADV && check_dup(in)) { BT_DBG("duplicate packet; dropping %u bytes: %s", in->om_len, bt_hex(in->om_data, in->om_len)); @@ -754,7 +751,7 @@ int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if, void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi, enum bt_mesh_net_if net_if) { - struct os_mbuf *buf = NET_BUF_SIMPLE(29); + struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_NET_MAX_PDU_LEN); struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi }; struct net_buf_simple_state state; diff --git a/nimble/host/mesh/src/net.h b/nimble/host/mesh/src/net.h index f4b1192b2c..8c501540df 100644 --- a/nimble/host/mesh/src/net.h +++ b/nimble/host/mesh/src/net.h @@ -25,6 +25,19 @@ CONFIG_BT_MESH_IVU_DIVIDER) #define BT_MESH_IVU_TIMEOUT K_HOURS(BT_MESH_IVU_HOURS) +/* Minimum valid Mesh Network PDU length. The Network headers + * themselves take up 9 bytes. After that there is a minimum of 1 byte + * payload for both CTL=1 and CTL=0 PDUs (smallest OpCode is 1 byte). CTL=1 + * PDUs must use a 64-bit (8 byte) NetMIC, whereas CTL=0 PDUs have at least + * a 32-bit (4 byte) NetMIC and AppMIC giving again a total of 8 bytes. + */ +#define BT_MESH_NET_MIN_PDU_LEN (BT_MESH_NET_HDR_LEN + 1 + 8) +/* Maximum valid Mesh Network PDU length. The longest packet can either be a + * transport control message (CTL=1) of 12 bytes + 8 bytes of NetMIC, or an + * access message (CTL=0) of 16 bytes + 4 bytes of NetMIC. + */ +#define BT_MESH_NET_MAX_PDU_LEN (BT_MESH_NET_HDR_LEN + 16 + 4) + struct bt_mesh_net_cred; struct bt_mesh_node { diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/proxy.c index 6d631b7211..9ed983d141 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/proxy.c @@ -328,7 +328,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, static void proxy_cfg(struct bt_mesh_proxy_client *client) { - struct os_mbuf *buf = NET_BUF_SIMPLE(29); + struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_NET_MAX_PDU_LEN); struct bt_mesh_net_rx rx; uint8_t opcode; int err; From 8256009f6d90e6b81b9839e7ec32de87b34df87b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 12:46:00 +0200 Subject: [PATCH 029/306] mesh: Initialize msg_ctx when re-encrypting friend msg Set app_idx and net_idx in the msg_ctx before calling bt_mesh_keys_resolve when re-encrypting friend messages, as they'll be referenced inside the function. this is port of 48526b6925a11bb979b657912dda012303e9050e --- nimble/host/mesh/src/friend.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 9a83c87fc5..8dc55c1511 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -345,7 +345,12 @@ static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd, struct unseg_app_sdu_meta *meta) { uint16_t app_idx = FRIEND_ADV(buf)->app_idx; - struct bt_mesh_net_rx net; + struct bt_mesh_net_rx net = { + .ctx = { + .app_idx = app_idx, + .net_idx = frnd->subnet->net_idx, + }, + }; int err; meta->subnet = frnd->subnet; @@ -437,6 +442,8 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, return 0; } + BT_DBG("Re-encrypting friend pdu"); + err = unseg_app_sdu_decrypt(frnd, buf, &meta); if (err) { BT_WARN("Decryption failed! %d", err); From 8255bee130c3ab3e1852448f09634e60fd3ca9fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 12:47:24 +0200 Subject: [PATCH 030/306] mesh: Update seqnum when re-encrypting for friend Sets the sequence number when re-encrypting messages from the friend to the lpn. this is port of 512444d863f0e4de69ea600dda37b11f032e9707 --- nimble/host/mesh/src/friend.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 8dc55c1511..5918ecf5b1 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -442,7 +442,8 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, return 0; } - BT_DBG("Re-encrypting friend pdu"); + BT_DBG("Re-encrypting friend pdu (SeqNum %06x -> %06x)", + meta.crypto.seq_num, bt_mesh.seq); err = unseg_app_sdu_decrypt(frnd, buf, &meta); if (err) { @@ -450,6 +451,8 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, return err; } + meta.crypto.seq_num = bt_mesh.seq; + err = unseg_app_sdu_encrypt(frnd, buf, &meta); if (err) { BT_WARN("Re-encryption failed! %d", err); From ab0f5d833b22c4aee089e750563175744d0d59d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 12:48:24 +0200 Subject: [PATCH 031/306] mesh: Reduce proxy rx buffer to an exact fit Removes the 3 byte padding at the end of each proxy connection's rx buffer. this is port of 135af766664f1fd1d9eacd2ffc78aa6d240663db --- nimble/host/mesh/src/proxy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/proxy.c index 9ed983d141..d013c79894 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/proxy.c @@ -86,7 +86,7 @@ ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) -#define CLIENT_BUF_SIZE 68 +#define CLIENT_BUF_SIZE 65 static const struct ble_gap_adv_params slow_adv_param = { .conn_mode = (BLE_GAP_CONN_MODE_UND), From 9f396bca302c892a43f79c01b96fdaa1cc417040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 12:51:57 +0200 Subject: [PATCH 032/306] mesh: Fix provisioner provisioning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct format errors, such as oob action 2-octers should use 0x%04x, and action in prov capalilities pdu big-ending. When every call `bt_mesh_auth_method_set<*>` should also clear auth value, otherwise will case confirm failed. Provisioner role expect peer public key should be sent immediately, instead of requiring ACK. After all, ACK may be lost, and the other device’s public key will be sent over, and provisioning procedure will be failed.. this is port of 0841ee69f2376f40befa938caacf97172be6fecd --- nimble/host/mesh/src/prov.c | 4 ++-- nimble/host/mesh/src/provisioner.c | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c index ba514dde97..170fc1d099 100644 --- a/nimble/host/mesh/src/prov.c +++ b/nimble/host/mesh/src/prov.c @@ -40,7 +40,7 @@ int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64])) int err; static struct bt_pub_key_cb pub_key_cb; - const size_t offset = offsetof(struct bt_mesh_prov_link, dhkey); + const size_t offset = offsetof(struct bt_mesh_prov_link, auth); pub_key_cb.func = func ? func : pub_key_ready; @@ -257,7 +257,7 @@ static void prov_recv(const struct prov_bearer *bearer, void *cb_data, if (type >= ARRAY_SIZE(bt_mesh_prov_link.role->op)) { BT_ERR("Unknown provisioning PDU type 0x%02x", type); - bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT); + bt_mesh_prov_link.role->error(PROV_ERR_NVAL_PDU); return; } diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index d69aa6650a..e26efe718e 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -168,9 +168,9 @@ static bool prov_check_method(struct bt_mesh_dev_capabilities *caps) } if (!(BIT(bt_mesh_prov_link.oob_action) & caps->input_actions)) { - BT_WARN("The required input action (0x%02x) " + BT_WARN("The required input action (0x%04x) " "not supported by the device (0x%02x)", - bt_mesh_prov_link.oob_action, caps->input_actions); + (uint16_t)BIT(bt_mesh_prov_link.oob_action), caps->input_actions); return false; } @@ -194,9 +194,9 @@ static bool prov_check_method(struct bt_mesh_dev_capabilities *caps) } if (!(BIT(bt_mesh_prov_link.oob_action) & caps->output_actions)) { - BT_WARN("The required output action (0x%02x) " + BT_WARN("The required output action (0x%04x) " "not supported by the device (0x%02x)", - bt_mesh_prov_link.oob_action, caps->output_actions); + (uint16_t)BIT(bt_mesh_prov_link.oob_action), caps->output_actions); return false; } @@ -226,9 +226,11 @@ static void prov_capabilities(const uint8_t *data) BT_DBG("Static OOB Type: 0x%02x", caps.static_oob); BT_DBG("Output OOB Size: %u", caps.output_size); - caps.output_actions = (bt_mesh_output_action_t)data[6]; + caps.output_actions = (bt_mesh_output_action_t) + (sys_get_be16(&data[6])); caps.input_size = data[8]; - caps.input_actions = (bt_mesh_input_action_t)data[9]; + caps.input_actions = (bt_mesh_input_action_t) + (sys_get_be16(&data[9])); BT_DBG("Output OOB Action: 0x%04x", caps.output_actions); BT_DBG("Input OOB Size: %u", caps.input_size); BT_DBG("Input OOB Action: 0x%04x", caps.input_actions); @@ -324,8 +326,6 @@ static void public_key_sent(int err, void *cb_data) prov_dh_key_gen(); return; } - - bt_mesh_prov_link.expect = PROV_PUB_KEY; } static void send_pub_key(void) @@ -355,6 +355,8 @@ static void send_pub_key(void) BT_ERR("Failed to send Public Key"); return; } + + bt_mesh_prov_link.expect = PROV_PUB_KEY; } static void prov_dh_key_cb(const uint8_t dhkey[32]) From 83cf6da68cb8c49371875cc113d176f9cfe74f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 12:58:17 +0200 Subject: [PATCH 033/306] mesh: Add CDB handle key refresh phase Fixed some undesired or incorrect macros, which can cause build error. this is port of 71fd8e1d0141096238aadb9ce20a14781cf50b7c --- nimble/host/mesh/include/mesh/cdb.h | 1 - nimble/host/mesh/include/mesh/cfg.h | 6 ++++++ nimble/host/mesh/src/cdb.c | 2 +- nimble/host/mesh/src/provisioner.c | 2 +- nimble/host/mesh/src/settings.c | 4 +--- nimble/host/mesh/src/shell.c | 10 +++++----- nimble/host/mesh/src/testing.c | 4 ---- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/nimble/host/mesh/include/mesh/cdb.h b/nimble/host/mesh/include/mesh/cdb.h index 8f9a6bc9b9..440390cd62 100644 --- a/nimble/host/mesh/include/mesh/cdb.h +++ b/nimble/host/mesh/include/mesh/cdb.h @@ -40,7 +40,6 @@ struct bt_mesh_cdb_node { struct bt_mesh_cdb_subnet { uint16_t net_idx; - bool kr_flag; uint8_t kr_phase; struct { diff --git a/nimble/host/mesh/include/mesh/cfg.h b/nimble/host/mesh/include/mesh/cfg.h index 378f0a0aa7..6fd69266ea 100644 --- a/nimble/host/mesh/include/mesh/cfg.h +++ b/nimble/host/mesh/include/mesh/cfg.h @@ -35,6 +35,12 @@ enum bt_mesh_feat_state { BT_MESH_FEATURE_NOT_SUPPORTED, }; +/* Key Refresh Phase */ +#define BT_MESH_KR_NORMAL 0x00 +#define BT_MESH_KR_PHASE_1 0x01 +#define BT_MESH_KR_PHASE_2 0x02 +#define BT_MESH_KR_PHASE_3 0x03 + /* Legacy feature defines */ #define BT_MESH_RELAY_DISABLED BT_MESH_FEATURE_DISABLED #define BT_MESH_RELAY_ENABLED BT_MESH_FEATURE_ENABLED diff --git a/nimble/host/mesh/src/cdb.c b/nimble/host/mesh/src/cdb.c index f0c2e5f975..60d47dee26 100644 --- a/nimble/host/mesh/src/cdb.c +++ b/nimble/host/mesh/src/cdb.c @@ -235,7 +235,7 @@ uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub) { uint8_t flags = 0x00; - if (sub && sub->kr_flag) { + if (sub && SUBNET_KEY_TX_IDX(sub)) { flags |= BT_MESH_NET_FLAG_KR; } diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index e26efe718e..265dbf24d7 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -503,7 +503,7 @@ static void send_prov_data(void) #endif bt_mesh_prov_buf_init(pdu, PROV_DATA); #if MYNEWT_VAL(BLE_MESH_CDB) - net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net_key, 16); + net_buf_simple_add_mem(&pdu, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_key, 16); net_buf_simple_add_be16(pdu, prov_device.node->net_idx); net_buf_simple_add_u8(pdu, bt_mesh_cdb_subnet_flags(sub)); net_buf_simple_add_be32(pdu, bt_mesh_cdb.iv_index); diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index 193cc0b2c4..1fb2b0894b 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -829,7 +829,6 @@ static int cdb_subnet_set(int argc, char *name) if (sub) { BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx); - sub->kr_flag = key.kr_flag; sub->kr_phase = key.kr_phase; memcpy(sub->keys[0].net_key, &key.val[0], 16); memcpy(sub->keys[1].net_key, &key.val[1], 16); @@ -843,7 +842,6 @@ static int cdb_subnet_set(int argc, char *name) return -ENOMEM; } - sub->kr_flag = key.kr_flag; sub->kr_phase = key.kr_phase; memcpy(sub->keys[0].net_key, &key.val[0], 16); memcpy(sub->keys[1].net_key, &key.val[1], 16); @@ -1608,7 +1606,7 @@ static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) memcpy(&key.val[0], sub->keys[0].net_key, 16); memcpy(&key.val[1], sub->keys[1].net_key, 16); - key.kr_flag = sub->kr_flag; + key.kr_flag = 0U; /* Deprecated */ key.kr_phase = sub->kr_phase; snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx); diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index 1ac4cafe68..ade9cd65a8 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -738,7 +738,7 @@ int cmd_mesh_init(int argc, char *argv[]) printk("Mesh initialized\n"); - if (IS_ENABLED(CONFIG_SETTINGS)) { + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { settings_load(); } @@ -2345,7 +2345,7 @@ static int cmd_provision(int argc, char *argv[]) return 0; } - net_key = sub->keys[sub->kr_flag].net_key; + net_key = sub->keys[SUBNET_KEY_TX_IDX(sub)].net_key; } err = bt_mesh_provision(net_key, net_idx, 0, iv_index, addr, @@ -2905,7 +2905,7 @@ static int cmd_cdb_node_add(int argc, char *argv[]) memcpy(node->dev_key, dev_key, 16); - if (IS_ENABLED(CONFIG_SETTINGS)) { + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_store_cdb_node(node); } @@ -2959,7 +2959,7 @@ static int cmd_cdb_subnet_add(int argc, memcpy(sub->keys[0].net_key, net_key, 16); - if (IS_ENABLED(CONFIG_SETTINGS)) { + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_store_cdb_subnet(sub); } @@ -3015,7 +3015,7 @@ static int cmd_cdb_app_key_add(int argc, memcpy(key->keys[0].app_key, app_key, 16); - if (IS_ENABLED(CONFIG_SETTINGS)) { + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_store_cdb_app_key(key); } diff --git a/nimble/host/mesh/src/testing.c b/nimble/host/mesh/src/testing.c index dfe8d18e3d..7ee11a1373 100644 --- a/nimble/host/mesh/src/testing.c +++ b/nimble/host/mesh/src/testing.c @@ -135,8 +135,6 @@ void bt_test_print_credentials(void) console_printf("Subnet: %d\n", i); console_printf("\tNetKeyIdx: %04x\n", sub->net_idx); - console_printf("\tNetKey: %s\n", - bt_hex(sub->keys[sub->kr_flag].net_key, 16)); } for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) @@ -154,8 +152,6 @@ void bt_test_print_credentials(void) app_key->net_idx); console_printf("\tAppKeyIdx: %04x\n", app_key->app_idx); - console_printf("\tAppKey: %s\n", - bt_hex(app_key->keys[sub->kr_flag].app_key, 16)); } for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) From c5f9d9a3c49125759a25b54119d58d867c0fc62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 13:04:04 +0200 Subject: [PATCH 034/306] mesh: Get rid of magic number in cmd_get_comp --- nimble/host/mesh/src/shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index ade9cd65a8..0a27e274e7 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -997,7 +997,7 @@ struct shell_cmd_help cmd_timeout_help = { static int cmd_get_comp(int argc, char *argv[]) { - struct os_mbuf *comp = NET_BUF_SIMPLE(32); + struct os_mbuf *comp = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); uint8_t status, page = 0x00; int err = 0; From fa8ca30b87fce7af909d464cef9b9b3383626ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 13:04:55 +0200 Subject: [PATCH 035/306] mesh: Check subnet existence in heartbeat_send Check that the assigned subnet hasn't been removed in heartbeat_send to avoid potential NULL defererence in transport's ctl_send. this is port of 8309353b7f556d7457f75b2777a2561a31a85a78 --- nimble/host/mesh/src/heartbeat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/heartbeat.c b/nimble/host/mesh/src/heartbeat.c index f990dc0c12..3ba7ae3add 100644 --- a/nimble/host/mesh/src/heartbeat.c +++ b/nimble/host/mesh/src/heartbeat.c @@ -87,8 +87,10 @@ static int heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data) .xmit = bt_mesh_net_transmit_get(), }; - /* Do nothing if heartbeat publication is not enabled */ - if (pub.dst == BT_MESH_ADDR_UNASSIGNED) { + /* Do nothing if heartbeat publication is not enabled or the subnet is + * removed. + */ + if (!tx.sub || pub.dst == BT_MESH_ADDR_UNASSIGNED) { return 0U; } From 5e24948f0f409826cedcf8a6a1c0189024ce85cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 13:10:27 +0200 Subject: [PATCH 036/306] mesh: Check model publish pointer before dereferencing Moves the if !(pub) check to happen before it gets used in the initialization of the message context in bt_mesh_model_publish. this is port of bba2d7b84b82ac7322898776b46727580bc39ae0 --- nimble/host/mesh/src/access.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index da077182ab..d23a656551 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -682,8 +682,15 @@ int bt_mesh_model_send(struct bt_mesh_model *model, int bt_mesh_model_publish(struct bt_mesh_model *model) { + int err; struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_model_pub *pub = model->pub; + + if (!pub) { + err = -ENOTSUP; + goto done; + } + struct bt_mesh_msg_ctx ctx = { .addr = pub->addr, .send_ttl = pub->ttl, @@ -694,15 +701,9 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) .ctx = &ctx, .src = bt_mesh_model_elem(model)->addr, }; - int err; BT_DBG(""); - if (!pub) { - err = -ENOTSUP; - goto done; - } - if (pub->addr == BT_MESH_ADDR_UNASSIGNED) { err = -EADDRNOTAVAIL; goto done; From 26666ceebd64ed797011ca13546fbca5aad78f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 13:11:45 +0200 Subject: [PATCH 037/306] mesh: Resolve dead code in store_seg If CONFIG_BT_MESH_SEQ_STORE_RATE is 1, the check in store_seq can be reduced to a simple if (false), and the modulo code does not need to be included in the build. this is port of aef354c6bc3264de9f2a38b8c56ff5253b35912a --- nimble/host/mesh/src/settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index 1fb2b0894b..cb583eb35a 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -1189,7 +1189,7 @@ static void store_pending_seq(void) void bt_mesh_store_seq(void) { - if (CONFIG_BT_MESH_SEQ_STORE_RATE && + if (CONFIG_BT_MESH_SEQ_STORE_RATE > 1 && (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)) { return; } From b2f8d90f638f095af1cd3ae5ae98a92d40263ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 14:00:26 +0200 Subject: [PATCH 038/306] mesh: Explicitly ignore gatt_service_register return code The error code from gatt_service_register is being ignored to ensure that repeated actions still complete. Do this explicitly by adding (void) casts, resolving coverity warnings on accidental error code ignores. this is port of f9d41595a3a168d982e95c1f46ef9fb8b989c55b --- nimble/host/mesh/src/mesh.c | 2 +- nimble/host/mesh/src/pb_gatt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index bbb4ee3d22..10c6fff991 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -117,7 +117,7 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); if (MYNEWT_VAL(BLE_MESH_PB_GATT) && pb_gatt_enabled) { - bt_mesh_proxy_prov_enable(); + (void)bt_mesh_proxy_prov_enable(); } return err; diff --git a/nimble/host/mesh/src/pb_gatt.c b/nimble/host/mesh/src/pb_gatt.c index a8f73787dd..bce7cf6c09 100644 --- a/nimble/host/mesh/src/pb_gatt.c +++ b/nimble/host/mesh/src/pb_gatt.c @@ -115,7 +115,7 @@ int bt_mesh_pb_gatt_close(uint16_t conn_handle) static int link_accept(const struct prov_bearer_cb *cb, void *cb_data) { - bt_mesh_proxy_prov_enable(); + (void)bt_mesh_proxy_prov_enable(); bt_mesh_adv_update(); link.cb = cb; From 5f60008a2b6d631410062ee6f3d1aca12a742256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 14:01:21 +0200 Subject: [PATCH 039/306] mesh: Remove unsigned typing to returns in heartbeat Removes U-suffix from signed return codes in heartbeat.c. this is port of dc6e880eab8526bd6ba9ab8bca3f6e2a299ff98e --- nimble/host/mesh/src/heartbeat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/heartbeat.c b/nimble/host/mesh/src/heartbeat.c index 3ba7ae3add..09d64594de 100644 --- a/nimble/host/mesh/src/heartbeat.c +++ b/nimble/host/mesh/src/heartbeat.c @@ -91,7 +91,7 @@ static int heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data) * removed. */ if (!tx.sub || pub.dst == BT_MESH_ADDR_UNASSIGNED) { - return 0U; + return 0; } hb.init_ttl = pub.ttl; From 1198bb8fb02c190418157a9d1f316f62565f6d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 14:23:46 +0200 Subject: [PATCH 040/306] mesh: Resolve keys before logging subnet Moves the debug log printing the transport packet metadata to after the keys are resolved, so that the subnet pointer is valid. this is port of 9b4266b5914da021ba40372eeb390bd1d3d9df7f --- nimble/host/mesh/src/transport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index f3a7c2d601..9e70434245 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -642,15 +642,15 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg, return -EINVAL; } - BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx, - tx->ctx->app_idx, tx->ctx->addr); - BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len)); - err = bt_mesh_keys_resolve(tx->ctx, &tx->sub, &key, &aid); if (err) { return err; } + BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->sub->net_idx, + tx->ctx->app_idx, tx->ctx->addr); + BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len)); + tx->xmit = bt_mesh_net_transmit_get(); tx->aid = aid; From 1696d0fbeb66912e7eb456ce97c06f0e36a13b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 14:26:11 +0200 Subject: [PATCH 041/306] mesh: Make internal virtual addr pointers const Adds the const qualifier to the internal api for adding and removing virtual addresses, to allow them to accept const hardcoded values in tests. this is port of 20ce680d790a4c0b8232f5aeadce864c1fc537af --- nimble/host/mesh/src/transport.c | 4 ++-- nimble/host/mesh/src/transport.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 9e70434245..6391272d02 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -1650,7 +1650,7 @@ static inline void va_store(struct bt_mesh_va *store) } } -uint8_t bt_mesh_va_add(uint8_t uuid[16], uint16_t *addr) +uint8_t bt_mesh_va_add(const uint8_t uuid[16], uint16_t *addr) { struct bt_mesh_va *va = NULL; int err; @@ -1692,7 +1692,7 @@ uint8_t bt_mesh_va_add(uint8_t uuid[16], uint16_t *addr) return STATUS_SUCCESS; } -uint8_t bt_mesh_va_del(uint8_t uuid[16], uint16_t *addr) +uint8_t bt_mesh_va_del(const uint8_t uuid[16], uint16_t *addr) { struct bt_mesh_va *va = NULL; diff --git a/nimble/host/mesh/src/transport.h b/nimble/host/mesh/src/transport.h index 23be7139d6..bf458e83c8 100644 --- a/nimble/host/mesh/src/transport.h +++ b/nimble/host/mesh/src/transport.h @@ -106,8 +106,8 @@ struct bt_mesh_va *bt_mesh_va_get(uint16_t index); struct bt_mesh_va *bt_mesh_va_find(uint8_t uuid[16]); -uint8_t bt_mesh_va_add(uint8_t uuid[16], uint16_t *addr); +uint8_t bt_mesh_va_add(const uint8_t uuid[16], uint16_t *addr); -uint8_t bt_mesh_va_del(uint8_t uuid[16], uint16_t *addr); +uint8_t bt_mesh_va_del(const uint8_t uuid[16], uint16_t *addr); uint8_t *bt_mesh_va_label_get(uint16_t addr); \ No newline at end of file From 6253904845b4ab8afdc41eec21ff96211bed5106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 14:27:03 +0200 Subject: [PATCH 042/306] mesh: Fix restoring fast period divisor from settings The Health Fast Period Divisor is stored within the model publish parameters on the access layer. The opposite part for divisor restoring has been missed. this is port of 73e1c6a77d71f8b51746946f78f0b3525101e1c0 --- nimble/host/mesh/src/settings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index cb583eb35a..903230d1b5 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -552,6 +552,7 @@ static int mod_set_pub(struct bt_mesh_model *mod, char *val) mod->pub->ttl = 0; mod->pub->period = 0; mod->pub->retransmit = 0; + mod->pub->period_div = pub.period_div; mod->pub->count = 0; BT_DBG("Cleared publication for model"); From 16efc1651aac7f82714c89d6338407cb67383aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 29 Mar 2021 14:34:15 +0200 Subject: [PATCH 043/306] mesh: Send Link Close message when closing link Instead of silently closing the link we should send a Link Close message three times before resetting provisioning state. From Mesh Profile Specification v1.0.1.: ``` 5.3.1.4.3 Link Close message The Link Close message is used to close a link. ``` ``` 5.3.2 Link Establishment procedure The device shall start the link timer, set to 60 seconds, when the link is open. When the link timer expires, then the device shall close the link. ``` ``` 5.3.3 Generic Provisioning behavior If the sender does not receive a Transaction Acknowledgment message within 30 seconds after sending the first message in a transaction, the sender shall cancel the transaction, cancel the provisioning process and close the link. ``` From Mesh Profile Test Specification p6: ``` MESH/PVNR/PBADV/BV-01-C Test Procedure: [...] 6. The IUT is induced to send a Link Close message with the Reason field set to 0x02 to terminate the link. The message is sent at least three times to ensure the message is received by the Lower Tester. ``` this is port of 497d9df96acde1d28f7cd83c786e496e8ea0db67 --- nimble/host/mesh/src/pb_adv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/pb_adv.c b/nimble/host/mesh/src/pb_adv.c index 28391b1883..653ec03fa9 100644 --- a/nimble/host/mesh/src/pb_adv.c +++ b/nimble/host/mesh/src/pb_adv.c @@ -125,6 +125,7 @@ static void gen_prov_ack_send(uint8_t xact_id); static void link_open(struct prov_rx *rx, struct os_mbuf *buf); static void link_ack(struct prov_rx *rx, struct os_mbuf *buf); static void link_close(struct prov_rx *rx, struct os_mbuf *buf); +static void prov_link_close(enum prov_bearer_link_status status); static void buf_sent(int err, void *user_data) { @@ -281,7 +282,7 @@ static void protocol_timeout(struct ble_npl_event *work) BT_DBG(""); link.rx.seg = 0U; - close_link(PROV_BEARER_LINK_STATUS_TIMEOUT); + prov_link_close(PROV_BEARER_LINK_STATUS_TIMEOUT); } /******************************************************************************* * Generic provisioning From 01879ef557be49f966a7ab7393169e0b5f841bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 20 Apr 2021 10:52:17 +0200 Subject: [PATCH 044/306] bttester: Set Company ID to Intel Corp. Tests require CID to have valid value, listed in BT SIG Assigned Numbers/Company Identifiers. Let's set it to Intel Corp. (0x0002) This affects MESH/NODE/CFG/CFGF/BV-01-C --- apps/bttester/src/mesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bttester/src/mesh.c b/apps/bttester/src/mesh.c index 8226fe99e1..1ad322fe56 100644 --- a/apps/bttester/src/mesh.c +++ b/apps/bttester/src/mesh.c @@ -41,7 +41,7 @@ extern uint8_t own_addr_type; #define CONTROLLER_INDEX 0 -#define CID_LOCAL 0xffff +#define CID_LOCAL 0x0002 /* Health server data */ #define CUR_FAULTS_MAX 4 From bc1fe4e4320976d23d84db4c36f612741fb6245e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 22 Apr 2021 10:59:19 +0200 Subject: [PATCH 045/306] mesh: Set BT_MESH_ADV_USER_DATA_SIZE to size of 4 byte pointer this is affecting MESH/NODE/TNPT/BV-04-C --- nimble/host/mesh/src/adv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index 779ee58ed5..6566df9c18 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -17,7 +17,7 @@ #define BT_MESH_ADV_DATA_SIZE 31 /* The user data is a pointer (4 bytes) to struct bt_mesh_adv */ -#define BT_MESH_ADV_USER_DATA_SIZE (sizeof(struct bt_mesh_adv *)) +#define BT_MESH_ADV_USER_DATA_SIZE 4 #define BT_MESH_MBUF_HEADER_SIZE (sizeof(struct os_mbuf_pkthdr) + \ BT_MESH_ADV_USER_DATA_SIZE +\ From 7a5f6ec320eacc3b9bc35820bf88194243ea1078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 26 Apr 2021 09:15:56 +0200 Subject: [PATCH 046/306] mesh: Fix condition is net_tx_cred_get Preprocessor directives using defined() in mesh should use identifiers defined in glue.h --- nimble/host/mesh/src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 2e1d6dc7f4..db97b9549a 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -344,7 +344,7 @@ static void bt_mesh_net_local(struct ble_npl_event *work) static const struct bt_mesh_net_cred *net_tx_cred_get(struct bt_mesh_net_tx *tx) { -#if defined(BLE_MESH_LOW_POWER) +#if defined(CONFIG_BT_MESH_LOW_POWER) if (tx->friend_cred && bt_mesh_lpn_established()) { return &bt_mesh.lpn.cred[SUBNET_KEY_TX_IDX(tx->sub)]; } From fa8d955c93c4a8a14cb9ea029fa8e15ab3a0ac89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 26 Apr 2021 09:19:40 +0200 Subject: [PATCH 047/306] mesh: Delete duplication in config --- nimble/host/mesh/syscfg.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index 9683df432b..ada5b64a83 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -428,16 +428,6 @@ syscfg.defs: a value of 300 means 30 seconds. value: 300 - BLE_MESH_LPN_POLL_TIMEOUT: - description: > - PollTimeout timer is used to measure time between two - consecutive requests sent by the Low Power node. If no - requests are received by the Friend node before the - PollTimeout timer expires, then the friendship is considered - terminated. The value is in units of 100 milliseconds, so e.g. - a value of 300 means 30 seconds. - value: 300 - BLE_MESH_LPN_INIT_POLL_TIMEOUT: description: > The initial value of the PollTimeout timer when Friendship From 195313a8d9082f2a34a09002cc823005a9d0a9fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 30 Apr 2021 13:24:36 +0200 Subject: [PATCH 048/306] mesh: Fix incorrect pointer type in cdb.c --- nimble/host/mesh/src/provisioner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index 265dbf24d7..c51a769674 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -503,7 +503,7 @@ static void send_prov_data(void) #endif bt_mesh_prov_buf_init(pdu, PROV_DATA); #if MYNEWT_VAL(BLE_MESH_CDB) - net_buf_simple_add_mem(&pdu, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_key, 16); + net_buf_simple_add_mem(pdu, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_key, 16); net_buf_simple_add_be16(pdu, prov_device.node->net_idx); net_buf_simple_add_u8(pdu, bt_mesh_cdb_subnet_flags(sub)); net_buf_simple_add_be32(pdu, bt_mesh_cdb.iv_index); From 0fba723f06ab652a35f6bc02dd21d9a85e119e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 30 Apr 2021 13:25:45 +0200 Subject: [PATCH 049/306] bttester: Add lpn_cb Add support of lpn_cb (established and terminated). It's required for MESH/NODE/HBP-BV-05-C Allow to acces bt_mesh by apllications (required to fill btp response with valid data) --- apps/bttester/src/bttester.h | 21 ++++++++++++++++ apps/bttester/src/mesh.c | 37 ++++++++++++++++++++++++++++ nimble/host/mesh/include/mesh/mesh.h | 1 + 3 files changed, 59 insertions(+) diff --git a/apps/bttester/src/bttester.h b/apps/bttester/src/bttester.h index 6761681e15..4a8fc47142 100644 --- a/apps/bttester/src/bttester.h +++ b/apps/bttester/src/bttester.h @@ -997,6 +997,27 @@ struct mesh_invalid_bearer_ev { #define MESH_EV_INCOMP_TIMER_EXP 0x88 +#define MESH_EV_LPN_ESTABLISHED 0x8b +struct mesh_lpn_established_ev { + uint16_t net_idx; + uint16_t friend_addr; + uint8_t queue_size; + uint8_t recv_win; +} __packed; + +#define MESH_EV_LPN_TERMINATED 0x8c +struct mesh_lpn_terminated_ev { + uint16_t net_idx; + uint16_t friend_addr; +} __packed; + +#define MESH_EV_LPN_POLLED 0x8d +struct mesh_lpn_polled_ev { + uint16_t net_idx; + uint16_t friend_addr; + uint8_t retry; +} __packed; + void tester_init(void); void tester_rsp(uint8_t service, uint8_t opcode, uint8_t index, uint8_t status); void tester_send(uint8_t service, uint8_t opcode, uint8_t index, uint8_t *data, diff --git a/apps/bttester/src/mesh.c b/apps/bttester/src/mesh.c index 1ad322fe56..87bdbea430 100644 --- a/apps/bttester/src/mesh.c +++ b/apps/bttester/src/mesh.c @@ -937,11 +937,48 @@ static struct bt_test_cb bt_test_cb = { .mesh_trans_incomp_timer_exp = incomp_timer_exp_cb, }; +static void lpn_established(uint16_t friend_addr) +{ + + struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + struct mesh_lpn_established_ev ev = { lpn->sub->net_idx, friend_addr, lpn->queue_size, + lpn->recv_win }; + + SYS_LOG_DBG("Friendship (as LPN) established with " + "Friend 0x%04x Queue Size %d Receive Window %d", + friend_addr, lpn->queue_size, lpn->recv_win); + + tester_send(BTP_SERVICE_ID_MESH, MESH_EV_LPN_ESTABLISHED, + CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); +} + +static void lpn_terminated(uint16_t friend_addr) +{ + struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + struct mesh_lpn_terminated_ev ev = { lpn->sub->net_idx, friend_addr }; + + SYS_LOG_DBG("Friendship (as LPN) lost with Friend " + "0x%04x", friend_addr); + + tester_send(BTP_SERVICE_ID_MESH, MESH_EV_LPN_TERMINATED, + CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); +} + +void lpn_cb(uint16_t friend_addr, bool established) +{ + if (established) { + lpn_established(friend_addr); + } else { + lpn_terminated(friend_addr); + } +} + uint8_t tester_init_mesh(void) { health_pub_init(); if (IS_ENABLED(CONFIG_BT_TESTING)) { + bt_mesh_lpn_set_cb(lpn_cb); bt_test_cb_register(&bt_test_cb); } diff --git a/nimble/host/mesh/include/mesh/mesh.h b/nimble/host/mesh/include/mesh/mesh.h index b9bc24fb18..83390ec4ce 100644 --- a/nimble/host/mesh/include/mesh/mesh.h +++ b/nimble/host/mesh/include/mesh/mesh.h @@ -27,5 +27,6 @@ #include "cfg.h" #include "heartbeat.h" #include "../src/app_keys.h" +#include "../src/net.h" #endif /* __BT_MESH_H */ From 8fe37356da9ab934dcf55c7759cb26e595ffefe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 5 May 2021 12:23:20 +0200 Subject: [PATCH 050/306] mesh: Sync lpn.c with Zephyr --- nimble/host/mesh/src/lpn.c | 76 +++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/nimble/host/mesh/src/lpn.c b/nimble/host/mesh/src/lpn.c index bd48c0883e..45c9004b63 100644 --- a/nimble/host/mesh/src/lpn.c +++ b/nimble/host/mesh/src/lpn.c @@ -148,6 +148,24 @@ static inline void group_clear(atomic_t *target, atomic_t *source) static void clear_friendship(bool force, bool disable); +static int32_t poll_timeout(struct bt_mesh_lpn *lpn) +{ + /* If we're waiting for segment acks keep polling at high freq */ + if (bt_mesh_tx_in_progress()) { + return min(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1)); + } + + if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) { + lpn->poll_timeout *= 2; + lpn->poll_timeout = min(lpn->poll_timeout, + POLL_TIMEOUT_MAX(lpn)); + } + + BT_DBG("Poll Timeout is %ums", (unsigned) lpn->poll_timeout); + + return lpn->poll_timeout; +} + static void friend_clear_sent(int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; @@ -211,6 +229,7 @@ static void clear_friendship(bool force, bool disable) bt_mesh_rx_reset(); + lpn_set_state(BT_MESH_LPN_DISABLED); k_delayed_work_cancel(&lpn->timer); if (lpn->clear_success) { @@ -229,7 +248,7 @@ static void clear_friendship(bool force, bool disable) lpn->recv_win = 0; lpn->queue_size = 0; lpn->disable = 0; - lpn->sent_req = 0; + lpn->sent_req = 0U; lpn->established = 0; lpn->clear_success = 0; lpn->sub = NULL; @@ -246,13 +265,12 @@ static void clear_friendship(bool force, bool disable) bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER); - if (disable) { + if (!disable) { lpn_set_state(BT_MESH_LPN_DISABLED); + k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); return; } - lpn_set_state(BT_MESH_LPN_ENABLED); - k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); } static void friend_req_sent(uint16_t duration, int err, void *user_data) @@ -331,7 +349,7 @@ static void req_sent(uint16_t duration, int err, void *user_data) if (err) { BT_ERR("Sending request failed (err %d)", err); - lpn->sent_req = 0; + lpn->sent_req = 0U; group_zero(lpn->pending); return; } @@ -459,11 +477,14 @@ static void friend_response_received(struct bt_mesh_lpn *lpn) lpn->fsn++; } - k_delayed_work_cancel(&lpn->timer); bt_mesh_scan_disable(); lpn_set_state(BT_MESH_LPN_ESTABLISHED); lpn->req_attempts = 0; - lpn->sent_req = 0; + lpn->sent_req = 0U; + + int32_t timeout = poll_timeout(lpn); + + k_delayed_work_submit(&lpn->timer, K_MSEC(timeout)); } void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) @@ -476,6 +497,10 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) return; } + if (lpn->state != BT_MESH_LPN_WAIT_UPDATE) { + return; + } + if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) { BT_WARN("Unexpected message withouth a preceding Poll"); return; @@ -545,7 +570,6 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, } } /* TODO: Add offer acceptance criteria check */ - k_delayed_work_cancel(&lpn->timer); lpn->recv_win = msg->recv_win; lpn->queue_size = msg->queue_size; @@ -738,7 +762,7 @@ static void update_timeout(struct bt_mesh_lpn *lpn) if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { BT_WARN("Retrying first Friend Poll"); - lpn->sent_req = 0; + lpn->sent_req = 0U; if (send_friend_poll() == 0) { return; } @@ -793,7 +817,7 @@ static void lpn_timeout(struct ble_npl_event *work) if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { uint8_t req = lpn->sent_req; - lpn->sent_req = 0; + lpn->sent_req = 0U; if (!req || req == TRANS_CTL_OP_FRIEND_POLL) { send_friend_poll(); @@ -856,24 +880,6 @@ void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count) sub_update(TRANS_CTL_OP_FRIEND_SUB_REM); } -static int32_t poll_timeout(struct bt_mesh_lpn *lpn) -{ - /* If we're waiting for segment acks keep polling at high freq */ - if (bt_mesh_tx_in_progress()) { - return min(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1)); - } - - if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) { - lpn->poll_timeout *= 2; - lpn->poll_timeout = min(lpn->poll_timeout, - POLL_TIMEOUT_MAX(lpn)); - } - - BT_DBG("Poll Timeout is %ums", (unsigned) lpn->poll_timeout); - - return lpn->poll_timeout; -} - int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { @@ -932,12 +938,6 @@ int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx, send_friend_poll(); } - if (!lpn->sent_req) { - int32_t timeout = poll_timeout(lpn); - - k_delayed_work_submit(&lpn->timer, K_MSEC(timeout)); - } - return 0; } @@ -1020,12 +1020,6 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, send_friend_poll(); } - if (!lpn->sent_req) { - int32_t timeout = poll_timeout(lpn); - - k_delayed_work_submit(&lpn->timer, K_MSEC(timeout)); - } - return 0; } @@ -1073,8 +1067,6 @@ int bt_mesh_lpn_init(void) BT_DBG(""); - lpn->groups_changed = 0; - k_delayed_work_init(&lpn->timer, lpn_timeout); if (lpn->state == BT_MESH_LPN_ENABLED) { From 56838dd93564a9b03b137ad6d3f1651ad029bccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 5 May 2021 14:20:16 +0200 Subject: [PATCH 051/306] mesh: Set BLE_MESH_LPN_SUB_ALL_NODES_ADDR to off by default --- nimble/host/mesh/syscfg.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index ada5b64a83..d110a3888a 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -453,7 +453,7 @@ syscfg.defs: description: > Automatically subscribe all nodes address when friendship established. - value: 1 + value: 0 BLE_MESH_FRIEND: description: > From a62a2e37cc8f05c69da825a790d8b3680667d8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 6 May 2021 13:46:05 +0200 Subject: [PATCH 052/306] mesh: Fix typos in flags/frags --- nimble/host/mesh/src/adv.h | 3 +++ nimble/host/mesh/src/friend.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index 6566df9c18..38db786040 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -35,6 +35,9 @@ typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration, int err, void *user_data); struct bt_mesh_adv { + + struct net_buf *frags; + const struct bt_mesh_send_cb *cb; void *cb_data; diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 5918ecf5b1..354d31a651 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -125,6 +125,7 @@ static void purge_buffers(struct net_buf_slist_t *list) while (!net_buf_slist_is_empty(list)) { struct os_mbuf *buf; buf = (void *)net_buf_slist_get(list); + BT_MESH_ADV(buf)->frags = NULL; BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS; net_buf_unref(buf); } @@ -1235,7 +1236,7 @@ static void friend_timeout(struct ble_npl_event *work) /* Clear the flag we use for segment tracking */ BT_MESH_ADV(frnd->last)->flags &= ~NET_BUF_FRAGS; - BT_MESH_ADV(frnd->last)->flags = 0; + BT_MESH_ADV(frnd->last)->frags = 0; BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x", frnd->last, frnd->lpn); @@ -1381,6 +1382,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, uint64_t *seq_auth net_buf_slist_remove(&frnd->queue, prev, cur); frnd->queue_size--; + BT_MESH_ADV(buf)->frags = 0; net_buf_unref(buf); break; @@ -1622,6 +1624,7 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t add BT_DBG("PENDING SEGMENTS %d", pending_segments); /* Make sure old slist entry state doesn't remain */ + BT_MESH_ADV(buf)->frags = NULL; BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS; net_buf_unref(buf); From 5ea192af0108f72ab7f5ef0223e12f17c83e6841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 6 May 2021 13:59:41 +0200 Subject: [PATCH 053/306] bttester: Allow for more retransmit attempts in mesh This improves stability of transport tests --- apps/bttester/syscfg.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/bttester/syscfg.yml b/apps/bttester/syscfg.yml index db869c341b..7f99ded013 100644 --- a/apps/bttester/syscfg.yml +++ b/apps/bttester/syscfg.yml @@ -80,7 +80,7 @@ syscfg.vals: SHELL_TASK: 0 SHELL_NEWTMGR: 0 LOG_LEVEL: 12 - MSYS_1_BLOCK_COUNT: 80 + MSYS_1_BLOCK_COUNT: 100 BLE_MONITOR_RTT: 1 CONSOLE_RTT: 0 @@ -127,7 +127,8 @@ syscfg.vals: BLE_MESH_CFG_CLI: 1 BLE_MESH_RX_SDU_MAX: 110 BLE_MESH_HEALTH_CLI: 1 - BLE_MESH_FRIEND_QUEUE_SIZE: 32 + BLE_MESH_FRIEND_QUEUE_SIZE: 16 + BLE_MESH_SEG_RETRANSMIT_ATTEMPTS: 6 BLE_MESH_RX_SEG_MAX: 13 BLE_MESH_TX_SEG_MSG_COUNT: 2 BLE_MAX_CONNECTIONS: 8 From a4d3fb4368eb1952739121317f0aa64d54e1bcb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 7 May 2021 14:06:21 +0200 Subject: [PATCH 054/306] mesh: Fix macro in net.c --- nimble/host/mesh/src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index db97b9549a..bbe186ec8d 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -344,7 +344,7 @@ static void bt_mesh_net_local(struct ble_npl_event *work) static const struct bt_mesh_net_cred *net_tx_cred_get(struct bt_mesh_net_tx *tx) { -#if defined(CONFIG_BT_MESH_LOW_POWER) +#if IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) if (tx->friend_cred && bt_mesh_lpn_established()) { return &bt_mesh.lpn.cred[SUBNET_KEY_TX_IDX(tx->sub)]; } From 9b562a6546b6c46d16cdd9e0cf6d8cee8613989a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 24 Feb 2021 14:09:50 +0100 Subject: [PATCH 055/306] mesh: add frags to bt_mesh_adv struct bt_mesh_adv was lacking frags member. It was left out in few places or wrongly interpreted as "flags", causing the typo. --- nimble/host/mesh/src/adv.h | 4 ++-- nimble/host/mesh/src/friend.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index 38db786040..6dd2c8107c 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -35,8 +35,8 @@ typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration, int err, void *user_data); struct bt_mesh_adv { - - struct net_buf *frags; + /** Fragments associated with this buffer. */ + struct os_mbuf *frags; const struct bt_mesh_send_cb *cb; void *cb_data; diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 354d31a651..4742e89d36 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -1236,7 +1236,7 @@ static void friend_timeout(struct ble_npl_event *work) /* Clear the flag we use for segment tracking */ BT_MESH_ADV(frnd->last)->flags &= ~NET_BUF_FRAGS; - BT_MESH_ADV(frnd->last)->frags = 0; + BT_MESH_ADV(frnd->last)->frags = NULL; BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x", frnd->last, frnd->lpn); @@ -1382,8 +1382,8 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, uint64_t *seq_auth net_buf_slist_remove(&frnd->queue, prev, cur); frnd->queue_size--; - BT_MESH_ADV(buf)->frags = 0; - + /* Make sure old slist entry state doesn't remain */ + BT_MESH_ADV(buf)->frags = NULL; net_buf_unref(buf); break; } From aecd4b2038e38e825b2cafd74a7ca0bef7028cec Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 16 Jun 2021 11:10:22 +0200 Subject: [PATCH 056/306] ctype: Fix undefined behavior in ctype.h usage When parse.c is build against newlib nano following error shows up: iparse.c:304:20: error: array subscript has type 'char' [-Werror=char-subscripts] This can be easily fixed with casting to unsigned type first. --- apps/btshell/src/parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/btshell/src/parse.c b/apps/btshell/src/parse.c index a2e2ae5217..e4dbade420 100644 --- a/apps/btshell/src/parse.c +++ b/apps/btshell/src/parse.c @@ -301,7 +301,7 @@ parse_time_us(const char *str, int *out_status) uint32_t val_mult = 1; uint32_t val_us; - while (isdigit(*str)) { + while (isdigit((unsigned char)*str)) { val *= 10; val += *str - '0'; str++; @@ -309,7 +309,7 @@ parse_time_us(const char *str, int *out_status) if (*str == '.') { str++; - while (isdigit(*str)) { + while (isdigit((unsigned char)*str)) { val *= 10; val += *str - '0'; val_div *= 10; From c337666a34220e63d8eaf97b4f08bd889598092a Mon Sep 17 00:00:00 2001 From: Avamander Date: Tue, 22 Jun 2021 00:41:32 +0300 Subject: [PATCH 057/306] Removed an illogical check from npl_freertos_callout_reset --- porting/npl/freertos/src/npl_os_freertos.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/porting/npl/freertos/src/npl_os_freertos.c b/porting/npl/freertos/src/npl_os_freertos.c index 87936bd8de..ecc5cd7b1e 100644 --- a/porting/npl/freertos/src/npl_os_freertos.c +++ b/porting/npl/freertos/src/npl_os_freertos.c @@ -279,10 +279,6 @@ npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) { BaseType_t woken1, woken2, woken3; - if (ticks < 0) { - return BLE_NPL_INVALID_PARAM; - } - if (ticks == 0) { ticks = 1; } From 6df27f0fcf268a0611ed2986aa0e753920847da8 Mon Sep 17 00:00:00 2001 From: Prasad Alatkar Date: Tue, 5 Jan 2021 20:19:09 +0530 Subject: [PATCH 058/306] NimBLE host: Modify `ble_gap_wl_set` to support clearing complete whitelist * Modify test case `*_wl_bad_args` to accept 0 whitelist entries. --- nimble/host/src/ble_gap.c | 5 ----- nimble/host/test/src/ble_gap_test.c | 5 +++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 8e56df13fb..3125870fa6 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -2169,11 +2169,6 @@ ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count) ble_hs_lock(); - if (white_list_count == 0) { - rc = BLE_HS_EINVAL; - goto done; - } - for (i = 0; i < white_list_count; i++) { if (addrs[i].type != BLE_ADDR_PUBLIC && addrs[i].type != BLE_ADDR_RANDOM) { diff --git a/nimble/host/test/src/ble_gap_test.c b/nimble/host/test/src/ble_gap_test.c index 7496e31681..876ef8f257 100644 --- a/nimble/host/test/src/ble_gap_test.c +++ b/nimble/host/test/src/ble_gap_test.c @@ -449,9 +449,10 @@ TEST_CASE_SELF(ble_gap_test_case_wl_bad_args) ble_gap_test_util_init(); - /*** 0 white list entries. */ + /*** 0 white list entries. This is acceptable now with the wl_set API + * change. */ rc = ble_hs_test_util_wl_set(NULL, 0, 0, 0); - TEST_ASSERT(rc == BLE_HS_EINVAL); + TEST_ASSERT(rc == 0); /*** Invalid address type. */ rc = ble_hs_test_util_wl_set( From d0f0cad655d2568400d524f371f8073cc5549340 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 22 Jun 2021 12:04:17 +0200 Subject: [PATCH 059/306] nimble/ll: Fix TxAdd field for ADV_EXT_IND We never include AdvA on primary channel so TxAdd should be set to 0 as it's RFU in such case. --- nimble/controller/src/ble_ll_adv.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 092e813c25..6ab6b24331 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -550,11 +550,6 @@ ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) /* only ADV_EXT_IND goes on primary advertising channels */ pdu_type = BLE_ADV_PDU_TYPE_ADV_EXT_IND; - /* Set TxAdd to random if needed. */ - if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { - pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; - } - *hdr_byte = pdu_type; adv_mode = 0; From 39007724580f80678bb56b22bc657e68f05e3ab6 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 22 Jul 2021 14:51:42 +0200 Subject: [PATCH 060/306] nimble/ll: Fix scanner assert on receiving AUX_ADV_IND If scanned chain was truncated due to low buffers for HCI event we may be already too late to remove next AUX from scheduler and thus can receive next packet. Just ignore PDU if truncated was already sent. --- nimble/controller/src/ble_ll_scan.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 197ec91072..164b2ab641 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2606,6 +2606,16 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, goto done; } + /* Just ignore PDU if truncated was already sent. + * This can happen if next PDU in chain was already received before we + * manage to cancel scan on error (which resulted in sending truncated HCI + * event) + */ + if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)) { + rc = -1; + goto done; + } + /* * We keep one allocated event in aux_data to be able to truncate chain * properly in case of error. If there is no event in aux_data it means this @@ -2646,7 +2656,6 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, /* Need to send truncated event if we already sent some reports */ if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED)); - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; From 28533d46f8f7c77b2a00b9a71909cd17ea36e996 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 27 Jul 2021 15:53:41 +0200 Subject: [PATCH 061/306] apps: Add periodic advertising instance to ext_advertiser sample Add new instance that advertises 1650 bytes of periodic data. --- apps/ext_advertiser/src/main.c | 80 ++++++++++++++++++++++++++++++++++ apps/ext_advertiser/syscfg.yml | 9 ++-- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/apps/ext_advertiser/src/main.c b/apps/ext_advertiser/src/main.c index 6bbc23d598..86b728436e 100644 --- a/apps/ext_advertiser/src/main.c +++ b/apps/ext_advertiser/src/main.c @@ -411,6 +411,84 @@ start_non_connectable_ext(void) console_printf("instance %u started (non-con non-scan)\n", instance); } +static void start_periodic(void) +{ + struct ble_gap_periodic_adv_params pparams; + struct ble_gap_ext_adv_params params; + struct ble_hs_adv_fields adv_fields; + struct os_mbuf *data; + uint8_t instance = 5; + ble_addr_t addr; + int rc; + + /* For periodic we use nstance with non-connectable advertising */ + memset (¶ms, 0, sizeof(params)); + + /* advertise using random addr */ + params.own_addr_type = BLE_OWN_ADDR_RANDOM; + + params.primary_phy = BLE_HCI_LE_PHY_1M; + params.secondary_phy = BLE_HCI_LE_PHY_1M; + params.tx_power = 127; + params.sid = 2; + + /* configure instance 0 */ + rc = ble_gap_ext_adv_configure(instance, ¶ms, NULL, NULL, NULL); + assert (rc == 0); + + /* set random (NRPA) address for instance */ + rc = ble_hs_id_gen_rnd(1, &addr); + assert (rc == 0); + + rc = ble_gap_ext_adv_set_addr(instance, &addr ); + assert (rc == 0); + + memset(&adv_fields, 0, sizeof(adv_fields)); + adv_fields.name = (const uint8_t *)"nimble with periodic"; + adv_fields.name_len = strlen((char *)adv_fields.name); + + /* Default to legacy PDUs size, mbuf chain will be increased if needed + */ + data = os_msys_get_pkthdr(BLE_HCI_MAX_ADV_DATA_LEN, 0); + assert(data); + + rc = ble_hs_adv_set_fields_mbuf(&adv_fields, data); + assert(rc == 0); + + rc = ble_gap_ext_adv_set_data(instance, data); + assert(rc == 0); + + /* configure periodic advertising */ + memset(&pparams, 0, sizeof(pparams)); + pparams.include_tx_power = 1; + pparams.itvl_min = 160; + pparams.itvl_max = 240; + + rc = ble_gap_periodic_adv_configure(instance, &pparams); + assert(rc == 0); + + /* get mbuf for periodic data */ + data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0); + assert(data); + + /* fill mbuf with periodic data */ + rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); + assert(rc == 0); + + rc = ble_gap_periodic_adv_set_data(instance, data); + assert (rc == 0); + + /* start periodic advertising */ + rc = ble_gap_periodic_adv_start(instance); + assert (rc == 0); + + /* start advertising */ + rc = ble_gap_ext_adv_start(instance, 0, 0); + assert (rc == 0); + + console_printf("instance %u started (periodic)\n", instance); +} + static void on_sync(void) { @@ -435,6 +513,8 @@ on_sync(void) start_legacy_duration(0, true); start_ext_max_events(0, true); + + start_periodic(); } /* diff --git a/apps/ext_advertiser/syscfg.yml b/apps/ext_advertiser/syscfg.yml index 5f5fb54b95..f157ab82b0 100644 --- a/apps/ext_advertiser/syscfg.yml +++ b/apps/ext_advertiser/syscfg.yml @@ -30,6 +30,9 @@ syscfg.vals: # Enable Extended Advertising BLE_EXT_ADV: 1 + # Enable Periodic Advertising + BLE_PERIODIC_ADV: 1 + # Max advertising data size BLE_EXT_ADV_MAX_SIZE: 1650 @@ -37,12 +40,12 @@ syscfg.vals: # to historical reasonds total number of advertising # instances is BLE_MULTI_ADV_INSTANCES + 1 as instance # 0 is always available - BLE_MULTI_ADV_INSTANCES: 4 + BLE_MULTI_ADV_INSTANCES: 5 # Controller uses msys pool for storing advertising data and scan responses. - # Since we advertise a lot of data (~4k in total) at the same time we need + # Since we advertise a lot of data (~6k in total) at the same time we need # to increase block count. - MSYS_1_BLOCK_COUNT: 24 + MSYS_1_BLOCK_COUNT: 32 # Whether to save data to sys/config, or just keep it in RAM. BLE_STORE_CONFIG_PERSIST: 0 From 498f3ad1cefd6351610a33e8dc2e2136c6d71efb Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 30 Jul 2021 15:23:46 +0200 Subject: [PATCH 062/306] transport/nrf5340: Fix assignment in assert Fix typo in assert which make it never catch intended error. --- nimble/transport/nrf5340/src/nrf5340_ble_hci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c index c0276c324c..9bf956b56b 100644 --- a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c +++ b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c @@ -272,10 +272,10 @@ nrf5340_ble_hci_trans_rx_process(int channel) rxd->expected_len = 0; #if MYNEWT_VAL(BLE_CONTROLLER) - assert((rxd->type == HCI_PKT_ACL) || (rxd->type = HCI_PKT_CMD)); + assert((rxd->type == HCI_PKT_ACL) || (rxd->type == HCI_PKT_CMD)); #endif #if MYNEWT_VAL(BLE_HOST) - assert((rxd->type == HCI_PKT_ACL) || (rxd->type = HCI_PKT_EVT)); + assert((rxd->type == HCI_PKT_ACL) || (rxd->type == HCI_PKT_EVT)); #endif break; #if MYNEWT_VAL(BLE_CONTROLLER) From 14acdf165829126f4af2007db37980ffa2fe4750 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 30 Jul 2021 12:02:23 +0200 Subject: [PATCH 063/306] nimble/ll: Use callout for scan duration and period hal_timer executes from ISR which was preempting LL task and could result in HCI flow issues if unlucky. --- .../include/controller/ble_ll_scan.h | 8 +-- nimble/controller/src/ble_ll_scan.c | 49 +++++++++---------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index 139ad5e1f7..9bbd4d6900 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -175,10 +175,10 @@ struct ble_ll_scan_sm struct ble_npl_event scan_interrupted_ev; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct hal_timer duration_timer; - struct hal_timer period_timer; - uint32_t duration_ticks; - uint32_t period_ticks; + struct ble_npl_callout duration_timer; + struct ble_npl_callout period_timer; + ble_npl_time_t duration_ticks; + ble_npl_time_t period_ticks; uint8_t ext_scanning; #endif diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 164b2ab641..44bb878941 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -3431,30 +3431,28 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) static void ble_ll_scan_duration_period_timers_restart(struct ble_ll_scan_sm *scansm) { - uint32_t now; + ble_npl_time_t now; - now = os_cputime_get32(); + now = ble_npl_time_get(); - os_cputime_timer_stop(&scansm->duration_timer); - os_cputime_timer_stop(&scansm->period_timer); + ble_npl_callout_stop(&scansm->duration_timer); + ble_npl_callout_stop(&scansm->period_timer); if (scansm->duration_ticks) { - os_cputime_timer_start(&scansm->duration_timer, + ble_npl_callout_reset(&scansm->duration_timer, now + scansm->duration_ticks); if (scansm->period_ticks) { - os_cputime_timer_start(&scansm->period_timer, + ble_npl_callout_reset(&scansm->period_timer, now + scansm->period_ticks); } } } static void -ble_ll_scan_duration_timer_cb(void *arg) +ble_ll_scan_duration_timer_cb(struct ble_npl_event *ev) { - struct ble_ll_scan_sm *scansm; - - scansm = (struct ble_ll_scan_sm *)arg; + struct ble_ll_scan_sm *scansm = ble_npl_event_get_arg(ev); ble_ll_scan_sm_stop(2); @@ -3465,9 +3463,9 @@ ble_ll_scan_duration_timer_cb(void *arg) } static void -ble_ll_scan_period_timer_cb(void *arg) +ble_ll_scan_period_timer_cb(struct ble_npl_event *ev) { - struct ble_ll_scan_sm *scansm = arg; + struct ble_ll_scan_sm *scansm = ble_npl_event_get_arg(ev); ble_ll_scan_sm_start(scansm); @@ -3497,8 +3495,8 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, struct ble_ll_scan_params *scanp_phy; int i; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - uint32_t period_ticks = 0; - uint32_t dur_ticks = 0; + ble_npl_time_t period_ticks = 0; + ble_npl_time_t dur_ticks = 0; #endif /* Check for valid parameters */ @@ -3518,16 +3516,13 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, period = 0; } - /* period is in 1.28 sec units - * TODO support full range, would require os_cputime milliseconds API - */ - if (period > 3355) { + /* period is in 1.28 sec units */ + if (ble_npl_time_ms_to_ticks(period * 1280, &period_ticks)) { return BLE_ERR_INV_HCI_CMD_PARMS; } - period_ticks = os_cputime_usecs_to_ticks(period * 1280000); /* duration is in 10ms units */ - dur_ticks = os_cputime_usecs_to_ticks(dur * 10000); + dur_ticks = ble_npl_time_ms_to_ticks32(dur * 10); if (dur_ticks && period_ticks && (dur_ticks >= period_ticks)) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -3541,8 +3536,8 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, ble_ll_scan_sm_stop(1); } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - os_cputime_timer_stop(&scansm->duration_timer); - os_cputime_timer_stop(&scansm->period_timer); + ble_npl_callout_stop(&scansm->duration_timer); + ble_npl_callout_stop(&scansm->period_timer); #endif return BLE_ERR_SUCCESS; @@ -3910,10 +3905,10 @@ ble_ll_scan_common_init(void) /* Initialize extended scan timers */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - os_cputime_timer_init(&scansm->duration_timer, + ble_npl_callout_init(&scansm->duration_timer, &g_ble_ll_data.ll_evq, ble_ll_scan_duration_timer_cb, scansm); - os_cputime_timer_init(&scansm->period_timer, ble_ll_scan_period_timer_cb, - scansm); + ble_npl_callout_init(&scansm->period_timer, &g_ble_ll_data.ll_evq, + ble_ll_scan_period_timer_cb, scansm); #endif ble_npl_event_init(&scansm->scan_interrupted_ev, ble_ll_scan_interrupted_event_cb, NULL); @@ -3939,8 +3934,8 @@ ble_ll_scan_reset(void) /* stop extended scan timers */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - os_cputime_timer_stop(&scansm->duration_timer); - os_cputime_timer_stop(&scansm->period_timer); + ble_npl_callout_stop(&scansm->duration_timer); + ble_npl_callout_stop(&scansm->period_timer); #endif /* Reset duplicate advertisers and those from which we rxd a response */ From a472cf519c1984700bb201539c8697b0e7aff0f3 Mon Sep 17 00:00:00 2001 From: vrahane Date: Tue, 10 Aug 2021 11:54:45 -0700 Subject: [PATCH 064/306] controller/ble_ll_scan: For callouts number of ticks are used --- nimble/controller/src/ble_ll_scan.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 44bb878941..e67d8063c0 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -3431,20 +3431,16 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) static void ble_ll_scan_duration_period_timers_restart(struct ble_ll_scan_sm *scansm) { - ble_npl_time_t now; - - now = ble_npl_time_get(); - ble_npl_callout_stop(&scansm->duration_timer); ble_npl_callout_stop(&scansm->period_timer); if (scansm->duration_ticks) { ble_npl_callout_reset(&scansm->duration_timer, - now + scansm->duration_ticks); + scansm->duration_ticks); if (scansm->period_ticks) { ble_npl_callout_reset(&scansm->period_timer, - now + scansm->period_ticks); + scansm->period_ticks); } } } From 7c581b0734406fd1ed698a11e54c69940b01ed5e Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 12 Jul 2021 14:49:01 +0200 Subject: [PATCH 065/306] nimble/host: Fix txom leaks in ble_sm_tx and ble_l2cap_sig_tx Those functions are expected to always consume txom. --- nimble/host/src/ble_l2cap_sig_cmd.c | 3 +++ nimble/host/src/ble_sm_cmd.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/nimble/host/src/ble_l2cap_sig_cmd.c b/nimble/host/src/ble_l2cap_sig_cmd.c index d9e507e258..48b35249ec 100644 --- a/nimble/host/src/ble_l2cap_sig_cmd.c +++ b/nimble/host/src/ble_l2cap_sig_cmd.c @@ -21,6 +21,7 @@ #include "ble_hs_priv.h" #if NIMBLE_BLE_CONNECT +/* this function consumes tx os_mbuf */ int ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom) { @@ -33,6 +34,8 @@ ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom) &conn, &chan); if (rc == 0) { rc = ble_l2cap_tx(conn, chan, txom); + } else { + os_mbuf_free_chain(txom); } ble_hs_unlock(); diff --git a/nimble/host/src/ble_sm_cmd.c b/nimble/host/src/ble_sm_cmd.c index 2983102cd1..b84df1ec75 100644 --- a/nimble/host/src/ble_sm_cmd.c +++ b/nimble/host/src/ble_sm_cmd.c @@ -63,6 +63,8 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom) &conn, &chan); if (rc == 0) { rc = ble_l2cap_tx(conn, chan, txom); + } else { + os_mbuf_free_chain(txom); } return rc; From 8b9a2aea41b2579126c191f55ae19a526c7b37c8 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 9 Mar 2021 17:33:03 +0100 Subject: [PATCH 066/306] nimble/ll: Fix scan interval adjust for continuous scan --- nimble/controller/src/ble_ll_scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index e67d8063c0..7eac16b5ae 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -3416,7 +3416,7 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) } if (uncoded->timing.interval == uncoded->timing.window) { - uncoded->timing.window += coded->timing.window; + uncoded->timing.interval += coded->timing.window; } } From 87f1d1da6cabc1c5ded863544d2e4df97a3003b3 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 25 Aug 2021 08:42:44 +0200 Subject: [PATCH 067/306] nimble/host: Sync sending Host Number of Completed Packets command Host Number of Completed Packets command is special as it doesn't generate status event and thus is not send with ble_hs_hci_cmd_tx. We should stil sync sending it with ble_hs_hci_cmd_tx() though to avoid requesting more than one command buffer from HCI transport (which may not be able to provide more). --- nimble/host/src/ble_hs_flow.c | 2 +- nimble/host/src/ble_hs_hci.c | 14 ++++++++++++++ nimble/host/src/ble_hs_hci_priv.h | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/nimble/host/src/ble_hs_flow.c b/nimble/host/src/ble_hs_flow.c index 2520c85415..1eabba9e0c 100644 --- a/nimble/host/src/ble_hs_flow.c +++ b/nimble/host/src/ble_hs_flow.c @@ -92,7 +92,7 @@ ble_hs_flow_tx_num_comp_pkts(void) * response from the controller, so don't use the normal blocking * HCI API when sending it. */ - rc = ble_hs_hci_cmd_send_buf( + rc = ble_hs_hci_cmd_tx_no_rsp( BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS), buf, sizeof(buf)); diff --git a/nimble/host/src/ble_hs_hci.c b/nimble/host/src/ble_hs_hci.c index ac472a9ea5..e5c3a741e5 100644 --- a/nimble/host/src/ble_hs_hci.c +++ b/nimble/host/src/ble_hs_hci.c @@ -291,6 +291,20 @@ ble_hs_hci_wait_for_ack(void) return rc; } +int +ble_hs_hci_cmd_tx_no_rsp(uint16_t opcode, const void *cmd, uint8_t cmd_len) +{ + int rc; + + ble_hs_hci_lock(); + + rc = ble_hs_hci_cmd_send_buf(opcode, cmd, cmd_len); + + ble_hs_hci_unlock(); + + return rc; +} + int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len, void *rsp, uint8_t rsp_len) diff --git a/nimble/host/src/ble_hs_hci_priv.h b/nimble/host/src/ble_hs_hci_priv.h index b02d4ab2e8..11e544f18f 100644 --- a/nimble/host/src/ble_hs_hci_priv.h +++ b/nimble/host/src/ble_hs_hci_priv.h @@ -81,6 +81,8 @@ struct hci_periodic_adv_params extern uint16_t ble_hs_hci_avail_pkts; +/* This function is not waiting for command status/complete HCI events */ +int ble_hs_hci_cmd_tx_no_rsp(uint16_t opcode, const void *cmd, uint8_t cmd_len); int ble_hs_hci_cmd_tx(uint16_t opcode, const void *cmd, uint8_t cmd_len, void *rsp, uint8_t rsp_len); void ble_hs_hci_init(void); From 9d3383b5ebb5dd1ba7a682acbf0ba768ccacbce6 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Mon, 5 Jul 2021 14:38:12 +0200 Subject: [PATCH 068/306] porting/npl/riot: add namespaced syscfg symlink --- porting/npl/riot/include/npl_syscfg/npl_sycfg.h | 1 + 1 file changed, 1 insertion(+) create mode 120000 porting/npl/riot/include/npl_syscfg/npl_sycfg.h diff --git a/porting/npl/riot/include/npl_syscfg/npl_sycfg.h b/porting/npl/riot/include/npl_syscfg/npl_sycfg.h new file mode 120000 index 0000000000..53c55a90b9 --- /dev/null +++ b/porting/npl/riot/include/npl_syscfg/npl_sycfg.h @@ -0,0 +1 @@ +../syscfg/syscfg.h \ No newline at end of file From 7d3f3cc6afce62a628404856fe4f90e27e04350a Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Mon, 19 Apr 2021 15:47:49 +0200 Subject: [PATCH 069/306] porting/nimble/src/nimble_port: riot initializes timers --- porting/nimble/src/nimble_port.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/porting/nimble/src/nimble_port.c b/porting/nimble/src/nimble_port.c index 484e37995c..d4824d0b37 100644 --- a/porting/nimble/src/nimble_port.c +++ b/porting/nimble/src/nimble_port.c @@ -45,8 +45,10 @@ nimble_port_init(void) #if NIMBLE_CFG_CONTROLLER ble_hci_ram_init(); +#ifndef RIOT_VERSION hal_timer_init(5, NULL); os_cputime_init(32768); +#endif ble_ll_init(); #endif } From ddf8043d1b97f1600aa88c53bd935d0fc9b22c9c Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Tue, 8 Jun 2021 11:57:36 +0200 Subject: [PATCH 070/306] l2cap: implement echo request-response procedure --- nimble/host/include/host/ble_l2cap.h | 22 +++++ nimble/host/src/ble_l2cap.c | 7 ++ nimble/host/src/ble_l2cap_sig.c | 120 ++++++++++++++++++++++++++- nimble/host/src/ble_l2cap_sig_priv.h | 2 + 4 files changed, 150 insertions(+), 1 deletion(-) diff --git a/nimble/host/include/host/ble_l2cap.h b/nimble/host/include/host/ble_l2cap.h index aef9682cc4..5c5383b261 100644 --- a/nimble/host/include/host/ble_l2cap.h +++ b/nimble/host/include/host/ble_l2cap.h @@ -246,6 +246,8 @@ struct ble_l2cap_chan_info { typedef int ble_l2cap_event_fn(struct ble_l2cap_event *event, void *arg); +typedef void ble_l2cap_ping_fn(uint16_t conn_handle, uint32_t rtt_ms, + struct os_mbuf *om); uint16_t ble_l2cap_get_conn_handle(struct ble_l2cap_chan *chan); int ble_l2cap_create_server(uint16_t psm, uint16_t mtu, @@ -259,6 +261,26 @@ int ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx); int ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx); int ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info); +/** + * Send an ECHO_REQ packet over the L2CAP signalling channel for the given + * connection + * + * @param conn_handle Connection handle + * @param cb Function called once the corresponding ECHO_RSP is + * received. May be NULL. + * @param data User payload appended to the ECHO_REQ packet, may be + * NULL + * @param data_len Length of @p data in bytes. Set to 0 to omit any user + * payload + * + * @return 0 on success + * BLE_HS_EBADDATA if given payload is invalid + * BLE_HS_ENOMEM if request packet cannot be allocated + * BLE_HS_ENOTCONN if not connected + */ +int ble_l2cap_ping(uint16_t conn_handle, ble_l2cap_ping_fn cb, + const void *data, uint16_t data_len); + #ifdef __cplusplus } #endif diff --git a/nimble/host/src/ble_l2cap.c b/nimble/host/src/ble_l2cap.c index 2bc50e0e93..a2c5156339 100644 --- a/nimble/host/src/ble_l2cap.c +++ b/nimble/host/src/ble_l2cap.c @@ -178,6 +178,13 @@ ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info return 0; } +int +ble_l2cap_ping(uint16_t conn_handle, ble_l2cap_ping_fn cb, + const void *data, uint16_t data_len) +{ + return ble_l2cap_sig_ping(conn_handle, cb, data, data_len); +} + int ble_l2cap_enhanced_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, diff --git a/nimble/host/src/ble_l2cap_sig.c b/nimble/host/src/ble_l2cap_sig.c index aaf9c642a4..fab16ea441 100644 --- a/nimble/host/src/ble_l2cap_sig.c +++ b/nimble/host/src/ble_l2cap_sig.c @@ -60,6 +60,7 @@ #define BLE_L2CAP_SIG_PROC_OP_RECONFIG 2 #define BLE_L2CAP_SIG_PROC_OP_DISCONNECT 3 #define BLE_L2CAP_SIG_PROC_OP_MAX 4 +#define BLE_L2CAP_SIG_PROC_OP_PING 5 #if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC) #define BLE_L2CAP_ECOC_MIN_MTU (64) @@ -97,6 +98,10 @@ struct ble_l2cap_sig_proc { uint16_t new_mtu; } reconfig; #endif + struct { + ble_l2cap_ping_fn *cb; + ble_npl_time_t time_sent; + } ping; }; }; @@ -112,6 +117,10 @@ static ble_l2cap_sig_rx_fn ble_l2cap_sig_rx_noop; static ble_l2cap_sig_rx_fn ble_l2cap_sig_update_req_rx; static ble_l2cap_sig_rx_fn ble_l2cap_sig_update_rsp_rx; static ble_l2cap_sig_rx_fn ble_l2cap_sig_rx_reject; +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 +static ble_l2cap_sig_rx_fn ble_l2cap_sig_echo_req; +static ble_l2cap_sig_rx_fn ble_l2cap_sig_echo_rsp; +#endif #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 static ble_l2cap_sig_rx_fn ble_l2cap_sig_coc_req_rx; @@ -145,7 +154,10 @@ static ble_l2cap_sig_rx_fn * const ble_l2cap_sig_dispatch[] = { [BLE_L2CAP_SIG_OP_CONFIG_RSP] = ble_l2cap_sig_rx_noop, [BLE_L2CAP_SIG_OP_DISCONN_REQ] = ble_l2cap_sig_disc_req_rx, [BLE_L2CAP_SIG_OP_DISCONN_RSP] = ble_l2cap_sig_disc_rsp_rx, - [BLE_L2CAP_SIG_OP_ECHO_RSP] = ble_l2cap_sig_rx_noop, +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 + [BLE_L2CAP_SIG_OP_ECHO_REQ] = ble_l2cap_sig_echo_req, + [BLE_L2CAP_SIG_OP_ECHO_RSP] = ble_l2cap_sig_echo_rsp, +#endif [BLE_L2CAP_SIG_OP_INFO_RSP] = ble_l2cap_sig_rx_noop, [BLE_L2CAP_SIG_OP_CREATE_CHAN_RSP] = ble_l2cap_sig_rx_noop, [BLE_L2CAP_SIG_OP_MOVE_CHAN_RSP] = ble_l2cap_sig_rx_noop, @@ -1632,6 +1644,58 @@ ble_l2cap_sig_disc_rsp_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, return 0; } +static int +ble_l2cap_sig_echo_req(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, + struct os_mbuf **om) +{ + void *rsp; + struct os_mbuf *txom; + struct ble_l2cap_sig_hdr *rsp_hdr; + int rc; + + /* we temporarily set size to 0 as we do not want to allocate additional + * space yet */ + rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_ECHO_RSP, + hdr->identifier, 0, &txom); + if (rsp == NULL) { + return BLE_HS_ENOMEM; + } + rc = os_mbuf_appendfrom(txom, *om, 0, OS_MBUF_PKTLEN(*om)); + if (rc != 0) { + os_mbuf_free_chain(txom); + return BLE_HS_ENOMEM; + } + /* after copying the request payload into the response, we need to adjust + * the size field in the header to the actual value */ + rsp_hdr = (struct ble_l2cap_sig_hdr *)txom->om_data; + rsp_hdr->length = htole16(OS_MBUF_PKTLEN(*om)); + + return ble_l2cap_sig_tx(conn_handle, txom); +} + +static int +ble_l2cap_sig_echo_rsp(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, + struct os_mbuf **om) +{ + struct ble_l2cap_sig_proc *proc; + uint32_t rtt_ms; + + proc = ble_l2cap_sig_proc_extract(conn_handle, BLE_L2CAP_SIG_PROC_OP_PING, + hdr->identifier); + if (proc == NULL) { + return BLE_HS_ENOENT; + } + + if (proc->ping.cb != NULL) { + ble_npl_time_t now = ble_npl_time_get(); + rtt_ms = ble_npl_time_ticks_to_ms32(now - proc->ping.time_sent); + proc->ping.cb(conn_handle, rtt_ms, *om); + ble_l2cap_sig_proc_free(proc); + } + + return 0; +} + int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan) { @@ -1869,6 +1933,60 @@ ble_l2cap_sig_extract_expired(struct ble_l2cap_sig_proc_list *dst_list) return next_exp_in; } +int +ble_l2cap_sig_ping(uint16_t conn_handle, ble_l2cap_ping_fn cb, + const void *data, uint16_t data_len) +{ + struct ble_l2cap_sig_proc *proc; + struct os_mbuf *txom; + void *req; + struct ble_l2cap_sig_hdr *hdr; + int rc; + + if ((data_len > 0) && (data == NULL)) { + return BLE_HS_EBADDATA; + } + + ble_hs_lock(); + proc = ble_l2cap_sig_proc_alloc(); + ble_hs_unlock(); + + if (!proc) { + return BLE_HS_ENOMEM; + } + + /* allocate and fill procedure context */ + proc->op = BLE_L2CAP_SIG_PROC_OP_PING; + proc->id = ble_l2cap_sig_next_id(); + proc->conn_handle = conn_handle; + proc->ping.cb = cb; + proc->ping.time_sent = ble_npl_time_get(); + + /* allocate signalling packet and copy payload into packet */ + req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_ECHO_REQ, + proc->id, 0, &txom); + if (req == NULL) { + ble_l2cap_sig_proc_free(proc); + return BLE_HS_ENOMEM; + } + if (data_len > 0) { + rc = os_mbuf_append(txom, data, data_len); + if (rc != 0) { + os_mbuf_free_chain(txom); + ble_l2cap_sig_proc_free(proc); + return BLE_HS_ENOMEM; + } + /* adjust the size field in the signalling header */ + hdr = (struct ble_l2cap_sig_hdr *)txom->om_data; + hdr->length = htole16(data_len); + } + + + rc = ble_l2cap_sig_tx(proc->conn_handle, txom); + ble_l2cap_sig_process_status(proc, rc); + return rc; +} + void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason) { diff --git a/nimble/host/src/ble_l2cap_sig_priv.h b/nimble/host/src/ble_l2cap_sig_priv.h index a698cd0d8f..55b37cd206 100644 --- a/nimble/host/src/ble_l2cap_sig_priv.h +++ b/nimble/host/src/ble_l2cap_sig_priv.h @@ -172,6 +172,8 @@ ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], } #endif +int ble_l2cap_sig_ping(uint16_t conn_handle, ble_l2cap_ping_fn cb, + const void *data, uint16_t data_len); void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason); int32_t ble_l2cap_sig_timer(void); struct ble_l2cap_chan *ble_l2cap_sig_create_chan(uint16_t conn_handle); From 891a0c949652ab3489d02f0d463f210683b9c2ae Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Thu, 9 Sep 2021 10:40:35 +0200 Subject: [PATCH 071/306] npl/riot: simplify ble_npl_hw_is_in_critical() Recently the RIOT IRQ API was extended to support irq_is_enabled(), so time to switch away from the hacked implementation of ble_npl_hw_is_in_critical(). --- porting/npl/riot/include/nimble/nimble_npl_os.h | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/porting/npl/riot/include/nimble/nimble_npl_os.h b/porting/npl/riot/include/nimble/nimble_npl_os.h index d279d250a8..ee0dfab340 100644 --- a/porting/npl/riot/include/nimble/nimble_npl_os.h +++ b/porting/npl/riot/include/nimble/nimble_npl_os.h @@ -38,8 +38,6 @@ extern "C" { typedef uint32_t ble_npl_time_t; typedef int32_t ble_npl_stime_t; -extern volatile int ble_npl_in_critical; - struct ble_npl_event { event_callback_t e; void *arg; @@ -257,27 +255,19 @@ ble_npl_time_delay(ble_npl_time_t ticks) static inline uint32_t ble_npl_hw_enter_critical(void) { - uint32_t ctx = irq_disable(); - ++ble_npl_in_critical; - return ctx; + return (uint32_t)irq_disable(); } static inline void ble_npl_hw_exit_critical(uint32_t ctx) { - --ble_npl_in_critical; irq_restore((unsigned)ctx); } static inline bool ble_npl_hw_is_in_critical(void) { - /* - * XXX Currently RIOT does not support an API for finding out if interrupts - * are currently disabled, hence in a critical section in this context. - * So for now, we use this global variable to keep this state for us. - -*/ - return (ble_npl_in_critical > 0); + return (bool)!irq_is_enabled(); } #ifdef __cplusplus From 11f4348c79cc69f03fb9fce69776572e157e4d96 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 13 Sep 2021 09:27:44 +0200 Subject: [PATCH 072/306] transport/usb: Fix potential buffer overrun When HCI command was received from USB transport cmd_len was not checked and was used for memcpy. It could lead to memory corruption if USB stack called this function with size exceeding maximum command size. This is currently possible scenario with TinyUSB stack (it will be fixed there as well). --- nimble/transport/usb/src/ble_hci_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/transport/usb/src/ble_hci_usb.c b/nimble/transport/usb/src/ble_hci_usb.c index d09421bb20..3f87856f11 100644 --- a/nimble/transport/usb/src/ble_hci_usb.c +++ b/nimble/transport/usb/src/ble_hci_usb.c @@ -229,7 +229,7 @@ tud_bt_hci_cmd_cb(void *hci_cmd, size_t cmd_len) if (ble_hci_usb_rx_cmd_ll_cb) { buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); assert(buf != NULL); - memcpy(buf, hci_cmd, cmd_len); + memcpy(buf, hci_cmd, min(cmd_len, BLE_HCI_TRANS_CMD_SZ)); rc = ble_hci_usb_rx_cmd_ll_cb(buf, ble_hci_usb_rx_cmd_ll_arg); } From fcb617a2ef533460b92bcd030aef81e3ed7106b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 19 Jul 2021 11:07:54 +0200 Subject: [PATCH 073/306] host/l2cap: send command reject in L2CAP disc req for invalid CID If ble_hs_conn_chan_find_by_scid fails to find channel, it means that destination CID in L2CAP Disconnection Request is invalid. Send L2CAP_COMMAND_REJECT_RSP with BLE_L2CAP_SIG_ERR_INVALID_CID reason. This is affecting L2CAP/LE/CFC/BV-23-C --- nimble/host/src/ble_l2cap_sig.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/nimble/host/src/ble_l2cap_sig.c b/nimble/host/src/ble_l2cap_sig.c index fab16ea441..2a36161998 100644 --- a/nimble/host/src/ble_l2cap_sig.c +++ b/nimble/host/src/ble_l2cap_sig.c @@ -1552,7 +1552,13 @@ ble_l2cap_sig_disc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, * is from peer perspective. It is source CID from nimble perspective */ chan = ble_hs_conn_chan_find_by_scid(conn, le16toh(req->dcid)); - if (!chan || (le16toh(req->scid) != chan->dcid)) { + if (!chan) { + os_mbuf_free_chain(txom); + ble_hs_unlock(); + ble_l2cap_sig_reject_invalid_cid_tx(conn_handle, hdr->identifier, req->dcid, req->scid); + return 0; + } + if (le16toh(req->scid) != chan->dcid) { os_mbuf_free_chain(txom); ble_hs_unlock(); return 0; From e0b15dadd1d3007879b912ad48a481ed1a4bffec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 2 Aug 2021 10:28:09 +0200 Subject: [PATCH 074/306] host/tests: add test for invalid CID in disconnection request --- nimble/host/test/src/ble_hs_test_util.h | 2 + nimble/host/test/src/ble_l2cap_test.c | 64 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/nimble/host/test/src/ble_hs_test_util.h b/nimble/host/test/src/ble_hs_test_util.h index 411443cfdd..7a0aa3eb19 100644 --- a/nimble/host/test/src/ble_hs_test_util.h +++ b/nimble/host/test/src/ble_hs_test_util.h @@ -162,6 +162,8 @@ int ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid, const void *data, int len); uint8_t ble_hs_test_util_verify_tx_l2cap_sig(uint16_t opcode, void *cmd, uint16_t cmd_size); +uint8_t ble_hs_test_util_verify_tx_l2cap_discon_rej(uint16_t opcode, void *cmd, + uint16_t cmd_size); int ble_hs_test_util_inject_rx_l2cap_sig(uint16_t conn_handle, uint8_t opcode, uint8_t id, void *cmd, uint16_t cmd_size); void ble_hs_test_util_verify_tx_l2cap(struct os_mbuf *txom); diff --git a/nimble/host/test/src/ble_l2cap_test.c b/nimble/host/test/src/ble_l2cap_test.c index 2b17da06a7..0f55bc006b 100644 --- a/nimble/host/test/src/ble_l2cap_test.c +++ b/nimble/host/test/src/ble_l2cap_test.c @@ -999,6 +999,46 @@ ble_l2cap_test_coc_disc_by_peer(struct test_data *t) &req, sizeof(req)) == id); } +static void +ble_l2cap_test_coc_disc_by_peer_invalid_dcid(struct test_data *t) +{ + struct ble_l2cap_sig_disc_req req; + struct event *ev = &t->event[t->event_iter++]; + uint8_t id = 10; + int rc; + struct os_mbuf *cmd; + uint16_t rej_err = htole16(BLE_L2CAP_SIG_ERR_INVALID_CID); + req.dcid = htole16(t->chan[0]->dcid + 1); + req.scid = htole16(t->chan[0]->dcid); + + rc = ble_hs_test_util_inject_rx_l2cap_sig(2, BLE_L2CAP_SIG_OP_DISCONN_REQ, + id, &req, sizeof(req)); + TEST_ASSERT(rc == 0); + + /* Ensure callback got NOT called. */ + TEST_ASSERT(!ev->handled); + + struct { + uint16_t local_cid; + uint16_t remote_cid; + } data = { + .local_cid = req.scid, + .remote_cid = req.dcid, + }; + + /* Ensure an we sent back Command Reject response + * Recect command should contain reason and CIDs pair + */ + cmd = os_mbuf_get(&sdu_os_mbuf_pool, 0); + os_mbuf_append(cmd, &rej_err, sizeof(uint16_t)); + os_mbuf_append(cmd, &data, sizeof(data)); + + ble_hs_test_util_verify_tx_l2cap_sig( + BLE_L2CAP_SIG_OP_REJECT, + cmd->om_data, cmd->om_len); + os_mbuf_free_chain(cmd); +} + static void ble_l2cap_test_coc_invalid_disc_by_peer(struct test_data *t) { @@ -1361,6 +1401,29 @@ TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_incoming_disconnect_failed) ble_hs_test_util_assert_mbufs_freed(NULL); } +TEST_CASE_SELF(ble_l2cap_test_case_invalid_cid_in_disconnect_req) +{ + struct test_data t; + + ble_l2cap_test_util_init(); + + ble_l2cap_test_set_chan_test_conf(BLE_L2CAP_TEST_PSM, + BLE_L2CAP_TEST_COC_MTU, &t); + t.expected_num_of_ev = 1; + + t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED; + t.event[0].app_status = 0; + t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS; + t.event[1].type = BLE_L2CAP_EVENT_COC_DISCONNECTED; + + ble_l2cap_test_coc_connect(&t); + ble_l2cap_test_coc_disc_by_peer_invalid_dcid(&t); + + TEST_ASSERT(t.expected_num_of_ev == t.event_cnt); + + ble_hs_test_util_assert_mbufs_freed(NULL); +} + TEST_CASE_SELF(ble_l2cap_test_case_coc_send_data_succeed) { struct test_data t; @@ -1493,6 +1556,7 @@ TEST_SUITE(ble_l2cap_test_suite) ble_l2cap_test_case_sig_coc_disconnect_succeed(); ble_l2cap_test_case_sig_coc_incoming_disconnect_succeed(); ble_l2cap_test_case_sig_coc_incoming_disconnect_failed(); + ble_l2cap_test_case_invalid_cid_in_disconnect_req(); ble_l2cap_test_case_coc_send_data_succeed(); ble_l2cap_test_case_coc_send_data_failed_too_big_sdu(); ble_l2cap_test_case_coc_recv_data_succeed(); From 5b93f6945a7761c39a1cab3bc0fad727a9635332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 20 Jul 2021 10:45:11 +0200 Subject: [PATCH 075/306] host/l2cap: disconnect channel if received more than expected If receive data lenght exceeds what was defined in first packet disconnect with peer. This is affecting L2CAP/LE/CFC/BV-28-C --- nimble/host/src/ble_l2cap_coc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/nimble/host/src/ble_l2cap_coc.c b/nimble/host/src/ble_l2cap_coc.c index aa953d79c5..f74cea2800 100644 --- a/nimble/host/src/ble_l2cap_coc.c +++ b/nimble/host/src/ble_l2cap_coc.c @@ -198,6 +198,17 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) } sdu_len = get_le16((*om)->om_data); + + /* We should receive payload of size sdu_len + 2 bytes of sdu_len field */ + if (om_total > sdu_len + 2) { + BLE_HS_LOG(ERROR, "Payload larger than expected (%d>%d)\n", + om_total, sdu_len + 2); + /* Disconnect peer with invalid behaviour */ + rx->sdu = NULL; + rx->data_offset = 0; + ble_l2cap_disconnect(chan); + return BLE_HS_EBADDATA; + } if (sdu_len > rx->mtu) { BLE_HS_LOG(INFO, "error: sdu_len > rx->mtu (%d>%d)\n", sdu_len, rx->mtu); @@ -227,6 +238,15 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) } else { BLE_HS_LOG(DEBUG, "Continuation...received %d\n", (*om)->om_len); + if (OS_MBUF_PKTLEN(rx->sdu) + (*om)->om_len > rx->data_offset) { + /* Disconnect peer with invalid behaviour */ + BLE_HS_LOG(ERROR, "Payload larger than expected (%d>%d)\n", + OS_MBUF_PKTLEN(rx->sdu) + (*om)->om_len, rx->data_offset); + rx->sdu = NULL; + rx->data_offset = 0; + ble_l2cap_disconnect(chan); + return BLE_HS_EBADDATA; + } rc = os_mbuf_appendfrom(rx->sdu, *om, 0, om_total); if (rc != 0) { /* FIXME: need to handle it better */ From ba36c802f33b2f9e2b79d8a09a78c2f88dfb211f Mon Sep 17 00:00:00 2001 From: Daniel Jackson Date: Sun, 26 Sep 2021 00:37:43 +0100 Subject: [PATCH 076/306] Return the current tick as when the RF will be fully enabled (when MYNEWT_VAL_BLE_LL_RFMGMT_ENABLE_TIME is not defined). When `MYNEWT_VAL_BLE_LL_RFMGMT_ENABLE_TIME` is not defined, the existing code always returns 0 as the "tick at which RF will be fully enabled". However, this causes problems. For example, in `ble_ll_adv_sm_start()` (ble_ll_adv.c:2743) the calculation of `delta` overflows when the system timer is between 0x80000000 and 0xFFFFFFFF -- causing an incorrect, huge adjustment to be made to the scheduled time, ultimately stopping the advertisements from being sent. --- nimble/controller/include/controller/ble_ll_rfmgmt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/include/controller/ble_ll_rfmgmt.h b/nimble/controller/include/controller/ble_ll_rfmgmt.h index 37b81a88be..5e2d636ff8 100644 --- a/nimble/controller/include/controller/ble_ll_rfmgmt.h +++ b/nimble/controller/include/controller/ble_ll_rfmgmt.h @@ -51,7 +51,7 @@ static inline void ble_ll_rfmgmt_reset(void) { } static inline void ble_ll_rfmgmt_scan_changed(bool e, uint32_t n) { } static inline void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *f) { } static inline void ble_ll_rfmgmt_release(void) { } -static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return 0; } +static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return os_cputime_get32(); } static inline bool ble_ll_rfmgmt_is_enabled(void) { return true; } #endif From e4f5b4498af0b5e549acb336a0f1bab200aa9739 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 28 Sep 2021 19:28:00 +0200 Subject: [PATCH 077/306] apps/ext_advertiser: Fix instance and sid values Let's use instance number as sid also, this makes it easier to find those instances in the air. Also fix instance numbers in comments. --- apps/ext_advertiser/src/main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/ext_advertiser/src/main.c b/apps/ext_advertiser/src/main.c index 86b728436e..9cb6c6fe57 100644 --- a/apps/ext_advertiser/src/main.c +++ b/apps/ext_advertiser/src/main.c @@ -86,7 +86,7 @@ start_ext_max_events(uint8_t pattern, bool configure) params.primary_phy = BLE_HCI_LE_PHY_1M; params.secondary_phy = BLE_HCI_LE_PHY_1M; params.tx_power = 127; - params.sid = pattern % 16; + params.sid = 4; /* allow larger interval, 400 * 0.625ms with 100 events will give up to * ~2.5 seconds for instance @@ -94,7 +94,7 @@ start_ext_max_events(uint8_t pattern, bool configure) params.itvl_min = BLE_GAP_ADV_FAST_INTERVAL1_MIN; params.itvl_max = 400; - /* configure instance 0 */ + /* configure instance 4 */ rc = ble_gap_ext_adv_configure(instance, ¶ms, NULL, start_ext_max_events_gap_event, NULL); assert (rc == 0); @@ -184,9 +184,9 @@ start_legacy_duration(uint8_t pattern, bool configure) params.primary_phy = BLE_HCI_LE_PHY_1M; params.secondary_phy = BLE_HCI_LE_PHY_1M; params.tx_power = 127; - params.sid = pattern % 16; + params.sid = 3; - /* configure instance 0 */ + /* configure instance 3 */ rc = ble_gap_ext_adv_configure(instance, ¶ms, NULL, start_legacy_duration_gap_event, NULL); assert (rc == 0); @@ -251,7 +251,7 @@ start_scannable_legacy_ext(void) params.tx_power = 127; params.sid = 2; - /* configure instance 0 */ + /* configure instance 2 */ rc = ble_gap_ext_adv_configure(instance, ¶ms, NULL, NULL, NULL); assert (rc == 0); @@ -335,7 +335,7 @@ start_scannable_ext(void) params.tx_power = 127; params.sid = 1; - /* configure instance 0 */ + /* configure instance 1 */ rc = ble_gap_ext_adv_configure(instance, ¶ms, NULL, scannable_ext_gap_event, NULL); assert (rc == 0); @@ -387,7 +387,7 @@ start_non_connectable_ext(void) params.tx_power = 127; params.sid = 0; - /* configure instance */ + /* configure instance 0 */ rc = ble_gap_ext_adv_configure(instance, ¶ms, NULL, NULL, NULL); assert (rc == 0); @@ -430,9 +430,9 @@ static void start_periodic(void) params.primary_phy = BLE_HCI_LE_PHY_1M; params.secondary_phy = BLE_HCI_LE_PHY_1M; params.tx_power = 127; - params.sid = 2; + params.sid = 5; - /* configure instance 0 */ + /* configure instance 5 */ rc = ble_gap_ext_adv_configure(instance, ¶ms, NULL, NULL, NULL); assert (rc == 0); From 2bc5aede344b093577fe0070e4c1b514e769e8fe Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 10 Mar 2021 00:11:05 +0100 Subject: [PATCH 078/306] nimble/ll: Rename ble_ll_scan_params to ble_ll_scan_phy --- .../include/controller/ble_ll_scan.h | 8 +- nimble/controller/src/ble_ll_scan.c | 76 +++++++++---------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index 9bbd4d6900..4ee1aa4b43 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -80,7 +80,7 @@ struct ble_ll_scan_timing { uint32_t start_time; }; -struct ble_ll_scan_params +struct ble_ll_scan_phy { uint8_t phy; uint8_t own_addr_type; @@ -185,9 +185,9 @@ struct ble_ll_scan_sm uint8_t restart_timer_needed; struct ble_ll_aux_data *cur_aux_data; - struct ble_ll_scan_params *scanp; - struct ble_ll_scan_params *scanp_next; - struct ble_ll_scan_params scanp_phys[BLE_LL_SCAN_PHY_NUMBER]; + struct ble_ll_scan_phy *scanp; + struct ble_ll_scan_phy *scanp_next; + struct ble_ll_scan_phy scan_phys[BLE_LL_SCAN_PHY_NUMBER]; }; /* Scan types */ diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 7eac16b5ae..aef0c12b5d 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -65,7 +65,7 @@ #endif /* The scanning parameters set by host */ -static struct ble_ll_scan_params g_ble_ll_scan_params[BLE_LL_SCAN_PHY_NUMBER]; +static struct ble_ll_scan_phy g_ble_ll_scan_phys[BLE_LL_SCAN_PHY_NUMBER]; /* The scanning state machine global object */ static struct ble_ll_scan_sm g_ble_ll_scan_sm; @@ -884,7 +884,7 @@ static void ble_ll_get_chan_to_scan(struct ble_ll_scan_sm *scansm, uint8_t *chan, int *phy) { - struct ble_ll_scan_params *scanp = scansm->scanp; + struct ble_ll_scan_phy *scanp = scansm->scanp; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) struct ble_ll_aux_data *aux_data = scansm->cur_aux_data; @@ -914,7 +914,7 @@ static int ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch) { int rc; - struct ble_ll_scan_params *scanp = scansm->scanp; + struct ble_ll_scan_phy *scanp = scansm->scanp; uint8_t scan_chan; #if (BLE_LL_BT5_PHY_SUPPORTED == 1) uint8_t phy_mode; @@ -1005,7 +1005,7 @@ ble_ll_scan_get_next_adv_prim_chan(uint8_t chan) } static uint32_t -ble_ll_scan_move_window_to(struct ble_ll_scan_params *scanp, uint32_t time) +ble_ll_scan_move_window_to(struct ble_ll_scan_phy *scanp, uint32_t time) { uint32_t end_time; @@ -1025,7 +1025,7 @@ ble_ll_scan_move_window_to(struct ble_ll_scan_params *scanp, uint32_t time) } static bool -ble_ll_scan_is_inside_window(struct ble_ll_scan_params *scanp, uint32_t time) +ble_ll_scan_is_inside_window(struct ble_ll_scan_phy *scanp, uint32_t time) { uint32_t start_time; @@ -1175,8 +1175,8 @@ ble_ll_scan_sm_stop(int chk_disable) static int ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm) { - struct ble_ll_scan_params *scanp; - struct ble_ll_scan_params *scanp_next; + struct ble_ll_scan_phy *scanp; + struct ble_ll_scan_phy *scanp_next; if (!ble_ll_is_valid_own_addr_type(scansm->own_addr_type, g_random_addr)) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -1295,10 +1295,10 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev) os_sr_t sr; bool start_scan; bool inside_window; - struct ble_ll_scan_params *scanp; + struct ble_ll_scan_phy *scanp; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) bool inside_window_next; - struct ble_ll_scan_params *scanp_next; + struct ble_ll_scan_phy *scanp_next; #endif uint32_t next_proc_time; uint32_t now; @@ -1438,7 +1438,7 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags) { int rc; struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; + struct ble_ll_scan_phy *scanp; rc = 0; scansm = &g_ble_ll_scan_sm; @@ -1990,7 +1990,7 @@ static int ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *addrd) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_ll_scan_params *scanp = scansm->scanp; + struct ble_ll_scan_phy *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; @@ -2130,7 +2130,7 @@ ble_ll_scan_rx_isr_on_legacy(uint8_t pdu_type, uint8_t *rxbuf, struct ble_ll_scan_addr_data *addrd) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_ll_scan_params *scanp = scansm->scanp; + struct ble_ll_scan_phy *scanp = scansm->scanp; struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; uint8_t sreq_adva_type; uint8_t *sreq_adva; @@ -2201,7 +2201,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf, struct ble_ll_scan_addr_data *addrd) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_ll_scan_params *scanp = scansm->scanp; + struct ble_ll_scan_phy *scanp = scansm->scanp; struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; struct ble_ll_aux_data *aux_data; int rc; @@ -3234,7 +3234,7 @@ ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) uint16_t scan_itvl; uint16_t scan_window; struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; + struct ble_ll_scan_phy *scanp; if (len != sizeof(*cmd)) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -3276,7 +3276,7 @@ ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) } /* Store scan parameters */ - scanp = &g_ble_ll_scan_params[PHY_UNCODED]; + scanp = &g_ble_ll_scan_phys[PHY_UNCODED]; scanp->configured = 1; scanp->scan_type = cmd->scan_type; scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(scan_itvl); @@ -3285,7 +3285,7 @@ ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) scanp->own_addr_type = cmd->own_addr_type; #if (BLE_LL_SCAN_PHY_NUMBER == 2) - g_ble_ll_scan_params[PHY_CODED].configured = 0; + g_ble_ll_scan_phys[PHY_CODED].configured = 0; #endif return 0; @@ -3319,9 +3319,9 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) const struct ble_hci_le_set_ext_scan_params_cp *cmd = (const void *) cmdbuf; const struct scan_params *params = cmd->scans; - struct ble_ll_scan_params new_params[BLE_LL_SCAN_PHY_NUMBER] = { }; - struct ble_ll_scan_params *uncoded = &new_params[PHY_UNCODED]; - struct ble_ll_scan_params *coded = &new_params[PHY_CODED]; + struct ble_ll_scan_phy new_params[BLE_LL_SCAN_PHY_NUMBER] = { }; + struct ble_ll_scan_phy *uncoded = &new_params[PHY_UNCODED]; + struct ble_ll_scan_phy *coded = &new_params[PHY_CODED]; uint16_t interval; uint16_t window; int rc; @@ -3420,7 +3420,7 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) } } - memcpy(g_ble_ll_scan_params, new_params, sizeof(new_params)); + memcpy(g_ble_ll_scan_phys, new_params, sizeof(new_params)); return 0; } @@ -3487,8 +3487,8 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, { int rc; struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; - struct ble_ll_scan_params *scanp_phy; + struct ble_ll_scan_phy *scanp; + struct ble_ll_scan_phy *scanp_phy; int i; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) ble_npl_time_t period_ticks = 0; @@ -3543,7 +3543,7 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, if (scansm->scan_enabled) { /* Controller does not allow initiating and scanning.*/ for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { - scanp_phy = &scansm->scanp_phys[i]; + scanp_phy = &scansm->scan_phys[i]; if (scanp_phy->configured && scanp_phy->scan_type == BLE_SCAN_TYPE_INITIATE) { return BLE_ERR_CMD_DISALLOWED; @@ -3576,8 +3576,8 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, scansm->scanp_next = NULL; for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { - scanp_phy = &scansm->scanp_phys[i]; - scanp = &g_ble_ll_scan_params[i]; + scanp_phy = &scansm->scan_phys[i]; + scanp = &g_ble_ll_scan_phys[i]; if (!scanp->configured) { continue; @@ -3606,7 +3606,7 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, * Parameters defaults. */ if (!scansm->scanp) { - scansm->scanp = &scansm->scanp_phys[PHY_UNCODED]; + scansm->scanp = &scansm->scan_phys[PHY_UNCODED]; scansm->own_addr_type = BLE_ADDR_PUBLIC; scanp_phy = scansm->scanp; @@ -3671,7 +3671,7 @@ ble_ll_scan_can_chg_whitelist(void) { int rc; struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; + struct ble_ll_scan_phy *scanp; scansm = &g_ble_ll_scan_sm; scanp = scansm->scanp; @@ -3689,7 +3689,7 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc, struct ble_ll_scan_sm **sm) { struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; + struct ble_ll_scan_phy *scanp; int rc; scansm = &g_ble_ll_scan_sm; @@ -3697,7 +3697,7 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) scansm->ext_scanning = 0; #endif - scansm->scanp = &scansm->scanp_phys[PHY_UNCODED]; + scansm->scanp = &scansm->scan_phys[PHY_UNCODED]; scansm->scanp_next = NULL; scanp = scansm->scanp; @@ -3726,8 +3726,8 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, struct ble_ll_scan_sm **sm) { struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp_uncoded; - struct ble_ll_scan_params *scanp_coded; + struct ble_ll_scan_phy *scanp_uncoded; + struct ble_ll_scan_phy *scanp_coded; struct hci_ext_conn_params *params; int rc; @@ -3739,7 +3739,7 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, if (hcc->init_phy_mask & BLE_PHY_MASK_1M) { params = &hcc->params[0]; - scanp_uncoded = &scansm->scanp_phys[PHY_UNCODED]; + scanp_uncoded = &scansm->scan_phys[PHY_UNCODED]; scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); @@ -3750,7 +3750,7 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) { params = &hcc->params[2]; - scanp_coded = &scansm->scanp_phys[PHY_CODED]; + scanp_coded = &scansm->scan_phys[PHY_CODED]; scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); @@ -3864,7 +3864,7 @@ static void ble_ll_scan_common_init(void) { struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanp; + struct ble_ll_scan_phy *scanp; int i; /* Clear state machine in case re-initialized */ @@ -3872,23 +3872,23 @@ ble_ll_scan_common_init(void) memset(scansm, 0, sizeof(struct ble_ll_scan_sm)); /* Clear scan parameters in case re-initialized */ - memset(g_ble_ll_scan_params, 0, sizeof(g_ble_ll_scan_params)); + memset(g_ble_ll_scan_phys, 0, sizeof(g_ble_ll_scan_phys)); /* Initialize scanning window end event */ ble_npl_event_init(&scansm->scan_sched_ev, ble_ll_scan_event_proc, scansm); for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { /* Set all non-zero default parameters */ - scanp = &g_ble_ll_scan_params[i]; + scanp = &g_ble_ll_scan_phys[i]; scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF); scanp->timing.window = ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF); } - scansm->scanp_phys[PHY_UNCODED].phy = BLE_PHY_1M; + scansm->scan_phys[PHY_UNCODED].phy = BLE_PHY_1M; #if (BLE_LL_SCAN_PHY_NUMBER == 2) - scansm->scanp_phys[PHY_CODED].phy = BLE_PHY_CODED; + scansm->scan_phys[PHY_CODED].phy = BLE_PHY_CODED; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) From e084ef70efdb62ddff25a5f97b024561bf4d8de6 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 9 Mar 2021 16:02:50 +0100 Subject: [PATCH 079/306] nimble/ll: Simplify scansm parameters 'own_addr_type' and 'scan_filt_policy' are the same for both PHYs so no need to keep them separately for each scanp. Also we already had own_addr_type so usage of this parameter was somewhat inconsistent. --- .../include/controller/ble_ll_scan.h | 4 +- nimble/controller/src/ble_ll_scan.c | 68 +++++++++---------- 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index 4ee1aa4b43..8827af4d61 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -83,8 +83,6 @@ struct ble_ll_scan_timing { struct ble_ll_scan_phy { uint8_t phy; - uint8_t own_addr_type; - uint8_t scan_filt_policy; uint8_t configured; uint8_t scan_type; uint8_t scan_chan; @@ -154,7 +152,9 @@ struct ble_ll_scan_pdu_data { struct ble_ll_scan_sm { uint8_t scan_enabled; + uint8_t own_addr_type; + uint8_t scan_filt_policy; uint8_t scan_filt_dups; uint8_t scan_rsp_pending; uint8_t scan_rsp_cons_fails; diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index aef0c12b5d..c7cdcbfa00 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -64,8 +64,13 @@ #define SCAN_VALID_PHY_MASK (BLE_HCI_LE_PHY_1M_PREF_MASK) #endif -/* The scanning parameters set by host */ -static struct ble_ll_scan_phy g_ble_ll_scan_phys[BLE_LL_SCAN_PHY_NUMBER]; +struct ble_ll_scan_params { + uint8_t own_addr_type; + uint8_t scan_filt_policy; + struct ble_ll_scan_phy scan_phys[BLE_LL_SCAN_PHY_NUMBER]; +}; + +static struct ble_ll_scan_params g_ble_ll_scan_params; /* The scanning state machine global object */ static struct ble_ll_scan_sm g_ble_ll_scan_sm; @@ -976,7 +981,7 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch) rc = 0; /* Enable/disable whitelisting */ - if (scanp->scan_filt_policy & 1) { + if (scansm->scan_filt_policy & 1) { ble_ll_whitelist_enable(); } else { ble_ll_whitelist_disable(); @@ -1990,7 +1995,6 @@ static int ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *addrd) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_ll_scan_phy *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; @@ -2080,7 +2084,7 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad } /* Check if scan filter policy allows unresolved RPAs to be processed */ - if (!(scanp->scan_filt_policy & 0x02)) { + if (!(scansm->scan_filt_policy & 0x02)) { return 0; } @@ -2093,7 +2097,7 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad break; case BLE_LL_ADDR_SUBTYPE_IDENTITY: /* We shall ignore identity in TargetA if we are using RPA */ - if ((scanp->own_addr_type & 0x02) && rl && rl->rl_has_local) { + if ((scansm->own_addr_type & 0x02) && rl && rl->rl_has_local) { return 0; } /* Ignore if not directed to us */ @@ -2115,7 +2119,7 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad #endif /* Check on WL if required by scan filter policy */ - if (scanp->scan_filt_policy & 0x01) { + if (scansm->scan_filt_policy & 0x01) { if (!ble_ll_whitelist_match(addrd->adv_addr, addrd->adv_addr_type, resolved)) { return 0; } @@ -3276,16 +3280,18 @@ ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) } /* Store scan parameters */ - scanp = &g_ble_ll_scan_phys[PHY_UNCODED]; + g_ble_ll_scan_params.own_addr_type = cmd->own_addr_type; + g_ble_ll_scan_params.scan_filt_policy = cmd->filter_policy; + + scanp = &g_ble_ll_scan_params.scan_phys[PHY_UNCODED]; scanp->configured = 1; scanp->scan_type = cmd->scan_type; scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(scan_itvl); scanp->timing.window = ble_ll_scan_time_hci_to_ticks(scan_window); - scanp->scan_filt_policy = cmd->filter_policy; - scanp->own_addr_type = cmd->own_addr_type; #if (BLE_LL_SCAN_PHY_NUMBER == 2) - g_ble_ll_scan_phys[PHY_CODED].configured = 0; + scanp = &g_ble_ll_scan_params.scan_phys[PHY_CODED]; + scanp->configured = 0; #endif return 0; @@ -3342,17 +3348,11 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } - coded->own_addr_type = cmd->own_addr_type; - uncoded->own_addr_type = cmd->own_addr_type; - /* Check scanner filter policy */ if (cmd->filter_policy > BLE_HCI_SCAN_FILT_MAX) { return BLE_ERR_INV_HCI_CMD_PARMS; } - coded->scan_filt_policy = cmd->filter_policy; - uncoded->scan_filt_policy = cmd->filter_policy; - /* Check if no reserved bits in PHYS are set and that at least one valid PHY * is set. */ @@ -3420,7 +3420,10 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) } } - memcpy(g_ble_ll_scan_phys, new_params, sizeof(new_params)); + g_ble_ll_scan_params.own_addr_type = cmd->own_addr_type; + g_ble_ll_scan_params.scan_filt_policy = cmd->filter_policy; + + memcpy(g_ble_ll_scan_params.scan_phys, new_params, sizeof(new_params)); return 0; } @@ -3575,9 +3578,12 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, scansm->scanp = NULL; scansm->scanp_next = NULL; + scansm->own_addr_type = g_ble_ll_scan_params.own_addr_type; + scansm->scan_filt_policy = g_ble_ll_scan_params.scan_filt_policy; + for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { scanp_phy = &scansm->scan_phys[i]; - scanp = &g_ble_ll_scan_phys[i]; + scanp = &g_ble_ll_scan_params.scan_phys[i]; if (!scanp->configured) { continue; @@ -3586,15 +3592,9 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, scanp_phy->configured = scanp->configured; scanp_phy->scan_type = scanp->scan_type; scanp_phy->timing = scanp->timing; - scanp_phy->scan_filt_policy = scanp->scan_filt_policy; - scanp_phy->own_addr_type = scanp->own_addr_type; if (!scansm->scanp) { scansm->scanp = scanp_phy; - /* Take own_addr_type from the first configured PHY. - * Note: All configured PHYs shall have the same own_addr_type - */ - scansm->own_addr_type = scanp_phy->own_addr_type; } else { scansm->scanp_next = scanp_phy; } @@ -3608,6 +3608,7 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, if (!scansm->scanp) { scansm->scanp = &scansm->scan_phys[PHY_UNCODED]; scansm->own_addr_type = BLE_ADDR_PUBLIC; + scansm->scan_filt_policy = BLE_HCI_SCAN_FILT_NO_WL; scanp_phy = scansm->scanp; scanp_phy->configured = 1; @@ -3616,8 +3617,6 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF); scanp_phy->timing.window = ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF); - scanp_phy->scan_filt_policy = BLE_HCI_SCAN_FILT_NO_WL; - scanp_phy->own_addr_type = BLE_ADDR_PUBLIC; } rc = ble_ll_scan_sm_start(scansm); @@ -3671,11 +3670,9 @@ ble_ll_scan_can_chg_whitelist(void) { int rc; struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_phy *scanp; scansm = &g_ble_ll_scan_sm; - scanp = scansm->scanp; - if (scansm->scan_enabled && (scanp->scan_filt_policy & 1)) { + if (scansm->scan_enabled && (scansm->scan_filt_policy & 1)) { rc = 0; } else { rc = 1; @@ -3694,6 +3691,7 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc, scansm = &g_ble_ll_scan_sm; scansm->own_addr_type = hcc->own_addr_type; + scansm->scan_filt_policy = hcc->filter_policy; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) scansm->ext_scanning = 0; #endif @@ -3701,7 +3699,6 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc, scansm->scanp_next = NULL; scanp = scansm->scanp; - scanp->scan_filt_policy = hcc->filter_policy; scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl); scanp->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window); scanp->scan_type = BLE_SCAN_TYPE_INITIATE; @@ -3733,6 +3730,7 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, scansm = &g_ble_ll_scan_sm; scansm->own_addr_type = hcc->own_addr_type; + scansm->scan_filt_policy = hcc->filter_policy; scansm->scanp = NULL; scansm->scanp_next = NULL; scansm->ext_scanning = 1; @@ -3744,7 +3742,6 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); scanp_uncoded->scan_type = BLE_SCAN_TYPE_INITIATE; - scanp_uncoded->scan_filt_policy = hcc->filter_policy; scansm->scanp = scanp_uncoded; } @@ -3755,7 +3752,6 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); scanp_coded->scan_type = BLE_SCAN_TYPE_INITIATE; - scanp_coded->scan_filt_policy = hcc->filter_policy; if (scansm->scanp) { scansm->scanp_next = scanp_coded; } else { @@ -3857,7 +3853,7 @@ ble_ll_scan_get_pdu_data(void) int ble_ll_scan_whitelist_enabled(void) { - return g_ble_ll_scan_sm.scanp->scan_filt_policy & 1; + return g_ble_ll_scan_sm.scan_filt_policy & 1; } static void @@ -3872,14 +3868,14 @@ ble_ll_scan_common_init(void) memset(scansm, 0, sizeof(struct ble_ll_scan_sm)); /* Clear scan parameters in case re-initialized */ - memset(g_ble_ll_scan_phys, 0, sizeof(g_ble_ll_scan_phys)); + memset(&g_ble_ll_scan_params, 0, sizeof(g_ble_ll_scan_params)); /* Initialize scanning window end event */ ble_npl_event_init(&scansm->scan_sched_ev, ble_ll_scan_event_proc, scansm); for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { /* Set all non-zero default parameters */ - scanp = &g_ble_ll_scan_phys[i]; + scanp = &g_ble_ll_scan_params.scan_phys[i]; scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF); scanp->timing.window = From eed4389851fcf96922a2e429376808f2dfddc912 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sat, 20 Mar 2021 17:46:28 +0100 Subject: [PATCH 080/306] nimble/ll: Decouple aux scanner from main scansm This change moves handling of scanning aux PDUs to separate unit and thus simplifies code in ble_ll_scan. Basically, once ADV_EXT_IND is scanned by main scansm, scanning aux PDUs is running as a separate LL state and is handled by separate code. Handling on aux PDUs was also refactored a bit, more importantly we no longer need ref/unref for aux_data which caused lots of issues in the past - aux_data is always only allocated in ISR context when ADV_EXT_IND with AuxPtr is received and then can be freed only in LL context if no subsequent scan is scheduled. In addition, some changes were done to filtering routines so that now filtering and address resolution is done only once for each scanned ext advertising event, i.e. either on ADV_EXT_IND or AUX_ADV_IND. There is still some legacy code for aux scanner left since it's used by initiator role. This will be eventually removed once initiator is refactored to use the same code as generic scanner. --- nimble/controller/include/controller/ble_ll.h | 2 + .../include/controller/ble_ll_resolv.h | 6 + .../include/controller/ble_ll_scan.h | 33 + .../include/controller/ble_ll_scan_aux.h | 54 + .../include/controller/ble_ll_sched.h | 4 + .../include/controller/ble_ll_sync.h | 4 +- nimble/controller/src/ble_ll.c | 27 + nimble/controller/src/ble_ll_scan.c | 1094 ++---------- nimble/controller/src/ble_ll_scan_aux.c | 1555 +++++++++++++++++ nimble/controller/src/ble_ll_sched.c | 68 + nimble/controller/src/ble_ll_sync.c | 32 +- nimble/controller/syscfg.yml | 6 + 12 files changed, 1958 insertions(+), 927 deletions(-) create mode 100644 nimble/controller/include/controller/ble_ll_scan_aux.h create mode 100644 nimble/controller/src/ble_ll_scan_aux.c diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index 24d7db3003..4a832c6558 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -220,6 +220,7 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; #define BLE_LL_STATE_CONNECTION (4) #define BLE_LL_STATE_DTM (5) #define BLE_LL_STATE_SYNC (6) +#define BLE_LL_STATE_SCAN_AUX (7) /* LL Features */ #define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001) @@ -354,6 +355,7 @@ struct ble_dev_addr #define BLE_LL_EXT_ADV_FLAGS_SIZE (1) #define BLE_LL_EXT_ADV_ADVA_SIZE (6) #define BLE_LL_EXT_ADV_TARGETA_SIZE (6) +#define BLE_LL_EXT_ADV_CTE_INFO_SIZE (1) #define BLE_LL_EXT_ADV_DATA_INFO_SIZE (2) #define BLE_LL_EXT_ADV_AUX_PTR_SIZE (3) #define BLE_LL_EXT_ADV_SYNC_INFO_SIZE (18) diff --git a/nimble/controller/include/controller/ble_ll_resolv.h b/nimble/controller/include/controller/ble_ll_resolv.h index 228e0a3703..b9ca7fd387 100644 --- a/nimble/controller/include/controller/ble_ll_resolv.h +++ b/nimble/controller/include/controller/ble_ll_resolv.h @@ -72,6 +72,12 @@ int ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len, struct ble_ll_resolv_entry * ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type); +static inline int8_t +ble_ll_resolv_get_idx(struct ble_ll_resolv_entry *rl) +{ + return rl - g_ble_ll_resolv_list; +} + /* Returns true if address resolution is enabled */ uint8_t ble_ll_resolv_enabled(void); diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index 8827af4d61..d3097f2b11 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -149,6 +149,20 @@ struct ble_ll_scan_pdu_data { uint8_t adva[BLE_DEV_ADDR_LEN]; }; +struct ble_ll_scan_addr_data { + uint8_t *adva; + uint8_t *targeta; + uint8_t *adv_addr; + uint8_t adva_type : 1; + uint8_t targeta_type : 1; + uint8_t adv_addr_type : 1; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + uint8_t adva_resolved : 1; + uint8_t targeta_resolved : 1; + int8_t rpa_index; +#endif +}; + struct ble_ll_scan_sm { uint8_t scan_enabled; @@ -286,6 +300,25 @@ void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data); /* Called to halt currently running scan */ void ble_ll_scan_halt(void); +uint8_t *ble_ll_get_scan_nrpa(void); +uint8_t ble_ll_scan_get_own_addr_type(void); +uint8_t ble_ll_scan_get_filt_policy(void); +uint8_t ble_ll_scan_get_filt_dups(void); +uint8_t ble_ll_scan_backoff_kick(void); +void ble_ll_scan_backoff_update(int success); + +int ble_ll_scan_dup_check_ext(uint8_t addr_type, uint8_t *addr, bool has_aux, + uint16_t adi); +int ble_ll_scan_dup_update_ext(uint8_t addr_type, uint8_t *addr, bool has_aux, + uint16_t adi); +int ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, uint8_t ext_adv, + uint16_t adi); +void ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, uint8_t ext_adv, + uint16_t adi); + +int ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, + struct ble_ll_scan_addr_data *addrd, uint8_t *scan_ok); + #ifdef __cplusplus } #endif diff --git a/nimble/controller/include/controller/ble_ll_scan_aux.h b/nimble/controller/include/controller/ble_ll_scan_aux.h new file mode 100644 index 0000000000..c7d63b8449 --- /dev/null +++ b/nimble/controller/include/controller/ble_ll_scan_aux.h @@ -0,0 +1,54 @@ +/* + * 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_SCAN_AUX_ +#define H_BLE_LL_SCAN_AUX_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + +struct ble_ll_scan_aux_data; + +void ble_ll_scan_aux_init(void); +int ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_time, + uint8_t pdu_time_rem, uint32_t aux_ptr); +int ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr); +int ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok); +void ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr); + +void ble_ll_scan_aux_break(struct ble_ll_scan_aux_data *aux); +void ble_ll_scan_aux_wfr_timer_exp(void); +void ble_ll_scan_aux_halt(void); +void ble_ll_scan_aux_sched_remove(struct ble_ll_sched_item *sch); + +int ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm, + struct os_mbuf *rxpdu); +void ble_ll_scan_aux_pkt_in_on_ext(struct os_mbuf *rxpdu, + struct ble_mbuf_hdr *rxhdr); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_SCAN_AUX_ */ diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h index a614cf0905..96834bb075 100644 --- a/nimble/controller/include/controller/ble_ll_sched.h +++ b/nimble/controller/include/controller/ble_ll_sched.h @@ -71,6 +71,7 @@ extern uint8_t g_ble_ll_sched_offset_ticks; #define BLE_LL_SCHED_TYPE_DTM (5) #define BLE_LL_SCHED_TYPE_PERIODIC (6) #define BLE_LL_SCHED_TYPE_SYNC (7) +#define BLE_LL_SCHED_TYPE_SCAN_AUX (8) /* Return values for schedule callback. */ #define BLE_LL_SCHED_STATE_RUNNING (0) @@ -200,6 +201,9 @@ int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, struct ble_ll_aux_data *aux_scan); int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode); + +int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, + uint8_t pdu_time_rem, uint32_t offset_us); #endif /* Stop the scheduler */ diff --git a/nimble/controller/include/controller/ble_ll_sync.h b/nimble/controller/include/controller/ble_ll_sync.h index 712af6dffc..8002d2a317 100644 --- a/nimble/controller/include/controller/ble_ll_sync.h +++ b/nimble/controller/include/controller/ble_ll_sync.h @@ -30,6 +30,7 @@ extern "C" { #endif +struct ble_ll_scan_addr_data; struct ble_ll_sync_sm; int ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len); @@ -48,8 +49,7 @@ void ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, uint16_t max_skip, uint32_t sync_timeout); void ble_ll_sync_transfer_disconnected(struct ble_ll_conn_sm *connsm); -void ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, - int rpa_index, uint8_t sid, +void ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd, uint8_t sid, struct ble_mbuf_hdr *rxhdr, const uint8_t *syncinfo); diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index cf83b79c38..8c7095a7e1 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -37,6 +37,7 @@ #include "controller/ble_ll_adv.h" #include "controller/ble_ll_sched.h" #include "controller/ble_ll_scan.h" +#include "controller/ble_ll_scan_aux.h" #include "controller/ble_ll_hci.h" #include "controller/ble_ll_whitelist.h" #include "controller/ble_ll_resolv.h" @@ -688,6 +689,11 @@ ble_ll_wfr_timer_exp(void *arg) case BLE_LL_STATE_SYNC: ble_ll_sync_wfr_timer_exp(); break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_LL_STATE_SCAN_AUX: + ble_ll_scan_aux_wfr_timer_exp(); + break; #endif default: break; @@ -848,6 +854,11 @@ ble_ll_rx_pkt_in(void) case BLE_LL_STATE_SYNC: ble_ll_sync_rx_pkt_in(m, ble_hdr); break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_LL_STATE_SCAN_AUX: + ble_ll_scan_aux_rx_pkt_in(m, ble_hdr); + break; #endif default: /* Any other state should never occur */ @@ -984,6 +995,11 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) case BLE_LL_STATE_SYNC: rc = ble_ll_sync_rx_isr_start(pdu_type, rxhdr); break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_LL_STATE_SCAN_AUX: + rc = ble_ll_scan_aux_rx_isr_start(pdu_type, rxhdr); + break; #endif default: /* Should not be in this state! */ @@ -1109,6 +1125,17 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) case BLE_LL_STATE_INITIATING: rc = ble_ll_init_rx_isr_end(rxbuf, crcok, rxhdr); break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_LL_STATE_SCAN_AUX: + if (!badpkt) { + rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); + if (rxpdu) { + ble_phy_rxpdu_copy(rxbuf, rxpdu); + } + } + rc = ble_ll_scan_aux_rx_isr_end(rxpdu, crcok); + break; +#endif default: rc = -1; STATS_INC(ble_ll_stats, bad_ll_state); diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index c7cdcbfa00..cf264b0ab0 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -32,8 +32,10 @@ #include "controller/ble_hw.h" #include "controller/ble_ll.h" #include "controller/ble_ll_sched.h" -#include "controller/ble_ll_adv.h" #include "controller/ble_ll_scan.h" +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#include "controller/ble_ll_scan_aux.h" +#endif #include "controller/ble_ll_hci.h" #include "controller/ble_ll_whitelist.h" #include "controller/ble_ll_resolv.h" @@ -75,24 +77,6 @@ static struct ble_ll_scan_params g_ble_ll_scan_params; /* The scanning state machine global object */ static struct ble_ll_scan_sm g_ble_ll_scan_sm; -struct ble_ll_ext_adv_hdr -{ - uint8_t mode; - uint8_t hdr_len; - uint8_t hdr[0]; -}; - -struct ble_ll_scan_addr_data { - bool adva_present; - uint8_t adva_type; - uint8_t *adva; - uint8_t targeta_type; - uint8_t *targeta; - uint8_t adv_addr_type; - uint8_t *adv_addr; - struct ble_ll_resolv_entry *rl; -}; - /* * Structure used to store advertisers. This is used to limit sending scan * requests to the same advertiser and also to filter duplicate events sent @@ -319,17 +303,66 @@ ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm) scansm->scan_nrpa_timer = now + ble_ll_resolv_get_rpa_tmo(); } } + +uint8_t * +ble_ll_get_scan_nrpa(void) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + + ble_ll_scan_refresh_nrpa(scansm); + + return scansm->scan_nrpa; +} #endif +uint8_t +ble_ll_scan_get_own_addr_type(void) +{ + return g_ble_ll_scan_sm.own_addr_type; +} + +uint8_t +ble_ll_scan_get_filt_policy(void) +{ + return g_ble_ll_scan_sm.scan_filt_policy; +} + +uint8_t +ble_ll_scan_get_filt_dups(void) +{ + return g_ble_ll_scan_sm.scan_filt_dups; +} + +uint8_t +ble_ll_scan_backoff_kick(void) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + + if (scansm->backoff_count > 0) { + scansm->backoff_count--; + } + + return scansm->backoff_count; +} + +void +ble_ll_scan_backoff_update(int success) +{ + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; + + ble_ll_scan_req_backoff(scansm, success); +} + static void ble_ll_scan_req_pdu_prepare(struct ble_ll_scan_sm *scansm, const uint8_t *adv_addr, uint8_t adv_addr_type, - struct ble_ll_resolv_entry *rl) + int8_t rpa_index) { uint8_t hdr_byte; struct ble_ll_scan_pdu_data *pdu_data; uint8_t *scana; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_resolv_entry *rl; uint8_t rpa[BLE_DEV_ADDR_LEN]; #endif @@ -351,6 +384,12 @@ ble_ll_scan_req_pdu_prepare(struct ble_ll_scan_sm *scansm, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) if (scansm->own_addr_type & 0x02) { + if (rpa_index >= 0) { + rl = &g_ble_ll_resolv_list[rpa_index]; + } else { + rl = NULL; + } + /* * If device is on RL and we have local IRK, we use RPA generated using * that IRK as ScanA. Otherwise we use NRPA as ScanA to prevent our @@ -436,74 +475,9 @@ ble_ll_scan_get_ext_adv_report(struct ext_adv_report *copy_from) return hci_ev; } -static void -ble_ll_scan_send_truncated(struct ble_ll_aux_data *aux_data) -{ - struct ble_hci_ev_le_subev_ext_adv_rpt *ev; - struct ext_adv_report *report; - struct ble_hci_ev *hci_ev; - - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { - return; - } - - BLE_LL_ASSERT(aux_data); - - /* No need to send if we did not send any report or sent truncated already */ - if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || - (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)) { - return; - } - - BLE_LL_ASSERT(aux_data->evt); - hci_ev = aux_data->evt; - aux_data->evt = NULL; - - hci_ev->length = sizeof(*ev) + sizeof(*report); - - ev = (void *) hci_ev->data; - report = ev->reports; - - report->data_len = 0; - - report->evt_type = aux_data->evt_type; - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; - - if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { - memcpy(report->addr, aux_data->adva, 6); - report->addr_type = aux_data->adva_type; - } - - if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { - memcpy(report->dir_addr, aux_data->targeta, 6); - report->dir_addr_type = aux_data->targeta_type; - } - - report->sid = aux_data->adi >> 12; - ble_ll_hci_event_send(hci_ev); - - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_ANY; - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; -} - -static int -ble_ll_scan_get_adi(struct ble_ll_aux_data *aux_data, uint16_t *adi) -{ - if (!aux_data || !(aux_data->flags & BLE_LL_AUX_HAS_ADI)) { - return -1; - } - - *adi = aux_data->adi; - - return 0; -} - void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data) { - /* Make sure we send report with 'truncated' data state if needed */ - ble_ll_scan_send_truncated(aux_data); } #endif @@ -544,7 +518,7 @@ ble_ll_scan_halt(void) * * @return int 0: have not received a scan response; 1 otherwise. */ -static int +int ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, uint8_t ext_adv, uint16_t adi) { @@ -588,7 +562,7 @@ ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void +void ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, uint8_t ext_adv, uint16_t adi) { @@ -867,8 +841,8 @@ ble_ll_scan_send_adv_report(uint8_t pdu_type, hdr->rxinfo.rssi, adv_data_len, om, inita, inita_type); - goto done; - } +goto done; +} #endif if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { @@ -1154,6 +1128,7 @@ ble_ll_scan_sm_stop(int chk_disable) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (scansm->ext_scanning) { + ble_ll_sched_rmv_elem_type(BLE_LL_SCHED_TYPE_SCAN_AUX, ble_ll_scan_aux_sched_remove); ble_ll_scan_clean_cur_aux_data(); ble_ll_sched_rmv_elem_type(BLE_LL_SCHED_TYPE_AUX_SCAN, ble_ll_scan_sched_remove); scansm->ext_scanning = 0; @@ -1388,6 +1363,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev) case BLE_LL_STATE_ADV: case BLE_LL_STATE_CONNECTION: case BLE_LL_STATE_SYNC: + case BLE_LL_STATE_SCAN_AUX: start_scan = false; break; case BLE_LL_STATE_INITIATING: @@ -1556,16 +1532,6 @@ ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_aux_data *aux_data, uint8_t *buf) return 0; } -static void -ble_ll_ext_scan_parse_adv_info(struct ext_adv_report *report, const uint8_t *buf) -{ - uint16_t adv_info = get_le16(buf); - - /* TODO Use DID */ - - report->sid = (adv_info >> 12); -} - /** * ble_ll_scan_update_aux_data * @@ -1699,139 +1665,6 @@ ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf, (aux_data->flags_isr & BLE_LL_AUX_FLAG_SCAN_ERROR); } -/** - * Called when a receive ADV_EXT PDU has ended. - * - * Context: Interrupt - * - * @return int - * < 0 Error - * >= 0: Success (number of bytes left in PDU) - * - */ -static int -ble_ll_scan_parse_ext_hdr(struct os_mbuf *om, - const uint8_t *adva, uint8_t adva_type, - const uint8_t *inita, uint8_t inita_type, - struct ble_mbuf_hdr *ble_hdr, - struct ext_adv_report *report) -{ - uint8_t pdu_len; - uint8_t ext_hdr_len; - uint8_t ext_hdr_flags; - uint8_t *ext_hdr; - uint8_t *rxbuf = om->om_data; - int i = 1; - struct ble_ll_scan_sm *scansm; - struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data; - - BLE_LL_ASSERT(report); - - scansm = &g_ble_ll_scan_sm; - - if (!scansm->ext_scanning) { - /* Ignore ext adv if host does not want it*/ - return -1; - } - - pdu_len = rxbuf[1]; - if (pdu_len == 0) { - return -1; - } - - report->evt_type = rxbuf[2] >> 6; - if ( report->evt_type > BLE_LL_EXT_ADV_MODE_SCAN) { - return -1; - } - - if (BLE_MBUF_HDR_SCAN_RSP_RXD(ble_hdr)) { - report->evt_type |= BLE_HCI_ADV_SCAN_RSP_MASK; - } - - ext_hdr_len = rxbuf[2] & 0x3F; - os_mbuf_adj(om, 3); - - ext_hdr_flags = rxbuf[3]; - ext_hdr = &rxbuf[4]; - - if (ext_hdr_len) { - i = 0; - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - i += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - if (adva) { - memcpy(report->addr, adva, 6); - report->addr_type = adva_type; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - i += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - if (inita) { - memcpy(report->dir_addr, inita, 6); - report->dir_addr_type = inita_type; - report->evt_type |= BLE_HCI_ADV_DIRECT_MASK; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { - /* Just skip it for now*/ - i += 1; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - ble_ll_ext_scan_parse_adv_info(report, (ext_hdr + i)); - i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } else if (report->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) { - report->sid = (aux_data->adi >> 12); - } - - /* In this point of time we don't want to care about aux ptr */ - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - i += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { - report->periodic_itvl = get_le16(ext_hdr + i + 2); - i += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { - report->tx_power = *(ext_hdr + i); - i += BLE_LL_EXT_ADV_TX_POWER_SIZE; - } - - /* TODO Handle ACAD if needed */ - } - - /* In the event we need information on primary and secondary PHY used during - * advertising. - */ - if (!aux_data) { - report->pri_phy = ble_hdr->rxinfo.phy; - goto done; - } - - report->sec_phy = aux_data->aux_phy; - report->pri_phy = aux_data->aux_primary_phy; - - if (ext_hdr_len) { - /* Adjust mbuf to contain advertising data only */ - os_mbuf_adj(om, ext_hdr_len); - } - - /* Let us first keep update event type in aux data. - * Note that in aux chain and aux scan response packets - * we do miss original event type, which we need for advertising report. - */ - aux_data->evt_type |= report->evt_type; - report->evt_type = aux_data->evt_type; - -done: - return pdu_len - ext_hdr_len - 1; -} - static int ble_ll_scan_get_addr_from_ext_adv(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr, uint8_t **addr, uint8_t *addr_type, @@ -1968,8 +1801,6 @@ ble_ll_scan_get_addr_data_from_legacy(uint8_t pdu_type, uint8_t *rxbuf, { BLE_LL_ASSERT(pdu_type < BLE_ADV_PDU_TYPE_ADV_EXT_IND); - addrd->adva_present = true; - addrd->adva = rxbuf + BLE_LL_PDU_HDR_LEN; addrd->adva_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); @@ -1982,79 +1813,45 @@ ble_ll_scan_get_addr_data_from_legacy(uint8_t pdu_type, uint8_t *rxbuf, } } -/* - * Matches incoming PDU using scan filter policy and whitelist, if applicable. - * This will also resolve addresses and update flags/fields in header and - * addr_data as needed. - * - * @return 0 = no match - * 1 = match - * 2 = match, but do not scan - */ -static int -ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *addrd) +int +ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, + struct ble_ll_scan_addr_data *addrd, uint8_t *scan_ok) { - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; #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 - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; struct ble_ll_resolv_entry *rl = NULL; #endif bool scan_req_allowed = true; - int resolved = 0; + bool resolved; - /* Use AdvA as initial advertiser address, we may try to resolve it later */ + /* Note: caller is expected to fill adva, targeta and rpa_index in addrd */ + + /* Use AdvA as initial advertiser address, we may change it if resolved */ addrd->adv_addr = addrd->adva; addrd->adv_addr_type = addrd->adva_type; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* By default, assume AdvA is not resolved */ - rxinfo->rpa_index = -1; + addrd->adva_resolved = 0; + addrd->targeta_resolved = 0; + + BLE_LL_ASSERT((addrd->rpa_index < 0) || + (ble_ll_addr_subtype(addrd->adva, addrd->adva_type) == + BLE_LL_ADDR_SUBTYPE_RPA)); switch (ble_ll_addr_subtype(addrd->adva, addrd->adva_type)) { case BLE_LL_ADDR_SUBTYPE_RPA: - /* - * Only resolve if packet actually contained AdvA. - * In extended advertising PDUs we may use RL index from a PDU that - * already had AdvA (e.g. ADV_EXT_IND in case of AUX_ADV_IND without - * AdvA). In legacy advertising PDUs we always need to resolve AdvA. - */ - if (addrd->adva_present) { - rxinfo->rpa_index = ble_hw_resolv_list_match(); - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - BLE_LL_ASSERT(aux_data); - rxinfo->rpa_index = aux_data->rpa_index; -#else - BLE_LL_ASSERT(false); - rxinfo->rpa_index = -1; -#endif - } - - if (rxinfo->rpa_index < 0) { + if (addrd->rpa_index < 0) { break; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (aux_data) { - aux_data->rpa_index = rxinfo->rpa_index; - } -#endif + addrd->adva_resolved = 1; /* Use resolved identity address as advertiser address */ - rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; + rl = &g_ble_ll_resolv_list[addrd->rpa_index]; addrd->adv_addr = rl->rl_identity_addr; addrd->adv_addr_type = rl->rl_addr_type; - addrd->rl = rl; - - rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; - resolved = 1; break; case BLE_LL_ADDR_SUBTYPE_IDENTITY: - /* - * If AdvA is an identity address, we need to check if that device was + /* If AdvA is an identity address, we need to check if that device was * added to RL in order to use proper privacy mode. */ rl = ble_ll_resolv_list_find(addrd->adva, addrd->adva_type); @@ -2062,12 +1859,12 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad break; } - addrd->rl = rl; - /* Ignore device if using network privacy mode and it has IRK */ if ((rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && rl->rl_has_peer) { - return 0; + return -1; } + + addrd->rpa_index = ble_ll_resolv_get_idx(rl); break; default: /* NRPA goes through filtering policy directly */ @@ -2079,30 +1876,29 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad case BLE_LL_ADDR_SUBTYPE_RPA: /* Check if TargetA can be resolved using the same RL entry as AdvA */ if (rl && ble_ll_resolv_rpa(addrd->targeta, rl->rl_local_irk)) { - rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; + addrd->targeta_resolved = 1; break; } /* Check if scan filter policy allows unresolved RPAs to be processed */ - if (!(scansm->scan_filt_policy & 0x02)) { - return 0; + if (!(scan_filt_policy & 0x02)) { + return -2; } - /* - * We will notify host as requited by scan policy, but make sure we - * do not send scan request since we do not know if this is directed - * to us. + /* Do not send scan request even if scan policy allows unresolved + * RPAs - we do not know if this one if directed to us. */ scan_req_allowed = false; break; case BLE_LL_ADDR_SUBTYPE_IDENTITY: /* We shall ignore identity in TargetA if we are using RPA */ - if ((scansm->own_addr_type & 0x02) && rl && rl->rl_has_local) { - return 0; + if ((own_addr_type & 0x02) && rl && rl->rl_has_local) { + return -1; } + /* Ignore if not directed to us */ if (!ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { - return 0; + return -1; } break; default: @@ -2110,85 +1906,69 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad break; } } + + resolved = addrd->adva_resolved; #else /* Ignore if not directed to us */ if (addrd->targeta && !ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { - return 0; + return -1; } + + resolved = false; #endif /* Check on WL if required by scan filter policy */ - if (scansm->scan_filt_policy & 0x01) { - if (!ble_ll_whitelist_match(addrd->adv_addr, addrd->adv_addr_type, resolved)) { - return 0; - } + if ((scan_filt_policy & 0x01) && + !ble_ll_whitelist_match(addrd->adv_addr, addrd->adv_addr_type, + resolved)) { + return -2; + } + + if (scan_ok) { + *scan_ok = scan_req_allowed; } - return scan_req_allowed ? 1 : 2; + return 0; } static int -ble_ll_scan_rx_isr_on_legacy(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) +ble_ll_scan_rx_isr_on_adv(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; struct ble_ll_scan_phy *scanp = scansm->scanp; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - uint8_t sreq_adva_type; - uint8_t *sreq_adva; +#endif + uint8_t scan_ok; int rc; ble_ll_scan_get_addr_data_from_legacy(pdu_type, rxbuf, addrd); - if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_RSP) { - if (!BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { - /* - * We were not expecting scan response so just ignore and do not - * update backoff. - */ - return -1; - } - - sreq_adva_type = !!(scansm->pdu_data.hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK); - sreq_adva = scansm->pdu_data.adva; - - /* - * Ignore scan response if AdvA does not match AdvA in request and also - * update backoff as if there was no scan response. - */ - if ((addrd->adva_type != sreq_adva_type) || - memcmp(addrd->adva, sreq_adva, BLE_DEV_ADDR_LEN)) { - ble_ll_scan_req_backoff(scansm, 0); - return -1; - } - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* - * We are not pushing this one through filters so need to update - * rpa_index here as otherwise pkt_in won't be able to determine - * advertiser address properly. - */ - rxinfo->rpa_index = ble_hw_resolv_list_match(); - if (rxinfo->rpa_index >= 0) { - rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; - } + addrd->rpa_index = ble_hw_resolv_list_match(); #endif - rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; - - return 0; - } - - rc = ble_ll_scan_rx_filter(hdr, addrd); - if (!rc) { + rc = ble_ll_scan_rx_filter(scansm->own_addr_type, scansm->scan_filt_policy, + addrd, &scan_ok); + if (rc < 0) { return 0; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; + rxinfo->rpa_index = addrd->rpa_index; + if (addrd->adva_resolved) { + rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; + } + if (addrd->targeta_resolved) { + rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; + } +#endif - if (rc == 2) { + if (!scan_ok) { /* Scan request forbidden by filter policy */ return 0; } @@ -2198,94 +1978,55 @@ ble_ll_scan_rx_isr_on_legacy(uint8_t pdu_type, uint8_t *rxbuf, (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)); } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static int -ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) +ble_ll_scan_rx_isr_on_scan_rsp(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - struct ble_ll_scan_phy *scanp = scansm->scanp; struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - struct ble_ll_aux_data *aux_data; - int rc; + uint8_t sreq_adva_type; + uint8_t *sreq_adva; - if (!scansm->ext_scanning) { - return -1; - } + ble_ll_scan_get_addr_data_from_legacy(pdu_type, rxbuf, addrd); - rc = ble_ll_scan_update_aux_data(hdr, rxbuf, &addrd->adva_present); - if (rc < 0) { - rxinfo->flags |= BLE_MBUF_HDR_F_AUX_INVALID; + if (!BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { + /* + * We were not expecting scan response so just ignore and do not + * update backoff. + */ return -1; - } else if (rc == 0) { - rxinfo->flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT; } - /* Now we can update aux_data from header since it may have just been created */ - aux_data = rxinfo->user_data; + sreq_adva_type = !!(scansm->pdu_data.hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK); + sreq_adva = scansm->pdu_data.adva; /* - * Restore proper header flags if filtering was already done successfully on - * some previous PDU in an event. + * Ignore scan response if AdvA does not match AdvA in request and also + * update backoff as if there was no scan response. */ - 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; - } - if (aux_data->flags & BLE_LL_AUX_IS_TARGETA_RESOLVED) { - rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; - } -#endif - goto done; + if ((addrd->adva_type != sreq_adva_type) || + memcmp(addrd->adva, sreq_adva, BLE_DEV_ADDR_LEN)) { + ble_ll_scan_req_backoff(scansm, 0); + return -1; } - if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { - addrd->adva = aux_data->adva; - addrd->adva_type = aux_data->adva_type; - } else { - /* Accept this PDU and wait for AdvA in aux */ - rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; - return 0; - } - if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { - addrd->targeta = aux_data->targeta; - addrd->targeta_type = aux_data->targeta_type; - } else { - addrd->targeta = NULL; - } - - rc = ble_ll_scan_rx_filter(hdr, addrd); - if (!rc) { - return 0; - } - - rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; - +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) /* - * Once we matched device, there's no need to go through filtering on every - * other PDU in an event so just store info required to restore state for - * subsequent PDUs in aux_data. + * We are not pushing this one through filters so need to update + * rpa_index here as otherwise pkt_in won't be able to determine + * advertiser address properly. */ - aux_data->flags |= BLE_LL_AUX_IS_MATCHED; - if (rxinfo->flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { - aux_data->flags |= BLE_LL_AUX_IS_TARGETA_RESOLVED; - /* AdvA state is already stored in rpa_index */ + rxinfo->rpa_index = ble_hw_resolv_list_match(); + if (rxinfo->rpa_index >= 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; } +#endif - if (rc == 2) { - /* Scan request forbidden by filter policy */ - return 0; - } + rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; -done: - return (scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && - ((rxbuf[2] >> 6) == BLE_LL_EXT_ADV_MODE_SCAN); + return 0; } -#endif static bool ble_ll_scan_send_scan_req(uint8_t pdu_type, uint8_t *rxbuf, @@ -2294,23 +2035,11 @@ ble_ll_scan_send_scan_req(uint8_t pdu_type, uint8_t *rxbuf, { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data = rxinfo->user_data; - uint8_t phy_mode; -#endif bool is_ext_adv = false; + int8_t rpa_index; uint16_t adi = 0; int rc; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { - if (ble_ll_scan_get_adi(aux_data, &adi) < 0) { - return false; - } - is_ext_adv = true; - } -#endif - /* Check if we already scanned this device successfully */ if (ble_ll_scan_have_rxd_scan_rsp(addrd->adv_addr, addrd->adv_addr_type, is_ext_adv, adi)) { @@ -2327,15 +2056,15 @@ ble_ll_scan_send_scan_req(uint8_t pdu_type, uint8_t *rxbuf, } } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - phy_mode = ble_ll_phy_to_phy_mode(rxinfo->phy, BLE_HCI_LE_PHY_CODED_ANY); - if (ble_ll_sched_scan_req_over_aux_ptr(rxinfo->channel, phy_mode)) { - return false; - } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + rpa_index = addrd->rpa_index; +#else + rpa_index = -1; #endif /* Use original AdvA in scan request (Core 5.1, Vol 6, Part B, section 6.3) */ - ble_ll_scan_req_pdu_prepare(scansm, addrd->adva, addrd->adva_type, addrd->rl); + ble_ll_scan_req_pdu_prepare(scansm, addrd->adva, addrd->adva_type, + rpa_index); rc = ble_phy_tx(ble_ll_scan_req_tx_pdu_cb, scansm, BLE_PHY_TRANSITION_TX_RX); if (rc) { @@ -2345,14 +2074,6 @@ ble_ll_scan_send_scan_req(uint8_t pdu_type, uint8_t *rxbuf, scansm->scan_rsp_pending = 1; rxinfo->flags |= BLE_MBUF_HDR_F_SCAN_REQ_TXD; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (rxinfo->channel < BLE_PHY_NUM_DATA_CHANS) { - /* Keep aux_data for expected scan response */ - scansm->cur_aux_data = ble_ll_scan_aux_data_ref(aux_data); - STATS_INC(ble_ll_stats, aux_scan_req_tx); - } -#endif - return true; } @@ -2388,48 +2109,31 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) return 0; } - rxbuf = rxpdu->om_data; - pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* - * In case aux was expected, copy aux_data for LL to use. Make sure this was - * indeed an aux as otherwise there's no need to process it and just pass to - * LL immediately. - */ - if (scansm->cur_aux_data) { - rxinfo->user_data = scansm->cur_aux_data; - scansm->cur_aux_data = NULL; - if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - return -1; - } - } -#endif - if (!crcok) { goto scan_rx_isr_ignore; } - /* - * Addresses will be always set in handlers, no need to initialize them. We - * only need to initialize rl which may not be always set, depending on how - * filtering goes. - */ - addrd.rl = NULL; + rxbuf = rxpdu->om_data; + pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; switch (pdu_type) { case BLE_ADV_PDU_TYPE_ADV_IND: case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: - case BLE_ADV_PDU_TYPE_SCAN_RSP: case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: - rc = ble_ll_scan_rx_isr_on_legacy(pdu_type, rxbuf, hdr, &addrd); + rc = ble_ll_scan_rx_isr_on_adv(pdu_type, rxbuf, hdr, &addrd); + break; + case BLE_ADV_PDU_TYPE_SCAN_RSP: + rc = ble_ll_scan_rx_isr_on_scan_rsp(pdu_type, rxbuf, hdr, &addrd); break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_ADV_PDU_TYPE_ADV_EXT_IND: - rc = ble_ll_scan_rx_isr_on_aux(pdu_type, rxbuf, hdr, &addrd); - break; + rc = ble_ll_scan_aux_rx_isr_end_on_ext(&g_ble_ll_scan_sm, rxpdu); + if (rc < 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; + } + ble_ll_state_set(BLE_LL_STATE_STANDBY); + return -1; #endif default: /* This is not something we would like to process here */ @@ -2579,281 +2283,6 @@ ble_ll_scan_wfr_timer_exp(void) ble_phy_restart_rx(); } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/* - * Send extended advertising report - * - * @return -1 on error (data truncated or other error) - * 0 on success (data status is "completed") - * 1 on success (data status is not "completed") - */ -static int -ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type, - uint8_t *inita, uint8_t inita_type, - struct os_mbuf *om, - struct ble_mbuf_hdr *hdr) -{ - struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data; - struct ble_hci_ev_le_subev_ext_adv_rpt *ev; - struct ext_adv_report *report; - struct ble_hci_ev *hci_ev; - struct ble_hci_ev *hci_ev_next; - int offset; - int datalen; - int rc; - bool need_event; - bool is_scannable_aux; - uint8_t max_data_len; - - if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { - rc = -1; - goto done; - } - - /* Just ignore PDU if truncated was already sent. - * This can happen if next PDU in chain was already received before we - * manage to cancel scan on error (which resulted in sending truncated HCI - * event) - */ - if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)) { - rc = -1; - goto done; - } - - /* - * We keep one allocated event in aux_data to be able to truncate chain - * properly in case of error. If there is no event in aux_data it means this - * is the first event for this chain. - */ - if (aux_data && aux_data->evt) { - hci_ev = aux_data->evt; - aux_data->evt = NULL; - - hci_ev->length = sizeof(*ev) + sizeof(*report); - } else { - hci_ev = ble_ll_scan_get_ext_adv_report(NULL); - if (!hci_ev) { - rc = -1; - goto done; - } - } - - ev = (void *) hci_ev->data; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* If RPA has been used, make sure we use correct address types - * in the advertising report. - */ - if (BLE_MBUF_HDR_RESOLVED(hdr)) { - adva_type += 2; - } - if (BLE_MBUF_HDR_TARGETA_RESOLVED(hdr)) { - inita_type += 2; - } -#endif - - datalen = ble_ll_scan_parse_ext_hdr(om, adva, adva_type, inita, inita_type, - hdr, ev->reports); - if (datalen < 0) { - rc = -1; - - /* Need to send truncated event if we already sent some reports */ - if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED)); - - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; - - report = ev->reports; - report->data_len = 0; - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; - - ble_ll_hci_event_send(hci_ev); - goto done; - } - - ble_hci_trans_buf_free((uint8_t *)hci_ev); - goto done; - } - - is_scannable_aux = aux_data && - (aux_data->evt_type & BLE_HCI_ADV_SCAN_MASK) && - !(aux_data->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK); - - max_data_len = BLE_LL_MAX_EVT_LEN - sizeof(*hci_ev) - sizeof(*ev) - sizeof(*report); - offset = 0; - - do { - hci_ev_next = NULL; - - ev = (void *) hci_ev->data; - report = ev->reports; - - report->data_len = min(max_data_len, datalen - offset); - - /* adjust event length */ - hci_ev->length += report->data_len; - report->rssi = hdr->rxinfo.rssi; - - os_mbuf_copydata(om, offset, report->data_len, report->data); - offset += report->data_len; - - /* - * We need another event if either there are still some data left to - * send in current PDU or scan is not completed. There are two exceptions - * though: - * - we sent all data from this PDU and there is scan error set already; - * it may be set before entering current function due to failed aux - * scan scheduling - * - this is a scannable event which is not a scan response - */ - need_event = ((offset < datalen) || (aux_data && !(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_COMPLETE))) && - !((offset == datalen) && (aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR)) && - !is_scannable_aux; - - if (need_event) { - /* - * We will need another event so let's try to allocate one now. If - * we cannot do this, need to mark event as truncated. - */ - hci_ev_next = ble_ll_scan_get_ext_adv_report(report); - - if (hci_ev_next) { - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_INCOMPLETE; - rc = 1; - } else { - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; - rc = -1; - } - } else if (aux_data && (aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR)) { - report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; - rc = -1; - } else { - rc = 0; - } - - if ((rc == -1) && aux_data) { - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - - if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { - ble_hci_trans_buf_free((uint8_t *)hci_ev); - goto done; - } - - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED; - } else if (!is_scannable_aux) { - /* - * We do not set 'sent' flags for scannable AUX since we only care - * about scan response that will come next. - */ - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_ANY; - if (rc == 0) { - aux_data->flags_ll |= BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED; - } - } - - ble_ll_hci_event_send(hci_ev); - - hci_ev = hci_ev_next; - } while ((offset < datalen) && hci_ev); - - BLE_LL_ASSERT(offset <= datalen); - - if (aux_data) { - /* Store any event left for later use */ - aux_data->evt = hci_ev; - } else { - /* If it is empty beacon, evt shall be NULL */ - BLE_LL_ASSERT(!hci_ev); - } - -done: - if (!aux_data) { - return rc; - } - - if (rc == 0) { - if (aux_data->evt_type & BLE_HCI_ADV_SCAN_RSP_MASK) { - /* Complete scan response can be added to duplicates list */ - ble_ll_scan_add_scan_rsp_adv(aux_data->adva, aux_data->adva_type, - 1, aux_data->adi); - } else if (is_scannable_aux) { - /* - * Scannable AUX is marked as incomplete because we do not want to - * add this to duplicates list now, this should happen only after - * we receive complete scan response. The drawback here is that we - * will keep receiving reports for scannable PDUs until complete - * scan response is received. - * - * XXX ^^ extend duplicates list to fix - */ - rc = 1; - } - } else if (rc < 0) { - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - } - - return rc; -} -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) -static void -ble_ll_scan_check_periodic_sync(const struct os_mbuf *om, struct ble_mbuf_hdr *rxhdr, - uint8_t *adva, uint8_t adva_type, int rpa_index) -{ - uint8_t pdu_len; - uint8_t ext_hdr_len; - uint8_t ext_hdr_flags; - uint8_t *ext_hdr; - uint8_t *rxbuf = om->om_data; - uint8_t sid; - int i; - - pdu_len = rxbuf[1]; - if (pdu_len == 0) { - return; - } - - ext_hdr_len = rxbuf[2] & 0x3F; - - if (ext_hdr_len) { - ext_hdr_flags = rxbuf[3]; - ext_hdr = &rxbuf[4]; - i = 0; - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - i += BLE_LL_EXT_ADV_ADVA_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - i += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { - i += 1; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - sid = (get_le16(ext_hdr + i) >> 12); - i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } else { - /* ADI is mandatory */ - return; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - i += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { - ble_ll_sync_info_event(adva, adva_type, rpa_index, sid, rxhdr, - ext_hdr + i); - } - } -} -#endif - static inline void ble_ll_scan_dup_move_to_head(struct ble_ll_scan_dup_entry *e) { @@ -2919,20 +2348,17 @@ ble_ll_scan_dup_check_legacy(uint8_t addr_type, uint8_t *addr, uint8_t pdu_type) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static int -ble_ll_scan_dup_check_ext(uint8_t addr_type, uint8_t *addr, - struct ble_ll_aux_data *aux_data) +int +ble_ll_scan_dup_check_ext(uint8_t addr_type, uint8_t *addr, bool has_aux, + uint16_t adi) { struct ble_ll_scan_dup_entry *e; - bool has_aux; bool is_anon; - uint16_t adi; uint8_t type; int rc; - has_aux = aux_data != NULL; is_anon = addr == NULL; - adi = has_aux ? aux_data->adi : 0; + adi = has_aux ? adi : 0; type = BLE_LL_SCAN_ENTRY_TYPE_EXT(addr_type, has_aux, is_anon, adi); @@ -2971,19 +2397,16 @@ ble_ll_scan_dup_check_ext(uint8_t addr_type, uint8_t *addr, return rc; } -static int -ble_ll_scan_dup_update_ext(uint8_t addr_type, uint8_t *addr, - struct ble_ll_aux_data *aux_data) +int +ble_ll_scan_dup_update_ext(uint8_t addr_type, uint8_t *addr, bool has_aux, + uint16_t adi) { struct ble_ll_scan_dup_entry *e; - bool has_aux; bool is_anon; - uint16_t adi; uint8_t type; - has_aux = aux_data != NULL; is_anon = addr == NULL; - adi = has_aux ? aux_data->adi : 0; + adi = has_aux ? adi : 0; type = BLE_LL_SCAN_ENTRY_TYPE_EXT(addr_type, has_aux, is_anon, adi); @@ -3019,7 +2442,6 @@ ble_ll_scan_rx_pkt_in_restore_addr_data(struct ble_mbuf_hdr *hdr, rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; addrd->adv_addr = rl->rl_identity_addr; addrd->adv_addr_type = rl->rl_addr_type; - addrd->rl = rl; } if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { addrd->targeta = ble_ll_get_our_devaddr(scansm->own_addr_type & 1); @@ -3065,143 +2487,6 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om, } } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - uint8_t *rxbuf = om->om_data; -#endif - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - struct ble_ll_aux_data *aux_data = rxinfo->user_data; - bool send_hci_report; - int rc; - - if (aux_data) { - aux_data->flags_ll |= aux_data->flags_isr; - } - - /* - * For every new extended advertising event scanned, rx_isr_end will either - * allocate new aux_data or set 'invalid' flag. This means if no 'invalid' - * flag is set, aux_data is always valid. - */ - - /* Drop on scan error or if we received not what we expected to receive */ - if (!BLE_MBUF_HDR_CRC_OK(hdr) || - 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) || - !scansm->scan_enabled) { - if (aux_data) { - ble_ll_scan_end_adv_evt(aux_data); - ble_ll_scan_aux_data_unref(aux_data); - rxinfo->user_data = NULL; - } - return; - } - - BLE_LL_ASSERT(aux_data); - - if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { - addrd->adva = aux_data->adva; - addrd->adva_type = aux_data->adva_type; - } else { - addrd->adva = NULL; - addrd->adva_type = 0; - } - if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { - addrd->targeta = aux_data->targeta; - addrd->targeta_type = aux_data->targeta_type; - } else { - addrd->targeta = NULL; - addrd->targeta_type = 0; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - /* - * Periodic scan uses own filter list so we need to let it do own filtering - * regardless of scanner filtering. Just make sure we already have AdvA. - */ - if (ble_ll_sync_enabled() && - ((rxbuf[2] >> 6) == BLE_LL_EXT_ADV_MODE_NON_CONN) && addrd->adva && - !(aux_data->flags_ll & BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED)) { - ble_ll_scan_check_periodic_sync(om, hdr, addrd->adva, addrd->adva_type, - rxinfo->rpa_index); - } -#endif - - /* Ignore if device was not matched by either whitelist or scan policy */ - if (!BLE_MBUF_HDR_DEVMATCH(hdr)) { - goto scan_continue; - } - - ble_ll_scan_rx_pkt_in_restore_addr_data(hdr, addrd); - - /* - * If there is AuxPtr in this PDU, we should first try to schedule scan for - * subsequent aux. - */ - if (BLE_MBUF_HDR_WAIT_AUX(hdr)) { - if (ble_ll_sched_aux_scan(hdr, scansm, aux_data)) { - rxinfo->flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT; - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - - /* Silently ignore if no HCI event was sent to host */ - if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY)) { - goto scan_continue; - } - } - - /* Ignore if this was just ADV_EXT_IND with AuxPtr, will process aux */ - if (!(aux_data->flags_ll & BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED)) { - goto scan_continue; - } - - STATS_INC(ble_ll_stats, aux_chain_cnt); - } - - send_hci_report = !scansm->scan_filt_dups || - !ble_ll_scan_dup_check_ext(addrd->adv_addr_type, - addrd->adv_addr, aux_data); - if (send_hci_report) { - rc = ble_ll_hci_send_ext_adv_report(pdu_type, - addrd->adv_addr, addrd->adv_addr_type, - addrd->targeta, addrd->targeta_type, - om, hdr); - if ((rc < 0) && BLE_MBUF_HDR_WAIT_AUX(hdr)) { - /* Data were truncated so stop scanning for subsequent auxes */ - aux_data->flags_ll |= BLE_LL_AUX_FLAG_SCAN_ERROR; - - if (ble_ll_sched_rmv_elem(&aux_data->sch) == 0) { - ble_ll_scan_aux_data_unref(aux_data->sch.cb_arg); - aux_data->sch.cb_arg = NULL; - } - } else if ((rc == 0) && scansm->scan_filt_dups) { - /* Complete data were send so we can update scan_dup list */ - ble_ll_scan_dup_update_ext(addrd->adv_addr_type, addrd->adv_addr, - aux_data); - } - } - - if (BLE_MBUF_HDR_SCAN_RSP_RXD(hdr)) { - /* - * For now assume success if we just received direct scan response, - * don't care about complete aux chain. - */ - ble_ll_scan_req_backoff(scansm, 1); - } - -scan_continue: - ble_ll_scan_aux_data_unref(rxinfo->user_data); - rxinfo->user_data = NULL; -} -#endif - /** * Process a received PDU while in the scanning state. * @@ -3213,15 +2498,11 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om, void ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hdr) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; - struct ble_ll_aux_data *aux_data = rxinfo->user_data; -#endif struct ble_ll_scan_addr_data addrd; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (aux_data || (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND)) { - ble_ll_scan_rx_pkt_in_on_aux(ptype, om, hdr, &addrd); + if (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { + ble_ll_scan_aux_pkt_in_on_ext(om, hdr); ble_ll_scan_chk_resume(); return; } @@ -3976,4 +3257,7 @@ ble_ll_scan_init(void) TAILQ_INIT(&g_scan_dup_list); ble_ll_scan_common_init(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_ll_scan_aux_init(); +#endif } diff --git a/nimble/controller/src/ble_ll_scan_aux.c b/nimble/controller/src/ble_ll_scan_aux.c new file mode 100644 index 0000000000..128b45a7cc --- /dev/null +++ b/nimble/controller/src/ble_ll_scan_aux.c @@ -0,0 +1,1555 @@ +/* + * 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 + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + +#include +#include +#include +#include +#include "os/os.h" +#include "nimble/ble.h" +#include "nimble/hci_common.h" +#include "nimble/ble_hci_trans.h" +#include "controller/ble_phy.h" +#include "controller/ble_hw.h" +#include "controller/ble_ll.h" +#include "controller/ble_ll_sched.h" +#include "controller/ble_ll_scan.h" +#include "controller/ble_ll_scan_aux.h" +#include "controller/ble_ll_hci.h" +#include "controller/ble_ll_whitelist.h" +#include "controller/ble_ll_resolv.h" +#include "controller/ble_ll_sync.h" + +#define BLE_LL_SCAN_AUX_F_AUX_ADV 0x0001 +#define BLE_LL_SCAN_AUX_F_AUX_CHAIN 0x0002 +#define BLE_LL_SCAN_AUX_F_MATCHED 0x0004 +#define BLE_LL_SCAN_AUX_F_W4_SCAN_RSP 0x0008 +#define BLE_LL_SCAN_AUX_F_SCANNED 0x0010 +#define BLE_LL_SCAN_AUX_F_HAS_ADVA 0x0020 +#define BLE_LL_SCAN_AUX_F_HAS_TARGETA 0x0040 +#define BLE_LL_SCAN_AUX_F_HAS_ADI 0x0080 +#define BLE_LL_SCAN_AUX_F_RESOLVED_ADVA 0x0100 +#define BLE_LL_SCAN_AUX_F_RESOLVED_TARGETA 0x0200 + +#define BLE_LL_SCAN_AUX_H_SENT_ANY 0x01 +#define BLE_LL_SCAN_AUX_H_DONE 0x02 +#define BLE_LL_SCAN_AUX_H_TRUNCATED 0x04 + +struct ble_ll_scan_aux_data { + uint16_t flags; + uint8_t hci_state; + + uint8_t scan_type; + + uint8_t pri_phy; + uint8_t sec_phy; + uint8_t chan; + uint8_t offset_unit : 1; + uint32_t aux_ptr; + struct ble_ll_sched_item sch; + struct ble_npl_event break_ev; + struct ble_hci_ev *hci_ev; + + uint16_t adi; + + uint8_t adva[6]; + uint8_t targeta[6]; + uint8_t adva_type : 1; + uint8_t targeta_type : 1; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + int8_t rpa_index; +#endif +}; + +#define AUX_MEMPOOL_SIZE (OS_MEMPOOL_SIZE( \ + MYNEWT_VAL(BLE_LL_SCAN_AUX_SEGMENT_CNT), \ + sizeof(struct ble_ll_scan_aux_data))) + +static os_membuf_t aux_data_mem[AUX_MEMPOOL_SIZE]; +static struct os_mempool aux_data_pool; + +static struct ble_ll_scan_aux_data *aux_data_current; + +static void ble_ll_hci_ev_send_ext_adv_truncated_report(struct ble_ll_scan_aux_data *aux); + +static inline uint8_t * +ble_ll_scan_aux_get_own_addr(void) +{ + uint8_t own_addr_type; + + own_addr_type = ble_ll_scan_get_own_addr_type() & 1; + + return ble_ll_get_our_devaddr(own_addr_type); +} + +static int +ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch) +{ + struct ble_ll_scan_aux_data *aux = sch->cb_arg; + uint32_t wfr_us; +#if BLE_LL_BT5_PHY_SUPPORTED + uint8_t phy_mode; +#endif + uint8_t lls; + int rc; + + BLE_LL_ASSERT(aux); + + lls = ble_ll_state_get(); + BLE_LL_ASSERT(lls == BLE_LL_STATE_STANDBY); + + rc = ble_phy_setchan(aux->chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); + BLE_LL_ASSERT(rc == 0); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + ble_phy_encrypt_disable(); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (ble_ll_resolv_enabled()) { + ble_phy_resolv_list_enable(); + } else { + ble_phy_resolv_list_disable(); + } +#endif + +#if BLE_LL_BT5_PHY_SUPPORTED + phy_mode = ble_ll_phy_to_phy_mode(aux->sec_phy, BLE_HCI_LE_PHY_CODED_ANY); + ble_phy_mode_set(phy_mode, phy_mode); +#endif + + rc = ble_phy_rx_set_start_time(sch->start_time + g_ble_ll_sched_offset_ticks, + sch->remainder); + if (rc != 0 && rc != BLE_PHY_ERR_RX_LATE) { + ble_ll_scan_aux_break(aux); + return BLE_LL_SCHED_STATE_DONE; + } + + /* Keep listening even if we are late, we may still receive something */ + + if (ble_ll_scan_get_filt_policy() & 1) { + ble_ll_whitelist_enable(); + } else { + ble_ll_whitelist_disable(); + } + + wfr_us = aux->offset_unit ? 300 : 30; + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_us); + + aux_data_current = aux; + + ble_ll_state_set(BLE_LL_STATE_SCAN_AUX); + + return BLE_LL_SCHED_STATE_DONE; +} + +static struct ble_ll_scan_aux_data * +ble_ll_scan_aux_alloc(void) +{ + struct ble_ll_scan_aux_data *aux; + + aux = os_memblock_get(&aux_data_pool); + if (!aux) { + return NULL; + } + + memset(aux, 0, sizeof(*aux)); + + aux->sch.sched_cb = ble_ll_scan_aux_sched_cb; + aux->sch.sched_type = BLE_LL_SCHED_TYPE_SCAN_AUX; + aux->sch.cb_arg = aux; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + aux->rpa_index = -1; +#endif + + return aux; +} + +static void +ble_ll_scan_aux_free(struct ble_ll_scan_aux_data *aux) +{ + BLE_LL_ASSERT(!aux->sch.enqueued); + BLE_LL_ASSERT(aux->hci_ev == NULL); + BLE_LL_ASSERT((aux->hci_state & BLE_LL_SCAN_AUX_H_DONE) || + !(aux->hci_state & BLE_LL_SCAN_AUX_H_SENT_ANY)); + + os_memblock_put(&aux_data_pool, aux); +} + +static void +ble_ll_scan_aux_update_scan_backoff(struct ble_ll_scan_aux_data *aux) +{ + if (!(aux->flags & BLE_LL_SCAN_AUX_F_W4_SCAN_RSP) && + !(aux->flags & BLE_LL_SCAN_AUX_F_SCANNED)) { + return; + } + + if ((aux->hci_state & BLE_LL_SCAN_AUX_H_DONE) && + !(aux->hci_state & BLE_LL_SCAN_AUX_H_TRUNCATED)) { + ble_ll_scan_backoff_update(1); + } else { + ble_ll_scan_backoff_update(0); + } +} + +static inline bool +ble_ll_scan_aux_need_truncation(struct ble_ll_scan_aux_data *aux) +{ + return (aux->hci_state & BLE_LL_SCAN_AUX_H_SENT_ANY) && + !(aux->hci_state & BLE_LL_SCAN_AUX_H_DONE); +} + +static struct ble_hci_ev * +ble_ll_hci_ev_alloc_ext_adv_report_for_aux(struct ble_ll_scan_addr_data *addrd, + struct ble_ll_scan_aux_data *aux) +{ + struct ble_hci_ev_le_subev_ext_adv_rpt *hci_subev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; + + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { + return NULL; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*hci_subev) + sizeof(*report); + + hci_subev = (void *)hci_ev->data; + hci_subev->subev_code = BLE_HCI_LE_SUBEV_EXT_ADV_RPT; + hci_subev->num_reports = 1; + + report = hci_subev->reports; + + memset(report, 0, sizeof(*report)); + + report->evt_type = 0; + if (addrd->adva) { + report->addr_type = addrd->adv_addr_type; + memcpy(report->addr, addrd->adv_addr, 6); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (addrd->adva_resolved) { + report->addr_type += 2; + } +#endif + } else { + report->addr_type = 0xff; + } + report->pri_phy = aux->pri_phy; + report->sec_phy = aux->sec_phy; + report->sid = aux->adi >> 12; + report->tx_power = 0x7f; + report->rssi = 0x7f; + report->periodic_itvl = 0; + if (addrd->targeta) { + report->evt_type |= BLE_HCI_ADV_DIRECT_MASK; + report->dir_addr_type = addrd->targeta_type; + memcpy(report->dir_addr, addrd->targeta, 6); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (addrd->targeta_resolved) { + report->dir_addr_type += 2; + } +#endif + } + report->data_len = 0; + + return hci_ev; +} + +static struct ble_hci_ev * +ble_ll_hci_ev_dup_ext_adv_report(struct ble_hci_ev *hci_ev_src) +{ + struct ble_hci_ev_le_subev_ext_adv_rpt *hci_subev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; + + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { + return NULL; + } + + memcpy(hci_ev, hci_ev_src, sizeof(*hci_ev) + sizeof(*hci_subev) + + sizeof(*report)); + hci_ev->length = sizeof(*hci_subev) + sizeof(*report); + + hci_subev = (void *)hci_ev->data; + + report = hci_subev->reports; + report->data_len = 0; + + return hci_ev; +} + +static void +ble_ll_hci_ev_update_ext_adv_report_from_aux(struct ble_hci_ev *hci_ev, + struct os_mbuf *rxpdu, + struct ble_mbuf_hdr *rxhdr) +{ + struct ble_hci_ev_le_subev_ext_adv_rpt *hci_subev; + struct ext_adv_report *report; + uint8_t adv_mode; + uint8_t eh_len; + uint8_t eh_flags; + uint8_t *eh_data; + uint8_t *rxbuf; + + hci_subev = (void *)hci_ev->data; + report = hci_subev->reports; + rxbuf = rxpdu->om_data; + + adv_mode = rxbuf[2] >> 6; + eh_len = rxbuf[2] & 0x3f; + eh_flags = rxbuf[3]; + eh_data = &rxbuf[4]; + + report->evt_type |= adv_mode; + if (rxhdr->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD) { + report->evt_type |= BLE_HCI_ADV_SCAN_MASK | BLE_HCI_ADV_SCAN_RSP_MASK; + } + report->sec_phy = rxhdr->rxinfo.phy; + + /* Strip PDU header and ext header, leave only AD */ + os_mbuf_adj(rxpdu, 3 + eh_len); + + /* + * We only care about SyncInfo and TxPower so don't bother parsing if they + * are not present, just set to 'unknown' values. + */ + if ((eh_len == 0) || !(eh_flags & ((1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT) | + (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)))) { + report->periodic_itvl = 0; + report->tx_power = 0x7f; + return; + } + /* Now parse extended header... */ + + if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + eh_data += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + eh_data += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + eh_data += BLE_LL_EXT_ADV_CTE_INFO_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + eh_data += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + eh_data += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { + report->periodic_itvl = get_le16(eh_data + 2); + eh_data += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; + } else { + report->periodic_itvl = 0; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { + report->tx_power = *eh_data; + } else { + report->tx_power = 0x7f; + } +} + +static void +ble_ll_hci_ev_update_ext_adv_report_from_ext(struct ble_hci_ev *hci_ev, + struct os_mbuf *rxpdu, + struct ble_mbuf_hdr *rxhdr) +{ + struct ble_mbuf_hdr_rxinfo *rxinfo = &rxhdr->rxinfo; + struct ble_hci_ev_le_subev_ext_adv_rpt *hci_subev; + struct ext_adv_report *report; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_resolv_entry *rl; +#endif + uint8_t pdu_hdr; + uint8_t adv_mode; + uint8_t eh_len; + uint8_t eh_flags; + uint8_t *eh_data; + uint8_t *rxbuf; + + rxbuf = rxpdu->om_data; + + pdu_hdr = rxbuf[0]; + adv_mode = rxbuf[2] >> 6; + eh_len = rxbuf[2] & 0x3f; + eh_flags = rxbuf[3]; + eh_data = &rxbuf[4]; + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*hci_subev) + sizeof(*report); + + hci_subev = (void *)hci_ev->data; + hci_subev->subev_code = BLE_HCI_LE_SUBEV_EXT_ADV_RPT; + hci_subev->num_reports = 1; + + report = hci_subev->reports; + + memset(report, 0, sizeof(*report)); + + report->evt_type = adv_mode; + + report->pri_phy = rxinfo->phy; + report->sec_phy = 0; + report->sid = 0xff; + report->rssi = rxhdr->rxinfo.rssi; + report->periodic_itvl = 0; + report->data_len = 0; + + /* Now parse extended header... */ + + if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (rxinfo->rpa_index >= 0) { + rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; + report->addr_type = rl->rl_addr_type + 2; + memcpy(report->addr, rl->rl_identity_addr, 6); + } else { + report->addr_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_MASK); + memcpy(report->addr, eh_data, 6); + } +#else + report->addr_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_MASK); + memcpy(report->addr, eh_data, 6); +#endif + eh_data += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + report->evt_type |= BLE_HCI_ADV_DIRECT_MASK; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (rxinfo->flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { + report->dir_addr_type = (ble_ll_scan_get_own_addr_type() & 1) + 2; + memcpy(report->dir_addr, ble_ll_scan_aux_get_own_addr(), 6); + } else { + report->dir_addr_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK); + memcpy(report->dir_addr, eh_data, 6); + } +#else + report->dir_addr_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK); + memcpy(report->dir_addr, eh_data, 6); +#endif + eh_data += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + eh_data += BLE_LL_EXT_ADV_CTE_INFO_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + eh_data += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + eh_data += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { + eh_data += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { + report->tx_power = *eh_data; + } else { + report->tx_power = 0x7f; + } + + /* Strip PDU header and ext header, leave only AD */ + os_mbuf_adj(rxpdu, 3 + eh_len); + +} + +static void +ble_ll_hci_ev_send_ext_adv_truncated_report(struct ble_ll_scan_aux_data *aux) +{ + struct ble_hci_ev_le_subev_ext_adv_rpt *hci_subev; + struct ext_adv_report *report; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { + return; + } + + hci_ev = aux->hci_ev; + aux->hci_ev = NULL; + + BLE_LL_ASSERT(hci_ev); + + hci_subev = (void *)hci_ev->data; + report = hci_subev->reports; + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; + + ble_ll_hci_event_send(hci_ev); + + aux->hci_state |= BLE_LL_SCAN_AUX_H_DONE | BLE_LL_SCAN_AUX_H_TRUNCATED; +} + +static int +ble_ll_hci_ev_send_ext_adv_report(struct os_mbuf *rxpdu, + struct ble_mbuf_hdr *rxhdr, + struct ble_hci_ev **hci_ev) +{ + struct ble_mbuf_hdr_rxinfo *rxinfo = &rxhdr->rxinfo; + struct ble_hci_ev_le_subev_ext_adv_rpt *hci_subev; + struct ble_hci_ev *hci_ev_next; + struct ext_adv_report *report; + bool truncated = false; + int max_data_len; + int data_len; + int offset; + + data_len = OS_MBUF_PKTLEN(rxpdu); + max_data_len = BLE_LL_MAX_EVT_LEN - + sizeof(**hci_ev) - sizeof(*hci_subev) - sizeof(*report); + offset = 0; + hci_ev_next = NULL; + + do { + hci_subev = (void *)(*hci_ev)->data; + report = hci_subev->reports; + + report->rssi = rxinfo->rssi; + + report->data_len = min(max_data_len, data_len - offset); + os_mbuf_copydata(rxpdu, offset, report->data_len, report->data); + (*hci_ev)->length += report->data_len; + + offset += report->data_len; + + /* + * We need another event if either there are still some data left in + * this PDU or scan for next aux is scheduled. + */ + if ((offset < data_len) || + (rxinfo->flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT)) { + hci_ev_next = ble_ll_hci_ev_dup_ext_adv_report(*hci_ev); + if (hci_ev_next) { + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_INCOMPLETE; + } else { + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; + } + } + + switch (report->evt_type & BLE_HCI_ADV_DATA_STATUS_MASK) { + case BLE_HCI_ADV_DATA_STATUS_TRUNCATED: + truncated = true; + /* no break */ + case BLE_HCI_ADV_DATA_STATUS_COMPLETE: + BLE_LL_ASSERT(!hci_ev_next); + break; + case BLE_HCI_ADV_DATA_STATUS_INCOMPLETE: + BLE_LL_ASSERT(hci_ev_next); + break; + default: + BLE_LL_ASSERT(0); + } + + ble_ll_hci_event_send(*hci_ev); + + *hci_ev = hci_ev_next; + } while ((offset < data_len) && *hci_ev); + + return truncated ? -1 : 0; +} + + +static int +ble_ll_hci_ev_send_ext_adv_report_for_aux(struct os_mbuf *rxpdu, + struct ble_mbuf_hdr *rxhdr, + struct ble_ll_scan_aux_data *aux, + struct ble_ll_scan_addr_data *addrd) +{ + struct ble_hci_ev *hci_ev; + int rc; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { + return -1; + } + + /* + * We need to always keep one event allocated in aux to be able to truncate + * data properly in case of an error. If there is no event in aux it means + * this is first event and we can silently ignore in case of an error. + */ + if (aux->hci_ev) { + hci_ev = aux->hci_ev; + aux->hci_ev = NULL; + } else { + hci_ev = ble_ll_hci_ev_alloc_ext_adv_report_for_aux(addrd, aux); + if (!hci_ev) { + return -1; + } + } + + ble_ll_hci_ev_update_ext_adv_report_from_aux(hci_ev, rxpdu, rxhdr); + + rc = ble_ll_hci_ev_send_ext_adv_report(rxpdu, rxhdr, &hci_ev); + if (rc < 0) { + BLE_LL_ASSERT(!hci_ev); + aux->hci_state = BLE_LL_SCAN_AUX_H_DONE | BLE_LL_SCAN_AUX_H_TRUNCATED; + } else if (hci_ev) { + aux->hci_state = BLE_LL_SCAN_AUX_H_SENT_ANY; + } else { + aux->hci_state = BLE_LL_SCAN_AUX_H_DONE; + } + + aux->hci_ev = hci_ev; + + return rc; +} + +static void +ble_ll_hci_ev_send_ext_adv_report_for_ext(struct os_mbuf *rxpdu, + struct ble_mbuf_hdr *rxhdr) +{ + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { + return; + } + + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (!hci_ev) { + return; + } + + ble_ll_hci_ev_update_ext_adv_report_from_ext(hci_ev, rxpdu, rxhdr); + + ble_ll_hci_ev_send_ext_adv_report(rxpdu, rxhdr, &hci_ev); + + BLE_LL_ASSERT(!hci_ev); +} + +static void +ble_ll_scan_aux_break_ev(struct ble_npl_event *ev) +{ + struct ble_ll_scan_aux_data *aux = ble_npl_event_get_arg(ev); + + BLE_LL_ASSERT(aux); + + if (ble_ll_scan_aux_need_truncation(aux)) { + ble_ll_hci_ev_send_ext_adv_truncated_report(aux); + } + + ble_ll_scan_aux_update_scan_backoff(aux); + + ble_ll_scan_aux_free(aux); + ble_ll_scan_chk_resume(); +} + +void +ble_ll_scan_aux_break(struct ble_ll_scan_aux_data *aux) +{ + ble_npl_event_init(&aux->break_ev, ble_ll_scan_aux_break_ev, aux); + ble_ll_event_send(&aux->break_ev); +} + +static int +ble_ll_scan_aux_parse_aux_ptr(struct ble_ll_scan_aux_data *aux, + uint32_t aux_ptr, uint32_t *offset_us) +{ + uint8_t offset_unit; + uint32_t offset; + uint8_t chan; + uint8_t phy; + + phy = (aux_ptr >> 21) & 0x07; + switch (phy) { + case 0: + phy = BLE_PHY_1M; + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case 1: + phy = BLE_PHY_2M; + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case 2: + phy = BLE_PHY_CODED; + break; +#endif + default: + return -1; + } + + chan = aux_ptr & 0x3f; + if (chan >= BLE_PHY_NUM_DATA_CHANS) { + return -1; + } + + offset = 30 * ((aux_ptr >> 8) & 0x1fff); + if ((aux_ptr >> 7) & 0x01) { + offset *= 10; + offset_unit = 1; + } else { + offset_unit = 0; + } + + if (offset < BLE_LL_MAFS) { + return -1; + } + + aux->sec_phy = phy; + aux->chan = chan; + aux->offset_unit = offset_unit; + + *offset_us = offset; + + return 0; +} + +int +ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_time, + uint8_t pdu_time_rem, uint32_t aux_ptr) +{ + uint32_t offset_us; + int rc; + + rc = ble_ll_scan_aux_parse_aux_ptr(aux, aux_ptr, &offset_us); + if (rc < 0) { + return -1; + } + + rc = ble_ll_sched_scan_aux(&aux->sch, pdu_time, pdu_time_rem, offset_us); + if (rc < 0) { + return -1; + } + + return 0; +} + +int +ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr) +{ + struct ble_ll_scan_aux_data *aux; + + if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) { + return -1; + } + + BLE_LL_ASSERT(aux_data_current); + aux = aux_data_current; + + /* + * Prepare TX transition when doing active scanning and receiving 1st PDU + * since we may want to send AUX_SCAN_REQ. + */ + if ((aux->scan_type == BLE_SCAN_TYPE_ACTIVE) && + !(aux->flags & BLE_LL_SCAN_AUX_F_AUX_ADV)) { + return 1; + } + + return 0; +} + +static int +ble_ll_scan_aux_parse_to_aux_data(struct ble_ll_scan_aux_data *aux, + uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) +{ + uint8_t pdu_hdr; + uint8_t pdu_len; + uint8_t adv_mode; + uint8_t eh_len; + uint8_t eh_flags; + uint8_t *eh_data; + + pdu_hdr = rxbuf[0]; + pdu_len = rxbuf[1]; + + /* PDU without at least Extended Header Length is invalid */ + if (pdu_len == 0) { + return -1; + } + + /* Mark as AUX received on 1st PDU, then as CHAIN received on subsequent */ + if (aux->flags & BLE_LL_SCAN_AUX_F_AUX_ADV) { + aux->flags |= BLE_LL_SCAN_AUX_F_AUX_CHAIN; + } else { + aux->flags |= BLE_LL_SCAN_AUX_F_AUX_ADV; + } + + adv_mode = rxbuf[2] >> 6; + eh_len = rxbuf[2] & 0x3f; + + /* Only AUX_CHAIN_IND is valid without Extended Header */ + if (eh_len == 0) { + if (!(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN) || adv_mode) { + return -1; + } + return 0; + } + + eh_flags = rxbuf[3]; + eh_data = &rxbuf[4]; + + /* Now parse extended header... */ + + /* AdvA is only valid in 1st PDU, ignore in AUX_CHAIN_IND */ + if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + if (!(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN)) { + memcpy(aux->adva, eh_data, 6); + aux->adva_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_MASK); + aux->flags |= BLE_LL_SCAN_AUX_F_HAS_ADVA; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + aux->rpa_index = ble_hw_resolv_list_match(); +#endif + } + eh_data += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + /* TargetA is only valid in 1st PDU, ignore in AUX_CHAIN_IND */ + if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + if (!(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN)) { + memcpy(aux->targeta, eh_data, 6); + aux->targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK); + aux->flags |= BLE_LL_SCAN_AUX_F_HAS_TARGETA; + } + eh_data += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + eh_data += BLE_LL_EXT_ADV_CTE_INFO_SIZE; + } + + /* + * ADI handling is a bit convoluted.... + * ADI is mandatory in ADV_EXT_IND with AuxPtr and is also mandatory in PDU + * if included in superior PDU. This implies that each AUX_CHAIN shall have + * ADI. However... AUX_SCAN_RSP does not need to have ADI, so if there's no + * ADI in AUX_SCAN_RSP we allow it and clear corresponding flag to skip ADI + * checks on subsequent PDUs. + */ + if (eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + if (aux->flags & BLE_LL_SCAN_AUX_F_HAS_ADI) { + if (get_le16(eh_data) != aux->adi) { + return -1; + } + } + eh_data += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } else if (aux->flags & BLE_LL_SCAN_AUX_F_HAS_ADI) { + if (rxhdr->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD) { + aux->flags &= ~BLE_LL_SCAN_AUX_F_HAS_ADI; + } else { + return -1; + } + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + aux->aux_ptr = get_le24(eh_data); + rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT; + } + + return 0; +} + +static int +ble_ll_scan_aux_ext_parse(uint8_t *rxbuf, struct ble_ll_scan_addr_data *addrd, + uint16_t *adi, uint32_t *aux_ptr) +{ + uint8_t pdu_hdr; + uint8_t pdu_len; + uint8_t adv_mode; + uint8_t eh_len; + uint8_t eh_flags; + uint8_t *eh_data; + + pdu_hdr = rxbuf[0]; + pdu_len = rxbuf[1]; + + if (pdu_len == 0) { + return -1; + } + + adv_mode = rxbuf[2] >> 6; + eh_len = rxbuf[2] & 0x3f; + + if ((adv_mode == 3) || (eh_len == 0)) { + return -1; + } + + eh_flags = rxbuf[3]; + eh_data = &rxbuf[4]; + + /* ADV_EXT_IND with AuxPtr but without ADI is invalid */ + if ((eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) && + !(eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT))) { + return -1; + } + + /* ADV_EXT_IND without either AdvA or AuxPtr is not valid */ + if (!(eh_flags & ((1 << BLE_LL_EXT_ADV_ADVA_BIT) | + (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)))) { + return -1; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + addrd->adva = eh_data; + addrd->adva_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_RAND); + eh_data += BLE_LL_EXT_ADV_ADVA_SIZE; + } else { + addrd->adva = NULL; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + addrd->targeta = eh_data; + addrd->targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_RAND); + eh_data += BLE_LL_EXT_ADV_TARGETA_SIZE; + } else { + addrd->targeta = NULL; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + eh_data += BLE_LL_EXT_ADV_CTE_INFO_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + *adi = get_le16(eh_data); + eh_data += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } else { + *adi = 0; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + *aux_ptr = get_le24(eh_data); + } else { + *aux_ptr = 0; + } + + return 0; +} + +static void +ble_ll_scan_aux_update_rxinfo_from_addrd(struct ble_ll_scan_addr_data *addrd, + struct ble_mbuf_hdr_rxinfo *rxinfo) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + rxinfo->rpa_index = addrd->rpa_index; + if (addrd->adva_resolved) { + rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; + } + if (addrd->targeta_resolved) { + rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED; + } +#endif +} + +static void +ble_ll_scan_aux_update_aux_data_from_addrd(struct ble_ll_scan_addr_data *addrd, + struct ble_ll_scan_aux_data *aux) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + aux->rpa_index = addrd->rpa_index; + if (addrd->adva_resolved) { + aux->flags |= BLE_LL_SCAN_AUX_F_RESOLVED_ADVA; + } + if (addrd->targeta_resolved) { + aux->flags |= BLE_LL_SCAN_AUX_F_RESOLVED_TARGETA; + } +#endif +} + +int +ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm, + struct os_mbuf *rxpdu) +{ + struct ble_mbuf_hdr *rxhdr = BLE_MBUF_HDR_PTR(rxpdu); + struct ble_mbuf_hdr_rxinfo *rxinfo = &rxhdr->rxinfo; + struct ble_ll_scan_addr_data addrd; + struct ble_ll_scan_aux_data *aux; + uint8_t *rxbuf; + uint32_t aux_ptr; + uint16_t adi; + bool do_match; + int rc; + + rxbuf = rxpdu->om_data; + + rc = ble_ll_scan_aux_ext_parse(rxbuf, &addrd, &adi, &aux_ptr); + if (rc < 0) { + return -1; + } + + /* We can filter based on ext PDU alone if both AdvA and TargetA are present + * or there's no AuxPtr. Otherwise, we need to wait for aux PDU to filter. + */ + do_match = !aux_ptr || (addrd.adva && addrd.targeta); + if (do_match) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + addrd.rpa_index = ble_hw_resolv_list_match(); +#endif + rc = ble_ll_scan_rx_filter(ble_ll_scan_get_own_addr_type(), + ble_ll_scan_get_filt_policy(), + &addrd, NULL); + if (rc < 0) { + return -1; + } + + if (!aux_ptr) { + /* We do not allocate aux_data for ADV_EXT_IND without AuxPtr so + * need to pass match data in rxinfo. + */ + ble_ll_scan_aux_update_rxinfo_from_addrd(&addrd, rxinfo); + } + } + + if (aux_ptr) { + aux = ble_ll_scan_aux_alloc(); + if (!aux) { + return -1; + } + + aux->scan_type = scansm->scanp->scan_type; + + aux->pri_phy = rxinfo->phy; + aux->aux_ptr = aux_ptr; + + if (addrd.adva) { + memcpy(aux->adva, addrd.adva, 6); + aux->adva_type = addrd.adva_type; + aux->flags |= BLE_LL_SCAN_AUX_F_HAS_ADVA; + } + + if (addrd.targeta) { + memcpy(aux->targeta, addrd.targeta, 6); + aux->targeta_type = addrd.targeta_type; + aux->flags |= BLE_LL_SCAN_AUX_F_HAS_TARGETA; + } + + aux->adi = adi; + aux->flags |= BLE_LL_SCAN_AUX_F_HAS_ADI; + + if (do_match) { + aux->flags |= BLE_LL_SCAN_AUX_F_MATCHED; + ble_ll_scan_aux_update_aux_data_from_addrd(&addrd, aux); + } else if (addrd.adva) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* If ext PDU has AdvA, we need to store rpa_index to be able to + * reuse it for filtering when done on aux PDU. + */ + aux->rpa_index = ble_hw_resolv_list_match(); +#endif + } + + rxinfo->user_data = aux; + } + + return 0; +} + +void +ble_ll_scan_aux_pkt_in_on_ext(struct os_mbuf *rxpdu, + struct ble_mbuf_hdr *rxhdr) +{ + struct ble_mbuf_hdr_rxinfo *rxinfo = &rxhdr->rxinfo; + struct ble_ll_scan_aux_data *aux = rxinfo->user_data; + int rc; + + if (rxinfo->flags & BLE_MBUF_HDR_F_IGNORED) { + BLE_LL_ASSERT(!aux); + return; + } + + if (!aux) { + ble_ll_hci_ev_send_ext_adv_report_for_ext(rxpdu, rxhdr); + return; + } + + BLE_LL_ASSERT(aux->aux_ptr); + + rc = ble_ll_scan_aux_sched(aux, rxhdr->beg_cputime, rxhdr->rem_usecs, + aux->aux_ptr); + if (rc < 0) { + ble_ll_scan_aux_free(aux); + } +} + +static uint8_t +ble_ll_scan_aux_scan_req_tx_pdu_cb(uint8_t *dptr, void *arg, uint8_t *hdr_byte) +{ + struct ble_ll_scan_aux_data *aux = arg; + uint8_t *scana; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_resolv_entry *rl; + uint8_t rpa[BLE_DEV_ADDR_LEN]; +#endif + uint8_t hb; + + hb = BLE_ADV_PDU_TYPE_SCAN_REQ; + + /* ScanA */ + if (ble_ll_scan_get_own_addr_type() & 0x01) { + hb |= BLE_ADV_PDU_HDR_TXADD_RAND; + scana = g_random_addr; + } else { + scana = g_dev_addr; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (ble_ll_scan_get_own_addr_type() & 0x02) { + if (aux->rpa_index >=0) { + rl = &g_ble_ll_resolv_list[aux->rpa_index]; + } else { + rl = NULL; + } + + /* + * If device is on RL and we have local IRK, we use RPA generated using + * that IRK as ScanA. Otherwise we use NRPA as ScanA to prevent our + * device from being tracked when doing an active scan + * ref: Core 5.2, Vol 6, Part B, section 6.3) + */ + if (rl && rl->rl_has_local) { + ble_ll_resolv_get_priv_addr(rl, 1, rpa); + scana = rpa; + } else { + scana = ble_ll_get_scan_nrpa(); + } + + hb |= BLE_ADV_PDU_HDR_TXADD_RAND; + } +#endif + memcpy(dptr, scana, BLE_DEV_ADDR_LEN); + + /* AdvA */ + if (aux->adva_type) { + hb |= BLE_ADV_PDU_HDR_RXADD_RAND; + } + memcpy(dptr + BLE_DEV_ADDR_LEN, aux->adva, BLE_DEV_ADDR_LEN); + + *hdr_byte = hb; + + return BLE_DEV_ADDR_LEN * 2; +} + +static bool +ble_ll_scan_aux_send_scan_req(struct ble_ll_scan_aux_data *aux, + struct ble_ll_scan_addr_data *addrd) +{ + int rc; + + /* Check if we already scanned this device successfully */ + if (ble_ll_scan_have_rxd_scan_rsp(addrd->adv_addr, addrd->adv_addr_type, + true, aux->adi)) { + return false; + } + + /* We want to send a request, see if backoff allows us */ + if (ble_ll_scan_backoff_kick() != 0) { + return false; + } + + /* TODO perhaps we should check if scan req+rsp won't overlap with scheduler + * item (old code did it), but for now let's just scan and we will be + * interrupted if scheduler kicks in. + */ + + rc = ble_phy_tx(ble_ll_scan_aux_scan_req_tx_pdu_cb, aux, + BLE_PHY_TRANSITION_TX_RX); + if (rc) { + return false; + } + + return true; +} + +int +ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) +{ + struct ble_ll_scan_addr_data addrd; + struct ble_mbuf_hdr_rxinfo *rxinfo; + struct ble_ll_scan_aux_data *aux; + struct ble_mbuf_hdr *rxhdr; + uint8_t scan_ok; + uint8_t adv_mode; + uint8_t *rxbuf; + int rc; + + BLE_LL_ASSERT(aux_data_current); + aux = aux_data_current; + aux_data_current = NULL; + + if (rxpdu == NULL) { + ble_ll_scan_aux_break(aux); + goto done; + } + + rxhdr = BLE_MBUF_HDR_PTR(rxpdu); + rxinfo = &rxhdr->rxinfo; + rxinfo->user_data = aux; + + if (!crcok) { + rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; + goto done; + } + + rxbuf = rxpdu->om_data; + + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_SCAN_RSP) { + aux->flags &= ~BLE_LL_SCAN_AUX_F_W4_SCAN_RSP; + aux->flags |= BLE_LL_SCAN_AUX_F_SCANNED; + rxinfo->flags |= BLE_MBUF_HDR_F_SCAN_RSP_RXD; + } + + rc = ble_ll_scan_aux_parse_to_aux_data(aux, rxbuf, rxhdr); + if (rc < 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; + goto done; + } + + if (aux->flags & BLE_LL_SCAN_AUX_F_MATCHED) { + goto done; + } + + /* We do filtering on either ADV_EXT_IND or AUX_ADV_IND so we should not be + * here when processing AUX_CHAIN_IND. + */ + BLE_LL_ASSERT(!(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN)); + + if (aux->flags & BLE_LL_SCAN_AUX_F_HAS_ADVA) { + addrd.adva = aux->adva; + addrd.adva_type = aux->adva_type; + } else { + addrd.adva = NULL; + } + + if (aux->flags & BLE_LL_SCAN_AUX_F_HAS_TARGETA) { + addrd.targeta = aux->targeta; + addrd.targeta_type = aux->targeta_type; + } else { + addrd.targeta = NULL; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + addrd.rpa_index = aux->rpa_index; +#endif + + rc = ble_ll_scan_rx_filter(ble_ll_scan_get_own_addr_type(), + ble_ll_scan_get_filt_policy(), + &addrd, &scan_ok); + if (rc < 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; + /* + * XXX hack warning + * Even if PDU was not allowed by current scan filter policy, we should + * still allow it to sync if SyncInfo is present. Since we do not use + * F_DEVMATCH in aux code for its intended purpose, let's use it here to + * indicate no match due to scan filter policy. + */ + if (rc == -2) { + rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; + } + goto done; + } + + aux->flags |= BLE_LL_SCAN_AUX_F_MATCHED; + + ble_ll_scan_aux_update_aux_data_from_addrd(&addrd, aux); + + adv_mode = rxbuf[2] >> 6; + + if ((aux->scan_type == BLE_SCAN_TYPE_ACTIVE) && + (adv_mode == BLE_LL_EXT_ADV_MODE_SCAN) && scan_ok) { + if (ble_ll_scan_aux_send_scan_req(aux, &addrd)) { + /* AUX_SCAN_REQ sent, keep PHY enabled to continue */ + aux->flags |= BLE_LL_SCAN_AUX_F_W4_SCAN_RSP; + rxinfo->flags |= BLE_MBUF_HDR_F_SCAN_REQ_TXD; + aux_data_current = aux; + return 0; + } + } + +done: + /* We are done with this PDU so go to standby and let LL resume if needed */ + ble_ll_state_set(BLE_LL_STATE_STANDBY); + return -1; +} + +static void +ble_ll_scan_aux_init_addrd_from_aux_data(struct ble_ll_scan_aux_data *aux, + struct ble_ll_scan_addr_data *addrd) +{ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_resolv_entry *rl; +#endif + + if (aux->flags & BLE_LL_SCAN_AUX_F_HAS_ADVA) { + addrd->adva = aux->adva; + addrd->adva_type = aux->adva_type; + } else { + addrd->adva = NULL; + addrd->adva_type = 0; + } + + if (aux->flags & BLE_LL_SCAN_AUX_F_HAS_TARGETA) { + addrd->targeta = aux->targeta; + addrd->targeta_type = aux->targeta_type; + } else { + addrd->targeta = NULL; + addrd->targeta_type = 0; + } + + addrd->adv_addr = addrd->adva; + addrd->adv_addr_type = addrd->adva_type; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + addrd->rpa_index = aux->rpa_index; + + if (aux->flags & BLE_LL_SCAN_AUX_F_RESOLVED_ADVA) { + BLE_LL_ASSERT(aux->rpa_index >= 0); + rl = &g_ble_ll_resolv_list[aux->rpa_index]; + addrd->adv_addr = rl->rl_identity_addr; + addrd->adv_addr_type = rl->rl_addr_type; + addrd->adva_resolved = 1; + } else { + addrd->adva_resolved = 0; + } + + if (aux->flags & BLE_LL_SCAN_AUX_F_RESOLVED_TARGETA) { + addrd->targeta = ble_ll_scan_aux_get_own_addr(); + addrd->targeta_type = ble_ll_scan_get_own_addr_type() & 1; + addrd->targeta_resolved = 1; + } else { + addrd->targeta_resolved = 0; + } +#endif +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +static void +ble_ll_scan_aux_sync_check(struct os_mbuf *rxpdu, + struct ble_ll_scan_addr_data *addrd) +{ + struct ble_mbuf_hdr *rxhdr = BLE_MBUF_HDR_PTR(rxpdu); + uint8_t *rxbuf = rxpdu->om_data; + uint8_t adv_mode; + uint8_t eh_len; + uint8_t eh_flags; + uint8_t *eh_data; + uint8_t sid; + + adv_mode = rxbuf[2] >> 6; + + if (adv_mode != BLE_LL_EXT_ADV_MODE_NON_CONN) { + return; + } + + eh_len = rxbuf[2] & 0x3f; + + if (eh_len == 0) { + return; + } + + eh_flags = rxbuf[3]; + eh_data = &rxbuf[4]; + + /* Need ADI and SyncInfo */ + if (!(eh_flags & ((1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT) | + (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)))) { + return; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + eh_data += BLE_LL_EXT_ADV_ADVA_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + eh_data += BLE_LL_EXT_ADV_TARGETA_SIZE; + } + + if (eh_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { + eh_data += 1; + } + + sid = get_le16(eh_data) >> 12; + eh_data += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + + if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + eh_data += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + } + + ble_ll_sync_info_event(addrd, sid, rxhdr, eh_data); +} +#endif + +void +ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr) +{ + struct ble_ll_scan_addr_data addrd; + struct ble_mbuf_hdr_rxinfo *rxinfo; + struct ble_ll_scan_aux_data *aux; + bool scan_duplicate = false; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + bool sync_check = false; +#endif + int rc; + + rxinfo = &rxhdr->rxinfo; + aux = rxinfo->user_data; + + BLE_LL_ASSERT(aux); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + sync_check = ble_ll_sync_enabled() && + !(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN); + + /* PDU was not allowed due to scan filter policy, but we can still try to + * sync since separate filter policy is used for this purpose. + */ + if ((rxinfo->flags & BLE_MBUF_HDR_F_DEVMATCH) && sync_check) { + ble_ll_scan_aux_init_addrd_from_aux_data(aux, &addrd); + ble_ll_scan_aux_sync_check(rxpdu, &addrd); + } +#endif + + if (rxinfo->flags & BLE_MBUF_HDR_F_IGNORED) { + if (ble_ll_scan_aux_need_truncation(aux)) { + ble_ll_hci_ev_send_ext_adv_truncated_report(aux); + } else { + aux->hci_state |= BLE_LL_SCAN_AUX_H_DONE; + } + + ble_ll_scan_aux_update_scan_backoff(aux); + } + + if (aux->hci_state & BLE_LL_SCAN_AUX_H_DONE) { + ble_ll_scan_aux_free(aux); + ble_ll_scan_chk_resume(); + return; + } + + /* Try to schedule scan for subsequent aux asap, if needed */ + if (rxinfo->flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT) { + rc = ble_ll_scan_aux_sched(aux, rxhdr->beg_cputime, rxhdr->rem_usecs, + aux->aux_ptr); + if (rc < 0) { + rxinfo->flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT; + } + } + + ble_ll_scan_aux_init_addrd_from_aux_data(aux, &addrd); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + if (sync_check) { + ble_ll_scan_aux_sync_check(rxpdu, &addrd); + } +#endif + + scan_duplicate = ble_ll_scan_get_filt_dups() && + ble_ll_scan_dup_check_ext(addrd.adv_addr_type, + addrd.adv_addr, true, aux->adi); + if (!scan_duplicate) { + rc = ble_ll_hci_ev_send_ext_adv_report_for_aux(rxpdu, rxhdr, aux, + &addrd); + + /* + * Update duplicates list if report was sent successfully and we are + * done with this chain. On error, status is already set to 'done' so + * we will cancel aux scan (if any) and stop further processing. + * However, if we send AUX_SCAN_REQ for this PDU then need to remove + * 'done' as we should continue with scanning after AUX_SCAN_RSP. + */ + + if (rc == 0) { + if (rxinfo->flags & BLE_MBUF_HDR_F_SCAN_REQ_TXD) { + aux->hci_state &= ~BLE_LL_SCAN_AUX_H_DONE; + } else if (aux->hci_state & BLE_LL_SCAN_AUX_H_DONE) { + BLE_LL_ASSERT(!(rxinfo->flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT)); + if (ble_ll_scan_get_filt_dups()) { + ble_ll_scan_dup_update_ext(addrd.adv_addr_type, + addrd.adv_addr, true, aux->adi); + } + if (aux->flags & BLE_LL_SCAN_AUX_F_SCANNED) { + ble_ll_scan_add_scan_rsp_adv(addrd.adv_addr, + addrd.adv_addr_type, + 1, aux->adi); + } + } + } + } else { + /* This is a duplicate, we don't want to scan it anymore */ + aux->hci_state |= BLE_LL_SCAN_AUX_H_DONE; + } + + /* + * If we are done processing this chain and aux scan was not scheduled or + * we removed it from scheduler, we can remove aux_data now. Otherwise we + * will remove on next pkt_in. + */ + if ((aux->hci_state & BLE_LL_SCAN_AUX_H_DONE) && + (!(rxinfo->flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT) || + (ble_ll_sched_rmv_elem(&aux->sch) == 0))) { + ble_ll_scan_aux_update_scan_backoff(aux); + ble_ll_scan_aux_free(aux); + } + + ble_ll_scan_chk_resume(); +} + +void +ble_ll_scan_aux_wfr_timer_exp(void) +{ + ble_phy_disable(); + ble_ll_scan_aux_halt(); +} + +void +ble_ll_scan_aux_halt(void) +{ + struct ble_ll_scan_aux_data *aux = aux_data_current; + + BLE_LL_ASSERT(aux); + + aux_data_current = NULL; + + ble_ll_state_set(BLE_LL_STATE_STANDBY); + + ble_ll_scan_aux_break(aux); +} + +void +ble_ll_scan_aux_sched_remove(struct ble_ll_sched_item *sch) +{ + ble_ll_scan_aux_break(sch->cb_arg); +} + +void +ble_ll_scan_aux_init(void) +{ + os_error_t err; + + err = os_mempool_init(&aux_data_pool, + MYNEWT_VAL(BLE_LL_SCAN_AUX_SEGMENT_CNT), + sizeof(struct ble_ll_scan_aux_data), + aux_data_mem, "ble_ll_scan_aux_data_pool"); + BLE_LL_ASSERT(err == 0); +} + +#endif /* BLE_LL_CFG_FEAT_LL_EXT_ADV */ \ No newline at end of file diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index d01f10edab..c41ad3fef6 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -28,6 +28,7 @@ #include "controller/ble_ll_sched.h" #include "controller/ble_ll_adv.h" #include "controller/ble_ll_scan.h" +#include "controller/ble_ll_scan_aux.h" #include "controller/ble_ll_rfmgmt.h" #include "controller/ble_ll_trace.h" #include "controller/ble_ll_sync.h" @@ -244,6 +245,9 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) ble_ll_adv_event_rmvd_from_sched((struct ble_ll_adv_sm *)entry->cb_arg); break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_LL_SCHED_TYPE_SCAN_AUX: + ble_ll_scan_aux_break(entry->cb_arg); + break; case BLE_LL_SCHED_TYPE_AUX_SCAN: ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)entry->cb_arg); break; @@ -1463,6 +1467,11 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) } else if (lls == BLE_LL_STATE_SYNC) { STATS_INC(ble_ll_stats, sched_state_sync_errs); ble_ll_sync_halt(); +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + } else if (lls == BLE_LL_STATE_SCAN_AUX) { + ble_ll_state_set(BLE_LL_STATE_STANDBY); + ble_ll_scan_aux_halt(); #endif } else { STATS_INC(ble_ll_stats, sched_state_conn_errs); @@ -1714,6 +1723,65 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, return rc; } + +int +ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, + uint8_t pdu_time_rem, uint32_t offset_us) +{ + struct ble_ll_sched_item *entry; + uint32_t offset_ticks; + os_sr_t sr; + int rc; + + offset_us += pdu_time_rem; + offset_ticks = os_cputime_usecs_to_ticks(offset_us); + + sch->start_time = pdu_time + offset_ticks - g_ble_ll_sched_offset_ticks; + sch->remainder = offset_us - os_cputime_ticks_to_usecs(offset_ticks); + /* TODO: make some sane slot reservation */ + sch->end_time = sch->start_time + os_cputime_usecs_to_ticks(5000); + + OS_ENTER_CRITICAL(sr); + + if (!ble_ll_sched_insert_if_empty(sch)) { + /* Scheduler was empty, inserted as 1st element */ + rc = 0; + goto done; + } + + os_cputime_timer_stop(&g_ble_ll_sched_timer); + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { + TAILQ_INSERT_BEFORE(entry, sch, link); + sch->enqueued = 1; + rc = 0; + break; + } + + if (ble_ll_sched_is_overlap(sch, entry)) { + rc = -1; + break; + } + } + + if (!entry) { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 1; + rc = 0; + } + +done: + entry = TAILQ_FIRST(&g_ble_ll_sched_q); + + OS_EXIT_CRITICAL(sr); + + if (entry == sch) { + ble_ll_rfmgmt_sched_changed(sch); + } + os_cputime_timer_start(&g_ble_ll_sched_timer, entry->start_time); + + return rc; +} #endif #if MYNEWT_VAL(BLE_LL_DTM) diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c index 7c46d10a29..cdffc4bf18 100644 --- a/nimble/controller/src/ble_ll_sync.c +++ b/nimble/controller/src/ble_ll_sync.c @@ -1333,14 +1333,11 @@ ble_ll_sync_event_end(struct ble_npl_event *ev) } void -ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, int rpa_index, +ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd, uint8_t sid, struct ble_mbuf_hdr *rxhdr, const uint8_t *syncinfo) { struct ble_ll_sync_sm *sm = NULL; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - const uint8_t *rpa = NULL; -#endif uint16_t max_skip; uint32_t offset; uint32_t usecs; @@ -1365,28 +1362,21 @@ ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, int rpa_index, return; } - /* check if resolved */ - if (rpa_index >= 0) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - rpa = addr; -#endif - addr = g_ble_ll_resolv_list[rpa_index].rl_identity_addr; - addr_type = g_ble_ll_resolv_list[rpa_index].rl_addr_type; - } - /* check peer */ if (g_ble_ll_sync_create_params.options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) { - if (ble_ll_sync_on_list(addr, addr_type, sid) < 0) { + if (ble_ll_sync_on_list(addrd->adv_addr, + addrd->adv_addr_type, sid) < 0) { return; } /* set addr and sid in sm */ sm->adv_sid = sid; - sm->adv_addr_type = addr_type; - memcpy(sm->adv_addr, addr, BLE_DEV_ADDR_LEN); + sm->adv_addr_type = addrd->adv_addr_type; + memcpy(sm->adv_addr, addrd->adv_addr, BLE_DEV_ADDR_LEN); } else { - if ((sm->adv_sid != sid) || (sm->adv_addr_type != addr_type) || - memcmp(sm->adv_addr, addr, BLE_DEV_ADDR_LEN)) { + if ((sm->adv_sid != sid) || + (sm->adv_addr_type != addrd->adv_addr_type) || + memcmp(sm->adv_addr, addrd->adv_addr, BLE_DEV_ADDR_LEN)) { return; } } @@ -1406,12 +1396,14 @@ ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, int rpa_index, return; } - if (rpa_index >= 0) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (addrd->adva_resolved) { sm->flags |= BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - memcpy(sm->adv_addr_rpa, rpa, BLE_DEV_ADDR_LEN); + memcpy(sm->adv_addr_rpa, addrd->adva, BLE_DEV_ADDR_LEN); #endif } +#endif /* set params from HCI LE Create Periodic Sync */ sm->timeout = g_ble_ll_sync_create_params.timeout; diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index b900ba9106..ea5590f8e4 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -291,6 +291,12 @@ syscfg.defs: restrictions: - 'BLE_LL_CFG_FEAT_LL_ISO if 1' + BLE_LL_SCAN_AUX_SEGMENT_CNT: + description: > + Number of auxiliary advertising segments that can be scanned + concurrently (Core 5.2, Vol 6, Part B, 4.4.2.2.2). + value: 8 + BLE_LL_EXT_ADV_AUX_PTR_CNT: description: > This option configure a max number of scheduled outstanding auxiliary From 08e69722d9b427c05400f4cb0483a02a0e63ce20 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 29 Sep 2021 23:44:37 +0200 Subject: [PATCH 081/306] nimble/ll: Fix TX time restrictions during phy transition We do not need to restrict TX time after sending LL_PHY_REQ as a master, this only applies to slave. This makes LL/CON/CEN/BV-53-C pass instead of being inconclusive due to data fragmentation done by IUT between LL_PHY_REQ and LL_PHU_UPDATE_IND. Ref: Core 5.x, Vol. 6, Part B, section 5.1.10.1 --- nimble/controller/src/ble_ll_ctrl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c index c4ac6504c9..384a48756e 100644 --- a/nimble/controller/src/ble_ll_ctrl.c +++ b/nimble/controller/src/ble_ll_ctrl.c @@ -2858,8 +2858,11 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) #endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) case BLE_LL_CTRL_PHY_REQ: - connsm->phy_tx_transition = - ble_ll_ctrl_phy_tx_transition_get(connsm->phy_data.req_pref_tx_phys_mask); + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + connsm->phy_tx_transition = + ble_ll_ctrl_phy_tx_transition_get( + connsm->phy_data.req_pref_tx_phys_mask); + } break; case BLE_LL_CTRL_PHY_UPDATE_IND: connsm->phy_tx_transition = From 17f985ff00900fed845f9f6aaa9b2dfb93a704af Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 30 Sep 2021 14:22:19 +0200 Subject: [PATCH 082/306] porting: Fix typo in linux blemesh sample --- porting/examples/linux_blemesh/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/porting/examples/linux_blemesh/Makefile b/porting/examples/linux_blemesh/Makefile index 556fc8ca6c..c1518e0e4d 100644 --- a/porting/examples/linux_blemesh/Makefile +++ b/porting/examples/linux_blemesh/Makefile @@ -17,7 +17,7 @@ # Toolchain commands CROSS_COMPILE ?= -CC := ccache $(CROSS_COMPILIE)gcc +CC := ccache $(CROSS_COMPILE)gcc CXX := ccache $(CROSS_COMPILE)g++ LD := $(CROSS_COMPILE)gcc AR := $(CROSS_COMPILE)ar From 93368f517fa12cede5eaaaab99e53210377bfa5f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 3 Oct 2021 01:20:44 +0200 Subject: [PATCH 083/306] travis.yml: Bump Go to 1.16 This is required for updated install script to work properly. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 285b81e5d0..0b59e7a862 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ _addons: &addon_conf - gcc-7-multilib go: - - "1.12" + - "1.16" git: depth: false From aa14cf801ae36d22ca5889541bc2149a347700b6 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 29 Sep 2021 21:24:21 +0200 Subject: [PATCH 084/306] nimble/ll: Fix handling of removing adv item from scheduler If adv item is removed from scheduler we should drop event instead of just sending done event. Sending done event instead can cause issues on extended advertising instances if we remove aux items since it does not clear aux_active flag. As a result, when done even is handled and we reached max_events, HCI event will not be sent since it waits for done event for secondary channel but that one won't cone since aux items are already removed. --- nimble/controller/src/ble_ll_adv.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 6ab6b24331..7efe914240 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -206,6 +206,8 @@ struct ble_ll_adv_sm struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_ADV_INSTANCES]; struct ble_ll_adv_sm *g_ble_ll_cur_adv_sm; +static void ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm); + static struct ble_ll_adv_sm * ble_ll_adv_sm_find_configured(uint8_t instance) { @@ -1049,12 +1051,7 @@ ble_ll_adv_tx_done(void *arg) void ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm) { - /* - * Need to set advertising channel to final chan so new event gets - * scheduled. - */ - advsm->adv_chan = ble_ll_adv_final_chan(advsm); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + ble_ll_adv_drop_event(advsm); } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) From 74e121759876df954ea1dce73d27e0eb65ff822e Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 30 Sep 2021 23:24:24 +0200 Subject: [PATCH 085/306] nimble/ll: Fix build with past and without privacy --- nimble/controller/src/ble_ll_sync.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c index cdffc4bf18..78d9456f64 100644 --- a/nimble/controller/src/ble_ll_sync.c +++ b/nimble/controller/src/ble_ll_sync.c @@ -1922,6 +1922,7 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, rpa_index = -1; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) /* check if need to resolve */ if (ble_ll_is_rpa(addr, addr_type)) { rpa_index = ble_ll_resolv_peer_rpa_any(addr); @@ -1931,6 +1932,7 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, addr_type = g_ble_ll_resolv_list[rpa_index].rl_addr_type; } } +#endif OS_ENTER_CRITICAL(sr); /* check if already synchronized with this peer */ From 94039bc18e4173f5e058483d763c23aaea147853 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 27 Sep 2021 23:20:25 +0200 Subject: [PATCH 086/306] nimble/ll: Remove unused code Not used anymore. --- .../include/controller/ble_ll_sched.h | 2 - nimble/controller/src/ble_ll_sched.c | 47 ------------------- 2 files changed, 49 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h index 96834bb075..bed864029f 100644 --- a/nimble/controller/include/controller/ble_ll_sched.h +++ b/nimble/controller/include/controller/ble_ll_sched.h @@ -200,8 +200,6 @@ int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, struct ble_ll_scan_sm *scansm, struct ble_ll_aux_data *aux_scan); -int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode); - int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, uint8_t pdu_time_rem, uint32_t offset_us); #endif diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index c41ad3fef6..b0fc4f5c42 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -1562,53 +1562,6 @@ ble_ll_sched_next_time(uint32_t *next_event_time) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/** - * Called to check if there is place for a planned scan req. - * - * @param chan - * @param phy_mode - * - * @return int 0: Clear for scan req 1: there is an upcoming event - */ -int -ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode) -{ - struct ble_ll_sched_item *sch; - uint32_t usec_dur; - uint32_t now = os_cputime_get32(); - - /* Lets calculate roughly how much time we need for scan req and scan rsp */ - usec_dur = ble_ll_pdu_tx_time_get(BLE_SCAN_REQ_LEN, phy_mode); - if (chan >= BLE_PHY_NUM_DATA_CHANS) { - usec_dur += ble_ll_pdu_tx_time_get(BLE_SCAN_RSP_MAX_LEN, phy_mode); - } else { - usec_dur += ble_ll_pdu_tx_time_get(BLE_SCAN_RSP_MAX_EXT_LEN, phy_mode); - } - - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - while (sch) { - /* Let's check if there is no scheduled item which want to start within - * given usecs.*/ - if (CPUTIME_GT(sch->start_time, now + os_cputime_usecs_to_ticks(usec_dur))) { - /* We are fine. Have time for scan req */ - return 0; - } - - /* There is something in the scheduler. If it is not aux ptr we assume - * it is more important that scan req - */ - if (sch->sched_type != BLE_LL_SCHED_TYPE_AUX_SCAN) { - return 1; - } - - ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)sch->cb_arg); - TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 0; - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - } - return 0; -} - /** * Called to schedule a aux scan. * From c0ef83b072542da7a47f53dc6af20bd108843281 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 30 Sep 2021 23:14:14 +0200 Subject: [PATCH 087/306] nimble/ll: Add clarification comment Just clarify why we should return here instead of 'break'. --- nimble/controller/src/ble_ll_scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index cf264b0ab0..399ce22580 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2133,6 +2133,9 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; } ble_ll_state_set(BLE_LL_STATE_STANDBY); + /* Return here, we do not want any further processing since it's all + * handled in scan_aux. + */ return -1; #endif default: From cddb7c4ccee72e718c8b1a57166e702917e02c13 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 30 Sep 2021 20:39:09 +0200 Subject: [PATCH 088/306] nimble/ll: Fix phy configuration for initiator Not sure how this even works, but configuration flags for phys were never set... --- nimble/controller/src/ble_ll_scan.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 399ce22580..660abf9023 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2986,6 +2986,12 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc, scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl); scanp->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window); scanp->scan_type = BLE_SCAN_TYPE_INITIATE; + scanp->configured = 1; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + scanp = &scansm->scan_phys[PHY_CODED]; + scanp->configured = 0; +#endif rc = ble_ll_scan_sm_start(scansm); if (sm == NULL) { @@ -3019,20 +3025,23 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, scansm->scanp_next = NULL; scansm->ext_scanning = 1; + params = &hcc->params[0]; + scanp_uncoded = &scansm->scan_phys[PHY_UNCODED]; if (hcc->init_phy_mask & BLE_PHY_MASK_1M) { - params = &hcc->params[0]; - scanp_uncoded = &scansm->scan_phys[PHY_UNCODED]; - + scanp_uncoded->configured = 1; scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); scanp_uncoded->scan_type = BLE_SCAN_TYPE_INITIATE; scansm->scanp = scanp_uncoded; + } else { + scanp_uncoded->configured = 0; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + params = &hcc->params[2]; + scanp_coded = &scansm->scan_phys[PHY_CODED]; if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) { - params = &hcc->params[2]; - scanp_coded = &scansm->scan_phys[PHY_CODED]; - + scanp_coded->configured = 1; scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); scanp_coded->scan_type = BLE_SCAN_TYPE_INITIATE; @@ -3041,7 +3050,12 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, } else { scansm->scanp = scanp_coded; } + } else { + scanp_coded->configured = 0; } +#else + scanp_coded = NULL; +#endif /* if any of PHYs is configured for continuous scan we alter interval to * fit other PHY From 6c9f70972e8c68efe1fd38d413778c9487c5d997 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 6 Oct 2021 17:33:02 +0200 Subject: [PATCH 089/306] nimble/ll: Fix scanning with LL Privacy disabled This is regression after eed4389851fcf96922a2e429376808f2dfddc912. Without this fix only SCAN_RSP are reported back to host... --- nimble/controller/src/ble_ll_scan.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 660abf9023..9b123622cb 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -1939,9 +1939,7 @@ ble_ll_scan_rx_isr_on_adv(uint8_t pdu_type, uint8_t *rxbuf, { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; struct ble_ll_scan_phy *scanp = scansm->scanp; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; -#endif uint8_t scan_ok; int rc; @@ -1957,8 +1955,8 @@ ble_ll_scan_rx_isr_on_adv(uint8_t pdu_type, uint8_t *rxbuf, return 0; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) rxinfo->rpa_index = addrd->rpa_index; if (addrd->adva_resolved) { rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED; From 6c9f95ad23c5ed8703ee7e35107a246b3e287dcd Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 5 Oct 2021 17:17:39 +0200 Subject: [PATCH 090/306] nimble/ll: Optimize AUX_CONNECT_REQ tx Currently we initialize a lot of connsm settings prior to scheduling 1st connection event and this takes some time. However, we only need connection interval, latency and supervision timeout to be initialized in order to schedule event properly and send AUX_CONNECT_REQ, other stuff can be done after tx has already started. This is especially important on slower MCU like CMAC as with old code it was barely possible to make tx within Tifs even on speed build. New code saves ~15us on CMAC prior to tx so we have quite a good margin to complete on time. --- .../include/controller/ble_ll_conn.h | 5 +- nimble/controller/src/ble_ll_conn.c | 38 +++++++------ nimble/controller/src/ble_ll_conn_hci.c | 54 ++++++++++++++----- 3 files changed, 66 insertions(+), 31 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h index d7db6878a1..daf7db5848 100644 --- a/nimble/controller/include/controller/ble_ll_conn.h +++ b/nimble/controller/include/controller/ble_ll_conn.h @@ -192,8 +192,9 @@ struct hci_ext_conn_params { uint16_t scan_itvl; uint16_t scan_window; - uint16_t conn_itvl_min; - uint16_t conn_itvl_max; + uint32_t conn_itvl; + uint16_t conn_itvl_ticks; + uint8_t conn_itvl_usecs; uint16_t conn_latency; uint16_t supervision_timeout; uint16_t min_ce_len; diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index af610b50ba..53303789b9 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -1755,14 +1755,6 @@ void ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, struct hci_ext_conn_params *hcc_params, int phy) { - /* Set slave latency and supervision timeout */ - connsm->slave_latency = hcc_params->conn_latency; - connsm->supervision_tmo = hcc_params->supervision_timeout; - - /* XXX: for now, just make connection interval equal to max */ - connsm->conn_itvl = hcc_params->conn_itvl_max; - - /* Check the min/max CE lengths are less than connection interval */ if (hcc_params->min_ce_len > (connsm->conn_itvl * 2)) { connsm->min_ce_len = connsm->conn_itvl * 2; @@ -1776,8 +1768,6 @@ ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, connsm->max_ce_len = hcc_params->max_ce_len; } - ble_ll_conn_calc_itvl_ticks(connsm); - #if (BLE_LL_BT5_PHY_SUPPORTED == 1) ble_ll_conn_init_phy(connsm, phy); #endif @@ -3176,6 +3166,7 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, struct ble_ll_resolv_entry *rl; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct hci_ext_conn_params *hcp; struct ble_ll_scan_sm *scansm; uint8_t phy; #endif @@ -3425,15 +3416,16 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, } if (connsm->scansm->ext_scanning) { - phy = ble_hdr->rxinfo.phy; + phy = ble_hdr->rxinfo.phy; - /* Update connection state machine with appropriate parameters for - * certain PHY - */ - ble_ll_conn_ext_set_params(connsm, - &connsm->initial_params.params[phy - 1], - phy); + hcp = &connsm->initial_params.params[phy - 1]; + connsm->slave_latency = hcp->conn_latency; + connsm->supervision_tmo = hcp->supervision_timeout; + + connsm->conn_itvl = hcp->conn_itvl; + connsm->conn_itvl_ticks = hcp->conn_itvl_ticks; + connsm->conn_itvl_usecs = hcp->conn_itvl_usecs; } #endif @@ -3472,6 +3464,18 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, ble_hdr->rxinfo.user_data = NULL; STATS_INC(ble_ll_stats, aux_conn_req_tx); } + + if (connsm->scansm->ext_scanning) { + phy = ble_hdr->rxinfo.phy; + + /* Update connection state machine with appropriate parameters for + * certain PHY + */ + ble_ll_conn_ext_set_params(connsm, + &connsm->initial_params.params[phy - 1], + phy); + + } #endif STATS_INC(ble_ll_conn_stats, conn_req_txd); diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index 9936b9d34e..aa6de540ba 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -556,6 +556,25 @@ ble_ll_conn_hcc_params_set_fallback(struct hci_ext_create_conn *hcc, #endif } +static void +ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint16_t *itvl_ticks, + uint8_t *itvl_usecs) +{ + uint32_t ticks; + uint32_t usecs; + + usecs = itvl * BLE_LL_CONN_ITVL_USECS; + ticks = os_cputime_usecs_to_ticks(usecs); + usecs = usecs - os_cputime_ticks_to_usecs(ticks); + if (usecs == 31) { + usecs = 0; + ++ticks; + } + + *itvl_ticks = ticks; + *itvl_usecs = usecs; +} + int ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) { @@ -564,6 +583,8 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) const struct hci_ext_conn_params *fallback_params = NULL; struct hci_ext_create_conn hcc = { 0 }; struct ble_ll_conn_sm *connsm; + uint16_t conn_itvl_min; + uint16_t conn_itvl_max; int rc; /* validate length */ @@ -629,13 +650,12 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) return rc; } - hcc.params[0].conn_itvl_min = le16toh(params->conn_min_itvl); - hcc.params[0].conn_itvl_max = le16toh(params->conn_min_itvl); + conn_itvl_min = le16toh(params->conn_min_itvl); + conn_itvl_max = le16toh(params->conn_max_itvl); hcc.params[0].conn_latency = le16toh(params->conn_latency); hcc.params[0].supervision_timeout = le16toh(params->supervision_timeout); - rc = ble_ll_conn_hci_chk_conn_params(hcc.params[0].conn_itvl_min, - hcc.params[0].conn_itvl_max, + rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max, hcc.params[0].conn_latency, hcc.params[0].supervision_timeout); if (rc) { @@ -649,6 +669,10 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } + hcc.params[0].conn_itvl = conn_itvl_max; + ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[0].conn_itvl_ticks, + &hcc.params[0].conn_itvl_usecs); + fallback_params = &hcc.params[0]; params++; } @@ -660,13 +684,12 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) } len -= sizeof(*params); - hcc.params[1].conn_itvl_min = le16toh(params->conn_min_itvl); - hcc.params[1].conn_itvl_max = le16toh(params->conn_min_itvl); + conn_itvl_min = le16toh(params->conn_min_itvl); + conn_itvl_max = le16toh(params->conn_max_itvl); hcc.params[1].conn_latency = le16toh(params->conn_latency); hcc.params[1].supervision_timeout = le16toh(params->supervision_timeout); - rc = ble_ll_conn_hci_chk_conn_params(hcc.params[1].conn_itvl_min, - hcc.params[1].conn_itvl_max, + rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max, hcc.params[1].conn_latency, hcc.params[1].supervision_timeout); if (rc) { @@ -680,6 +703,10 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } + hcc.params[1].conn_itvl = conn_itvl_max; + ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[1].conn_itvl_ticks, + &hcc.params[1].conn_itvl_usecs); + params++; } #endif @@ -700,13 +727,12 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) return rc; } - hcc.params[2].conn_itvl_min = le16toh(params->conn_min_itvl); - hcc.params[2].conn_itvl_max = le16toh(params->conn_min_itvl); + conn_itvl_min = le16toh(params->conn_min_itvl); + conn_itvl_max = le16toh(params->conn_max_itvl); hcc.params[2].conn_latency = le16toh(params->conn_latency); hcc.params[2].supervision_timeout = le16toh(params->supervision_timeout); - rc = ble_ll_conn_hci_chk_conn_params(hcc.params[2].conn_itvl_min, - hcc.params[2].conn_itvl_max, + rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max, hcc.params[2].conn_latency, hcc.params[2].supervision_timeout); if (rc) { @@ -720,6 +746,10 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } + hcc.params[2].conn_itvl = conn_itvl_max; + ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[2].conn_itvl_ticks, + &hcc.params[2].conn_itvl_usecs); + if (!fallback_params) { fallback_params = &hcc.params[2]; } From a892c8f78952907c88b9ff714a446a73348cef5c Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 5 Oct 2021 17:21:39 +0200 Subject: [PATCH 091/306] nimble/ll: Allow 2M params as fallback for ext conn create We ignore 2M values only for scanning since we do not scan on 2M when ext conn create is pending, but there's nothing wrong in using those parameters as fallback in case we established connection on phy that was not in phy mask. --- nimble/controller/src/ble_ll_conn_hci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index aa6de540ba..fe384c4147 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -707,6 +707,9 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[1].conn_itvl_ticks, &hcc.params[1].conn_itvl_usecs); + if (!fallback_params) { + fallback_params = &hcc.params[1]; + } params++; } #endif From 4ed4f9e3814b617f800094f74f8c01306f95f6a5 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 4 Oct 2021 10:09:14 +0200 Subject: [PATCH 092/306] mesh: Fix linux port It looks like create_free_list() in glue.c requires word aligned blocks which on 64-bit is 8 bytes. --- nimble/host/mesh/include/mesh/glue.h | 2 +- nimble/host/mesh/src/glue.c | 1 + nimble/host/mesh/src/transport.c | 7 ++++--- porting/npl/linux/include/nimble/nimble_npl_os.h | 3 ++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 8c9166c259..9a4bd9a524 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -411,7 +411,7 @@ static inline unsigned int find_msb_set(uint32_t op) #define CONFIG_BT_MESH_LPN_GROUPS MYNEWT_VAL(BLE_MESH_LPN_GROUPS) #define CONFIG_BT_MESH_ADV_BUF_COUNT MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT) -#define CONFIG_BT_MESH_SEG_BUFS MYNEWT_VAL(BLE_MESH_SEG_BUFS ) +#define CONFIG_BT_MESH_SEG_BUFS MYNEWT_VAL(BLE_MESH_SEG_BUFS) #define CONFIG_BT_MESH_FRIEND_QUEUE_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE) #define CONFIG_BT_MESH_FRIEND_RECV_WIN MYNEWT_VAL(BLE_MESH_FRIEND_RECV_WIN) #define CONFIG_BT_MESH_LPN_POLL_TIMEOUT MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT) diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index aab7f37414..8862344dca 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -906,6 +906,7 @@ int create_free_list(struct k_mem_slab *slab) uint32_t j; char *p; + /* blocks must be word aligned */ if(((slab->block_size | (uintptr_t)slab->buffer) & (sizeof(void *) - 1)) != 0) { return -EINVAL; diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 6391272d02..3582c998bf 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -113,11 +113,12 @@ static struct seg_rx { struct k_delayed_work ack; } seg_rx[CONFIG_BT_MESH_RX_SEG_MSG_COUNT]; -char _k_mem_slab_buffer_[(BT_MESH_APP_SEG_SDU_MAX*CONFIG_BT_MESH_SEG_BUFS)]; + +char _k_mem_slab_buffer_[OS_ALIGN((BT_MESH_APP_SEG_SDU_MAX)*(CONFIG_BT_MESH_SEG_BUFS), OS_ALIGNMENT)]; struct k_mem_slab segs = { .num_blocks = CONFIG_BT_MESH_SEG_BUFS, - .block_size = BT_MESH_APP_SEG_SDU_MAX, + .block_size = OS_ALIGN(BT_MESH_APP_SEG_SDU_MAX, OS_ALIGNMENT), .buffer = _k_mem_slab_buffer_, .free_list = NULL, .num_used = 0 @@ -1616,7 +1617,7 @@ void bt_mesh_trans_init(void) /* We need to initialize memslab free list here */ rc = create_free_list(&segs); if (rc) { - BT_ERR("Failed to create free memslab list") + BT_ERR("Failed to create free memslab list (error: %d)", rc); } for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { diff --git a/porting/npl/linux/include/nimble/nimble_npl_os.h b/porting/npl/linux/include/nimble/nimble_npl_os.h index bdd3988699..585d378525 100644 --- a/porting/npl/linux/include/nimble/nimble_npl_os.h +++ b/porting/npl/linux/include/nimble/nimble_npl_os.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "os_types.h" @@ -30,7 +31,7 @@ extern "C" { #endif -#define BLE_NPL_OS_ALIGNMENT 4 +#define BLE_NPL_OS_ALIGNMENT (__WORDSIZE / 8) #define BLE_NPL_TIME_FOREVER INT32_MAX From c185dd6719b1cc9e08abada79e16e866118d3501 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 1 Oct 2021 22:08:10 +0200 Subject: [PATCH 093/306] nimble/ll: Fix encrypted data PDU payload length calculation Encrypted data PDU payload includes MIC, so we need to take this into account when calculating actual payload size available for data. --- nimble/controller/src/ble_ll_conn.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 53303789b9..a2a577e769 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -918,6 +918,7 @@ static uint16_t ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) { uint16_t phy_max_tx_octets; + uint16_t mic_len; uint16_t ret; #if (BLE_LL_BT5_PHY_SUPPORTED == 1) @@ -940,11 +941,19 @@ ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) ret = pyld_len; - if (ret > connsm->eff_max_tx_octets) { + mic_len = 0; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (CONN_F_ENCRYPTED(connsm)) { + mic_len = BLE_LL_DATA_MIC_LEN; + } +#endif + + + if (ret > connsm->eff_max_tx_octets - mic_len) { ret = connsm->eff_max_tx_octets; } - if (ret > phy_max_tx_octets) { + if (ret > phy_max_tx_octets - mic_len) { ret = phy_max_tx_octets; } From fbd0a8c24d369a17dc04281f58a17ed7392e7f22 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 28 Sep 2021 01:38:26 +0200 Subject: [PATCH 094/306] nimble/ll: Refactor item scheduling This refactors all scheduling APIs (i.e. insertions to scheduler) to use common code instead of reimplementing the same or similar flow over and over again. The single 'ble_ll_sched_insert' call covers all currently possible scenarios with minimal overhead so all existing insertion APIs use it and add some more extra processing if needed. Also it adds some flexibility via preemption callback so it's possible to better define priorities for each item. --- .../include/controller/ble_ll_sched.h | 9 +- nimble/controller/src/ble_ll_adv.c | 22 +- nimble/controller/src/ble_ll_conn.c | 4 +- nimble/controller/src/ble_ll_sched.c | 1083 +++++------------ 4 files changed, 352 insertions(+), 766 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h index bed864029f..15f331998c 100644 --- a/nimble/controller/include/controller/ble_ll_sched.h +++ b/nimble/controller/include/controller/ble_ll_sched.h @@ -25,8 +25,8 @@ extern "C" { #endif /* Time per BLE scheduler slot */ -#define BLE_LL_SCHED_USECS_PER_SLOT (1250) -#define BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT (41) /* 1 tick = 30.517 usecs */ +#define BLE_LL_SCHED_USECS_PER_SLOT (1250) +#define BLE_LL_SCHED_TICKS_PER_SLOT (41) /* 1 tick = 30.517 usecs */ /* * Worst case time needed for scheduled advertising item. This is the longest @@ -160,8 +160,7 @@ int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb, void *arg); /* Schedule periodic advertising event */ -int ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start, - bool after_overlap); +int ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, bool first_event); int ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, uint32_t anchor_point, @@ -172,7 +171,7 @@ int ble_ll_sched_sync(struct ble_ll_sched_item *sch, int8_t phy_mode); /* Reschedule an advertising event */ -int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, +int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t max_delay_ticks); /* Reschedule and advertising pdu */ diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 7efe914240..19270accde 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -2280,7 +2280,6 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, { struct ble_ll_adv_sync *sync; struct ble_ll_sched_item *sch; - uint32_t sch_start; uint32_t max_usecs; uint8_t chan; int rc; @@ -2323,7 +2322,7 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, sch->end_time = sch->start_time + ble_ll_usecs_to_ticks_round_up(max_usecs); sch->start_time -= g_ble_ll_sched_offset_ticks; - rc = ble_ll_sched_periodic_adv(sch, &sch_start, first_pdu); + rc = ble_ll_sched_periodic_adv(sch, first_pdu); if (rc) { STATS_INC(ble_ll_stats, periodic_adv_drop_event); ble_npl_eventq_put(&g_ble_ll_data.ll_evq, @@ -2331,7 +2330,7 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, return; } - sync->start_time = sch_start + g_ble_ll_sched_offset_ticks; + sync->start_time = sch->start_time + g_ble_ll_sched_offset_ticks; assert(first_pdu || (sync->start_time == advsm->periodic_adv_event_start_time)); @@ -4585,13 +4584,15 @@ ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm) static void ble_ll_adv_reschedule_event(struct ble_ll_adv_sm *advsm) { - int rc; - uint32_t start_time; + struct ble_ll_sched_item *sch; uint32_t max_delay_ticks; + int rc; assert(advsm->adv_enabled); - if (!advsm->adv_sch.enqueued) { + sch = &advsm->adv_sch; + + if (!sch->enqueued) { if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { max_delay_ticks = 0; } else { @@ -4599,16 +4600,15 @@ ble_ll_adv_reschedule_event(struct ble_ll_adv_sm *advsm) os_cputime_usecs_to_ticks(BLE_LL_ADV_DELAY_MS_MAX * 1000); } - rc = ble_ll_sched_adv_reschedule(&advsm->adv_sch, &start_time, - max_delay_ticks); + rc = ble_ll_sched_adv_reschedule(sch, max_delay_ticks); if (rc) { ble_ll_adv_drop_event(advsm); return; } - start_time += g_ble_ll_sched_offset_ticks; - advsm->adv_event_start_time = start_time; - advsm->adv_pdu_start_time = start_time; + advsm->adv_event_start_time = sch->start_time + + g_ble_ll_sched_offset_ticks; + advsm->adv_pdu_start_time = advsm->adv_event_start_time; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index a2a577e769..0f930d94e3 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -2337,7 +2337,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) #if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) itvl = g_ble_ll_sched_data.sch_ticks_per_period; #else - itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; + itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_TICKS_PER_SLOT; #endif if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { @@ -2451,7 +2451,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) #else connsm->ce_end_time = connsm->anchor_point + - (MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT) + (MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_TICKS_PER_SLOT) + os_cputime_usecs_to_ticks(connsm->slave_cur_tx_win_usecs) + 1; #endif connsm->slave_cur_window_widening = BLE_LL_JITTER_USECS; diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index b0fc4f5c42..1eb7d549ea 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -20,7 +20,6 @@ #include #include #include -#include "os/os.h" #include "os/os_cputime.h" #include "ble/xcvr.h" #include "controller/ble_phy.h" @@ -35,20 +34,21 @@ #include "ble_ll_priv.h" #include "ble_ll_conn_priv.h" -/* XXX: this is temporary. Not sure what I want to do here */ -struct hal_timer g_ble_ll_sched_timer; +#define BLE_LL_SCHED_MAX_DELAY_ANY (0x7fffffff) -uint8_t g_ble_ll_sched_offset_ticks; +static struct hal_timer g_ble_ll_sched_timer; +static uint8_t g_ble_ll_sched_timer_running; -#define BLE_LL_SCHED_ADV_WORST_CASE_USECS \ - (BLE_LL_SCHED_MAX_ADV_PDU_USECS + BLE_LL_IFS + BLE_LL_SCHED_ADV_MAX_USECS \ - + XCVR_TX_SCHED_DELAY_USECS) +uint8_t g_ble_ll_sched_offset_ticks; #if (BLE_LL_SCHED_DEBUG == 1) int32_t g_ble_ll_sched_max_late; int32_t g_ble_ll_sched_max_early; #endif +typedef int (* ble_ll_sched_preempt_cb_t)(struct ble_ll_sched_item *sch, + struct ble_ll_sched_item *item); + /* XXX: TODO: * 1) Add some accounting to the schedule code to see how late we are * (min/max?) @@ -62,12 +62,203 @@ int32_t g_ble_ll_sched_max_early; */ /* Queue for timers */ -TAILQ_HEAD(ll_sched_qhead, ble_ll_sched_item) g_ble_ll_sched_q; +static TAILQ_HEAD(ll_sched_qhead, ble_ll_sched_item) g_ble_ll_sched_q; #if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) struct ble_ll_sched_obj g_ble_ll_sched_data; #endif +static int +preempt_any(struct ble_ll_sched_item *sch, + struct ble_ll_sched_item *item) +{ + return 1; +} + +static int +preempt_none(struct ble_ll_sched_item *sch, + struct ble_ll_sched_item *item) +{ + return 0; +} + +static int +preempt_any_except_conn(struct ble_ll_sched_item *sch, + struct ble_ll_sched_item *item) +{ + BLE_LL_ASSERT(sch->sched_type == BLE_LL_SCHED_TYPE_CONN); + + if (item->sched_type != BLE_LL_SCHED_TYPE_CONN) { + return 1; + } + + return ble_ll_conn_is_lru(sch->cb_arg, item->cb_arg); +} + +static inline int +ble_ll_sched_check_overlap(struct ble_ll_sched_item *sch1, + struct ble_ll_sched_item *sch2) +{ + /* Note: item ranges are defined as [start, end) so items do not overlap + * if one item starts at the same time as another ends. + */ + return CPUTIME_GT(sch1->end_time, sch2->start_time) && + CPUTIME_GT(sch2->end_time, sch1->start_time); +} + +static void +ble_ll_sched_preempt(struct ble_ll_sched_item *sch, + struct ble_ll_sched_item *first) +{ + struct ble_ll_sched_item *entry; + struct ble_ll_sched_item *next; + struct ble_ll_conn_sm *connsm; + + entry = first; + + do { + next = TAILQ_NEXT(entry, link); + + TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); + entry->enqueued = 0; + + switch (entry->sched_type) { + case BLE_LL_SCHED_TYPE_CONN: + connsm = (struct ble_ll_conn_sm *)entry->cb_arg; + ble_ll_event_send(&connsm->conn_ev_end); + break; + case BLE_LL_SCHED_TYPE_ADV: + ble_ll_adv_event_rmvd_from_sched(entry->cb_arg); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_LL_SCHED_TYPE_SCAN_AUX: + ble_ll_scan_aux_break(entry->cb_arg); + break; + case BLE_LL_SCHED_TYPE_AUX_SCAN: + ble_ll_scan_end_adv_evt(entry->cb_arg); + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) + case BLE_LL_SCHED_TYPE_PERIODIC: + ble_ll_adv_periodic_rmvd_from_sched(entry->cb_arg); + break; + case BLE_LL_SCHED_TYPE_SYNC: + ble_ll_sync_rmvd_from_sched(entry->cb_arg); + break; +#endif +#endif + default: + BLE_LL_ASSERT(0); + break; + } + + entry = next; + } while (entry != sch); +} + +static inline void +ble_ll_sched_q_head_changed(void) +{ + struct ble_ll_sched_item *first; + + g_ble_ll_sched_timer_running = 0; + os_cputime_timer_stop(&g_ble_ll_sched_timer); + + first = TAILQ_FIRST(&g_ble_ll_sched_q); + ble_ll_rfmgmt_sched_changed(first); +} + +static inline void +ble_ll_sched_restart(void) +{ + struct ble_ll_sched_item *first; + + first = TAILQ_FIRST(&g_ble_ll_sched_q); + + if (!g_ble_ll_sched_timer_running && first) { + g_ble_ll_sched_timer_running = 1; + os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time); + } +} + +static int +ble_ll_sched_insert(struct ble_ll_sched_item *sch, uint32_t max_delay, + ble_ll_sched_preempt_cb_t preempt_cb) +{ + struct ble_ll_sched_item *preempt_first; + struct ble_ll_sched_item *first; + struct ble_ll_sched_item *entry; + uint32_t max_start_time; + uint32_t duration; + + OS_ASSERT_CRITICAL(); + + preempt_first = NULL; + + max_start_time = sch->start_time + max_delay; + duration = sch->end_time - sch->start_time; + + first = TAILQ_FIRST(&g_ble_ll_sched_q); + if (!first) { + TAILQ_INSERT_HEAD(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 1; + goto done; + } + + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { + if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { + TAILQ_INSERT_BEFORE(entry, sch, link); + sch->enqueued = 1; + goto done; + } + + /* If current item overlaps our item check if we can preempt. If we + * cannot preempt, move our item past current item and see if it's + * still within allowed range. + */ + + if (ble_ll_sched_check_overlap(sch, entry)) { + if (preempt_cb(sch, entry)) { + if (!preempt_first) { + preempt_first = entry; + } + } else { + sch->start_time = entry->end_time; + + if ((max_delay == 0) || CPUTIME_GEQ(sch->start_time, + max_start_time)) { + sch->enqueued = 0; + goto done; + } + + sch->end_time = sch->start_time + duration; + preempt_first = NULL; + } + } + } + + if (!entry) { + TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + sch->enqueued = 1; + } + +done: + if (preempt_first) { + BLE_LL_ASSERT(sch->enqueued); + ble_ll_sched_preempt(sch, preempt_first); + } + + /* Pause scheduler if inserted as 1st item, we do not want to miss this + * one. Caller should restart outside critical section. + */ + if (TAILQ_FIRST(&g_ble_ll_sched_q) == sch) { + BLE_LL_ASSERT(sch->enqueued); + ble_ll_sched_q_head_changed(); + } + + return sch->enqueued ? 0 : -1; +} + +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) /** * Checks if two events in the schedule will overlap in time. NOTE: consecutive * schedule items can end and start at the same time. @@ -98,6 +289,7 @@ ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1, return rc; } +#endif /* * Determines if the schedule item overlaps the currently running schedule @@ -119,26 +311,7 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch) return rc; } -static int -ble_ll_sched_conn_overlap(struct ble_ll_sched_item *entry) -{ - int rc; - struct ble_ll_conn_sm *connsm; - - /* Should only be advertising or a connection here */ - if (entry->sched_type == BLE_LL_SCHED_TYPE_CONN) { - connsm = (struct ble_ll_conn_sm *)entry->cb_arg; - entry->enqueued = 0; - TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); - ble_ll_event_send(&connsm->conn_ev_end); - rc = 0; - } else { - rc = -1; - } - - return rc; -} - +#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) static struct ble_ll_sched_item * ble_ll_sched_insert_if_empty(struct ble_ll_sched_item *sch) { @@ -151,18 +324,15 @@ ble_ll_sched_insert_if_empty(struct ble_ll_sched_item *sch) } return entry; } +#endif int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) { - int rc; - os_sr_t sr; - uint32_t usecs; struct ble_ll_sched_item *sch; - struct ble_ll_sched_item *start_overlap; - struct ble_ll_sched_item *end_overlap; - struct ble_ll_sched_item *entry; - struct ble_ll_conn_sm *tmp; + uint32_t usecs; + os_sr_t sr; + int rc; /* Get schedule element from connection */ sch = &connsm->conn_sch; @@ -183,7 +353,6 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) return -1; } - /* We have to find a place for this schedule */ OS_ENTER_CRITICAL(sr); if (ble_ll_sched_overlaps_current(sch)) { @@ -191,101 +360,11 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) return -1; } - /* Stop timer since we will add an element */ - os_cputime_timer_stop(&g_ble_ll_sched_timer); - - start_overlap = NULL; - end_overlap = NULL; - rc = 0; - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - if (ble_ll_sched_is_overlap(sch, entry)) { - if (entry->sched_type == BLE_LL_SCHED_TYPE_CONN && - !ble_ll_conn_is_lru((struct ble_ll_conn_sm *)sch->cb_arg, - (struct ble_ll_conn_sm *)entry->cb_arg)) { - /* Only insert if this element is older than all that we - * overlap - */ - start_overlap = NULL; - rc = -1; - break; - } - - if (start_overlap == NULL) { - start_overlap = entry; - end_overlap = entry; - } else { - end_overlap = entry; - } - } else { - if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - break; - } - } - } - - if (!rc) { - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - sch->enqueued = 1; - } - - /* Remove first to last scheduled elements */ - entry = start_overlap; - while (entry) { - start_overlap = TAILQ_NEXT(entry,link); - switch (entry->sched_type) { - case BLE_LL_SCHED_TYPE_CONN: - tmp = (struct ble_ll_conn_sm *)entry->cb_arg; - ble_ll_event_send(&tmp->conn_ev_end); - break; - case BLE_LL_SCHED_TYPE_ADV: - ble_ll_adv_event_rmvd_from_sched((struct ble_ll_adv_sm *)entry->cb_arg); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_LL_SCHED_TYPE_SCAN_AUX: - ble_ll_scan_aux_break(entry->cb_arg); - break; - case BLE_LL_SCHED_TYPE_AUX_SCAN: - ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)entry->cb_arg); - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - case BLE_LL_SCHED_TYPE_PERIODIC: - ble_ll_adv_periodic_rmvd_from_sched((struct ble_ll_adv_sm *)entry->cb_arg); - break; - case BLE_LL_SCHED_TYPE_SYNC: - ble_ll_sync_rmvd_from_sched((struct ble_ll_sync_sm *)entry->cb_arg); - break; -#endif -#endif - default: - BLE_LL_ASSERT(0); - break; - } - - TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); - entry->enqueued = 0; - - if (entry == end_overlap) { - break; - } - entry = start_overlap; - } - - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } else { - sch = entry; - } + rc = ble_ll_sched_insert(sch, 0, preempt_any_except_conn); OS_EXIT_CRITICAL(sr); - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); return rc; } @@ -405,7 +484,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, } } earliest_start += MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * - BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; + BLE_LL_SCHED_TICKS_PER_SLOT; itvl_t = connsm->conn_itvl_ticks; /* We have to find a place for this schedule */ @@ -540,27 +619,17 @@ int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len) { - int rc; - os_sr_t sr; - uint8_t req_slots; - uint32_t initial_start; + struct ble_ll_sched_item *sch; + uint32_t orig_start_time; uint32_t earliest_start; - uint32_t earliest_end; - uint32_t dur; - uint32_t itvl_t; + uint32_t min_win_offset; + uint32_t max_delay; uint32_t adv_rxend; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *sch; - - /* - * XXX: TODO this code assumes the advertisement and connect request were - * sent at 1Mbps. - */ + os_sr_t sr; + int rc; /* Get schedule element from connection */ - rc = -1; sch = &connsm->conn_sch; - req_slots = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS); /* XXX: * The calculations for the 32kHz crystal bear alot of explanation. The @@ -603,7 +672,6 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, * wont be listening. We could do better calculation if we wanted to use * a transmit window of 1 as opposed to 2, but for now we dont care. */ - dur = req_slots * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; adv_rxend = os_cputime_get32(); if (ble_hdr->rxinfo.channel >= BLE_PHY_NUM_DATA_CHANS) { /* @@ -635,86 +703,38 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, BLE_LL_ASSERT(0); } } - earliest_start += MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * - BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT; - earliest_end = earliest_start + dur; - itvl_t = connsm->conn_itvl_ticks; - /* We have to find a place for this schedule */ - OS_ENTER_CRITICAL(sr); + sch->start_time = earliest_start - g_ble_ll_sched_offset_ticks; + sch->end_time = earliest_start + MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * + BLE_LL_SCHED_TICKS_PER_SLOT; - /* The schedule item must occur after current running item (if any) */ - sch->start_time = earliest_start; - initial_start = earliest_start; + orig_start_time = sch->start_time; - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible */ - rc = 0; - connsm->tx_win_off = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET); - } else { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - /* Set these because overlap function needs them to be set */ - sch->start_time = earliest_start; - sch->end_time = earliest_end; + min_win_offset = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * + BLE_LL_SCHED_TICKS_PER_SLOT; + sch->start_time += min_win_offset; + sch->end_time += min_win_offset; - /* We can insert if before entry in list */ - if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - if ((earliest_start - initial_start) <= itvl_t) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - } - break; - } + max_delay = connsm->conn_itvl_ticks - min_win_offset; - /* Check for overlapping events */ - if (ble_ll_sched_is_overlap(sch, entry)) { - /* Earliest start is end of this event since we overlap */ - earliest_start = entry->end_time; - earliest_end = earliest_start + dur; - } - } + OS_ENTER_CRITICAL(sr); - /* Must be able to schedule within one connection interval */ - if (!entry) { - if ((earliest_start - initial_start) <= itvl_t) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - } + rc = ble_ll_sched_insert(sch, max_delay, preempt_none); + + if (rc == 0) { + connsm->tx_win_off = os_cputime_ticks_to_usecs(sch->start_time - + orig_start_time) / + BLE_LL_CONN_TX_OFF_USECS; + + connsm->anchor_point = sch->start_time + g_ble_ll_sched_offset_ticks; + connsm->anchor_point_usecs = 0; + connsm->ce_end_time = sch->end_time; - if (!rc) { - /* calculate number of window offsets. Each offset is 1.25 ms */ - sch->enqueued = 1; - /* - * NOTE: we dont add sched offset ticks as we want to under-estimate - * the transmit window slightly since the window size is currently - * 2 when using a 32768 crystal. - */ - dur = os_cputime_ticks_to_usecs(earliest_start - initial_start); - connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS; - } } - if (!rc) { - sch->start_time = earliest_start; - sch->end_time = earliest_end; - /* - * Since we have the transmit window to transmit in, we dont need - * to set the anchor point usecs; just transmit to the nearest tick. - */ - connsm->anchor_point = earliest_start + g_ble_ll_sched_offset_ticks; - connsm->anchor_point_usecs = 0; - connsm->ce_end_time = earliest_end; - } - - /* Get head of list to restart timer */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - ble_ll_rfmgmt_sched_changed(sch); - OS_EXIT_CRITICAL(sr); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); return rc; } @@ -732,15 +752,11 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm) { - int rc; - os_sr_t sr; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *next_sch; struct ble_ll_sched_item *sch; - int first = 0; + os_sr_t sr; + int rc; /* Get schedule element from connection */ - rc = -1; sch = &connsm->conn_sch; /* Set schedule start and end times */ @@ -755,68 +771,13 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm) sch->end_time = connsm->ce_end_time; sch->remainder = 0; - /* We have to find a place for this schedule */ OS_ENTER_CRITICAL(sr); - /* The schedule item must occur after current running item (if any) */ - if (ble_ll_sched_overlaps_current(sch)) { - OS_EXIT_CRITICAL(sr); - return rc; - } - - entry = ble_ll_sched_insert_if_empty(sch); - if (!entry) { - /* Nothing in schedule. Schedule as soon as possible */ - rc = 0; - first = 1; - } else { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - while (1) { - next_sch = entry->link.tqe_next; - /* Insert if event ends before next starts */ - if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - break; - } - - if (ble_ll_sched_is_overlap(sch, entry)) { - /* If we overlap with a connection, we re-schedule */ - if (ble_ll_sched_conn_overlap(entry)) { - break; - } - } - - /* Move to next entry */ - entry = next_sch; - - /* Insert at tail if none left to check */ - if (!entry) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - break; - } - } - - if (!rc) { - sch->enqueued = 1; - } - - next_sch = TAILQ_FIRST(&g_ble_ll_sched_q); - if (next_sch == sch) { - first = 1; - } else { - sch = next_sch; - } - } - - if (first) { - ble_ll_rfmgmt_sched_changed(sch); - } + rc = ble_ll_sched_insert(sch, 0, preempt_any); OS_EXIT_CRITICAL(sr); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); return rc; } @@ -853,7 +814,6 @@ ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, uint32_t window_widening, int8_t phy_mode) { - struct ble_ll_sched_item *entry; uint8_t start_time_rem_usecs; uint8_t window_rem_usecs; uint32_t window_ticks; @@ -893,7 +853,6 @@ ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, return -1; } - /* We have to find a place for this schedule */ OS_ENTER_CRITICAL(sr); if (ble_ll_sched_sync_overlaps_current(sch)) { @@ -901,43 +860,11 @@ ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, return -1; } - /* Try to find slot for sync scan. */ - 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 (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - break; - } - - /* Check for overlapping events. For now drop if it overlaps with - * anything. We can make it smarter later on - */ - if (ble_ll_sched_is_overlap(sch, entry)) { - rc = -1; - break; - } - } - - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } else { - sch = entry; - } + rc = ble_ll_sched_insert(sch, 0, preempt_none); OS_EXIT_CRITICAL(sr); - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); return rc; } @@ -947,7 +874,6 @@ ble_ll_sched_sync(struct ble_ll_sched_item *sch, uint32_t beg_cputime, uint32_t rem_usecs, uint32_t offset, int8_t phy_mode) { - struct ble_ll_sched_item *entry; uint32_t start_time_rem_usecs; uint32_t off_rem_usecs; uint32_t start_time; @@ -979,51 +905,14 @@ ble_ll_sched_sync(struct ble_ll_sched_item *sch, OS_ENTER_CRITICAL(sr); - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible - * If we are here it means sch has been added to the scheduler */ - goto done; - } - - /* Try to find slot for scan. */ - 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 (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - break; - } - - /* Check for overlapping events. For now drop if it overlaps with - * anything. We can make it smarter later on - */ - if (ble_ll_sched_is_overlap(sch, entry)) { - rc = -1; - break; - } - } - - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - -done: - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } else { - sch = entry; - } + rc = ble_ll_sched_insert(sch, 0, preempt_none); OS_EXIT_CRITICAL(sr); - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); STATS_INC(ble_ll_stats, sync_scheduled); + return rc; } #endif @@ -1033,257 +922,87 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb, void *arg) { os_sr_t sr; - uint32_t adv_start; - uint32_t duration; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *orig; - - /* Get length of schedule item */ - duration = sch->end_time - sch->start_time; - orig = sch; + int rc; OS_ENTER_CRITICAL(sr); - entry = ble_ll_sched_insert_if_empty(sch); - if (!entry) { - adv_start = sch->start_time; - } else { - /* XXX: no need to stop timer if not first on list. Modify code? */ - 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 (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - TAILQ_INSERT_BEFORE(entry, sch, link); - break; - } - - /* Check for overlapping events */ - if (ble_ll_sched_is_overlap(sch, entry)) { - /* Earliest start is end of this event since we overlap */ - sch->start_time = entry->end_time; - sch->end_time = sch->start_time + duration; - } - } - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - adv_start = sch->start_time; + rc = ble_ll_sched_insert(sch, BLE_LL_SCHED_MAX_DELAY_ANY, + preempt_none); + BLE_LL_ASSERT(rc == 0); - sch->enqueued = 1; - - /* Restart with head of list */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - } - - if (cb) { - cb((struct ble_ll_adv_sm *)orig->cb_arg, adv_start, arg); - } - - if (orig == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } + cb(sch->cb_arg, sch->start_time, arg); OS_EXIT_CRITICAL(sr); - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); - return 0; + return rc; } int -ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start, - bool after_overlap) +ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, bool first_event) { - int rc = 0; os_sr_t sr; - uint32_t adv_start; - uint32_t duration; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *orig = sch; - - /* Get length of schedule item */ - duration = sch->end_time - sch->start_time; + int rc; OS_ENTER_CRITICAL(sr); - entry = ble_ll_sched_insert_if_empty(sch); - if (!entry) { - adv_start = sch->start_time; - } else { - /* XXX: no need to stop timer if not first on list. Modify code? */ - 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 (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - TAILQ_INSERT_BEFORE(entry, sch, link); - break; - } - /* Check for overlapping events */ - if (ble_ll_sched_is_overlap(sch, entry)) { - if (after_overlap) { - /* Earliest start is end of this event since we overlap */ - sch->start_time = entry->end_time; - sch->end_time = sch->start_time + duration; - } else { - rc = -1; - break; - } - } - } - - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } - adv_start = sch->start_time; - - if (!rc) { - sch->enqueued = 1; - } - - /* Restart with head of list */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - } - - if (!rc) { - *start = adv_start; - } - - if (orig == sch) { - ble_ll_rfmgmt_sched_changed(sch); + if (first_event) { + rc = ble_ll_sched_insert(sch, BLE_LL_SCHED_MAX_DELAY_ANY, + preempt_none); + } else { + rc = ble_ll_sched_insert(sch, 0, preempt_any); } OS_EXIT_CRITICAL(sr); - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); return rc; } int -ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start, +ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t max_delay_ticks) { - int rc; - os_sr_t sr; - uint32_t orig_start; - uint32_t duration; + struct ble_ll_sched_item *next; + uint32_t max_end_time; uint32_t rand_ticks; - struct ble_ll_sched_item *entry; - struct ble_ll_sched_item *next_sch; - struct ble_ll_sched_item *before; - struct ble_ll_sched_item *start_overlap; - struct ble_ll_sched_item *end_overlap; - - /* Get length of schedule item */ - duration = sch->end_time - sch->start_time; + os_sr_t sr; + int rc; - /* Add maximum randomization delay to end */ - rand_ticks = max_delay_ticks; - sch->end_time += max_delay_ticks; + max_end_time = sch->end_time + max_delay_ticks; - start_overlap = NULL; - end_overlap = NULL; - before = NULL; - rc = 0; OS_ENTER_CRITICAL(sr); - entry = ble_ll_sched_insert_if_empty(sch); - if (entry) { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - while (1) { - next_sch = entry->link.tqe_next; - if (ble_ll_sched_is_overlap(sch, entry)) { - if (start_overlap == NULL) { - start_overlap = entry; - end_overlap = entry; - } else { - end_overlap = entry; - } - } else { - if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - before = entry; - break; - } - } - - entry = next_sch; - if (entry == NULL) { - break; - } - } + /* Try to schedule as early as possible but no later than max allowed delay. + * If succeeded, randomize start time to be within max allowed delay from + * the original start time but make sure it ends before next scheduled item. + */ - /* - * If there is no overlap, we either insert before the 'before' entry - * or we insert at the end if there is no before entry. - */ - if (start_overlap == NULL) { - if (before) { - TAILQ_INSERT_BEFORE(before, sch, link); - } else { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); + rc = ble_ll_sched_insert(sch, max_delay_ticks, preempt_none); + if (rc == 0) { + next = TAILQ_NEXT(sch, link); + if (next) { + if (CPUTIME_LT(next->start_time, max_end_time)) { + max_end_time = next->start_time; } + rand_ticks = max_end_time - sch->end_time; } else { - /* - * This item will overlap with others. See if we can fit it in - * with original duration. - */ - before = NULL; - orig_start = sch->start_time; - entry = start_overlap; - sch->end_time = sch->start_time + duration; - while (1) { - next_sch = entry->link.tqe_next; - 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); - break; - } else { - sch->start_time = entry->end_time; - sch->end_time = sch->start_time + duration; - } - - if (entry == end_overlap) { - rand_ticks = (orig_start + max_delay_ticks) - sch->start_time; - if (rand_ticks > max_delay_ticks) { - /* No place for advertisement. */ - rc = -1; - } else { - if (next_sch == NULL) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - } else { - TAILQ_INSERT_BEFORE(next_sch, sch, link); - } - } - break; - } - entry = next_sch; - BLE_LL_ASSERT(entry != NULL); - } + rand_ticks = max_delay_ticks; } - } - if (!rc) { - sch->enqueued = 1; if (rand_ticks) { - sch->start_time += ble_ll_rand() % rand_ticks; + rand_ticks = ble_ll_rand() % rand_ticks; } - sch->end_time = sch->start_time + duration; - *start = sch->start_time; - if (sch == TAILQ_FIRST(&g_ble_ll_sched_q)) { - ble_ll_rfmgmt_sched_changed(sch); - } + sch->start_time += rand_ticks; + sch->end_time += rand_ticks; } OS_EXIT_CRITICAL(sr); - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); return rc; } @@ -1293,36 +1012,24 @@ ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch) { uint8_t lls; os_sr_t sr; - struct ble_ll_sched_item *entry; + int rc; OS_ENTER_CRITICAL(sr); lls = ble_ll_state_get(); if ((lls == BLE_LL_STATE_ADV) || (lls == BLE_LL_STATE_CONNECTION) || - (lls == BLE_LL_STATE_SYNC)) { - goto adv_resched_pdu_fail; - } - - entry = ble_ll_sched_insert_if_empty(sch); - if (entry) { - /* If we overlap with the first item, simply re-schedule */ - if (ble_ll_sched_is_overlap(sch, entry)) { - goto adv_resched_pdu_fail; - } - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; + (lls == BLE_LL_STATE_SYNC)) { + OS_EXIT_CRITICAL(sr); + return -1; } - ble_ll_rfmgmt_sched_changed(TAILQ_FIRST(&g_ble_ll_sched_q)); + rc = ble_ll_sched_insert(sch, 0, preempt_none); OS_EXIT_CRITICAL(sr); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - return 0; -adv_resched_pdu_fail: - OS_EXIT_CRITICAL(sr); - return -1; + ble_ll_sched_restart(); + + return rc; } /** @@ -1335,75 +1042,71 @@ ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch) int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch) { + uint8_t first_removed; os_sr_t sr; - struct ble_ll_sched_item *first; - int rc = 1; + int rc; - if (!sch) { - return rc; - } + BLE_LL_ASSERT(sch); OS_ENTER_CRITICAL(sr); + + first_removed = 0; + if (sch->enqueued) { - first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (first == sch) { - os_cputime_timer_stop(&g_ble_ll_sched_timer); + if (sch == TAILQ_FIRST(&g_ble_ll_sched_q)) { + first_removed = 1; } TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); sch->enqueued = 0; + rc = 0; + } else { + rc = 1; + } - if (first == sch) { - first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (first) { - os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time); - } - ble_ll_rfmgmt_sched_changed(first); - } + if (first_removed) { + ble_ll_sched_q_head_changed(); } + OS_EXIT_CRITICAL(sr); + ble_ll_sched_restart(); + return rc; } void ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb) { - os_sr_t sr; - struct ble_ll_sched_item *entry; struct ble_ll_sched_item *first; + struct ble_ll_sched_item *entry; + uint8_t first_removed; + os_sr_t sr; OS_ENTER_CRITICAL(sr); - first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (!first) { - OS_EXIT_CRITICAL(sr); - return; + first = TAILQ_FIRST(&g_ble_ll_sched_q); + if (first->sched_type == type) { + first_removed = 1; } TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - if (entry->sched_type == type) { - if (first == entry) { - os_cputime_timer_stop(&g_ble_ll_sched_timer); - first = NULL; - } - - TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); - remove_cb(entry); - entry->enqueued = 0; + if (entry->sched_type != type) { + continue; } + TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link); + remove_cb(entry); + entry->enqueued = 0; } - if (!first) { - first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (first) { - os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time); - } - ble_ll_rfmgmt_sched_changed(first); + if (first_removed) { + ble_ll_sched_q_head_changed(); } OS_EXIT_CRITICAL(sr); + + ble_ll_sched_restart(); } /** @@ -1481,6 +1184,7 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) sched: BLE_LL_DEBUG_GPIO(SCHED_ITEM_CB, 1); BLE_LL_ASSERT(sch->sched_cb); + rc = sch->sched_cb(sch); BLE_LL_DEBUG_GPIO(SCHED_ITEM_CB, 0); return rc; @@ -1500,6 +1204,8 @@ ble_ll_sched_run(void *arg) BLE_LL_DEBUG_GPIO(SCHED_RUN, 1); + g_ble_ll_sched_timer_running = 0; + /* Look through schedule queue */ sch = TAILQ_FIRST(&g_ble_ll_sched_q); if (sch) { @@ -1520,13 +1226,7 @@ ble_ll_sched_run(void *arg) TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); sch->enqueued = 0; ble_ll_sched_execute_item(sch); - - /* Restart if there is an item on the schedule */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - if (sch) { - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); - } - ble_ll_rfmgmt_sched_changed(sch); + ble_ll_sched_restart(); } BLE_LL_DEBUG_GPIO(SCHED_RUN, 0); @@ -1586,7 +1286,6 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, uint32_t start_time_rem_usecs; uint32_t end_time; uint32_t dur; - struct ble_ll_sched_item *entry; struct ble_ll_sched_item *sch; int phy_mode; @@ -1621,58 +1320,16 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, OS_ENTER_CRITICAL(sr); - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible - * If we are here it means sch has been added to the scheduler */ - rc = 0; - goto done; - } - - /* Try to find slot for aux scan. */ - 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 (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - break; - } - - /* Check for overlapping events. For now drop if it overlaps with - * anything. We can make it smarter later on - */ - if (ble_ll_sched_is_overlap(sch, entry)) { - break; - } - } - - if (!entry) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - -done: + rc = ble_ll_sched_insert(sch, 0, preempt_none); if (rc == 0) { sch->cb_arg = ble_ll_scan_aux_data_ref(aux_scan); STATS_INC(ble_ll_stats, aux_scheduled); } - /* Get head of list to restart timer */ - entry = TAILQ_FIRST(&g_ble_ll_sched_q); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } else { - sch = entry; - } - OS_EXIT_CRITICAL(sr); - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + ble_ll_sched_restart(); return rc; } @@ -1681,7 +1338,6 @@ int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, uint8_t pdu_time_rem, uint32_t offset_us) { - struct ble_ll_sched_item *entry; uint32_t offset_ticks; os_sr_t sr; int rc; @@ -1696,42 +1352,11 @@ ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, OS_ENTER_CRITICAL(sr); - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Scheduler was empty, inserted as 1st element */ - rc = 0; - goto done; - } - - os_cputime_timer_stop(&g_ble_ll_sched_timer); - TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { - if (CPUTIME_LEQ(sch->end_time, entry->start_time)) { - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - rc = 0; - break; - } - - if (ble_ll_sched_is_overlap(sch, entry)) { - rc = -1; - break; - } - } - - if (!entry) { - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - rc = 0; - } - -done: - entry = TAILQ_FIRST(&g_ble_ll_sched_q); + rc = ble_ll_sched_insert(sch, 0, preempt_none); OS_EXIT_CRITICAL(sr); - if (entry == sch) { - ble_ll_rfmgmt_sched_changed(sch); - } - os_cputime_timer_start(&g_ble_ll_sched_timer, entry->start_time); + ble_ll_sched_restart(); return rc; } @@ -1740,57 +1365,18 @@ ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, #if MYNEWT_VAL(BLE_LL_DTM) int ble_ll_sched_dtm(struct ble_ll_sched_item *sch) { - int rc; os_sr_t sr; - struct ble_ll_sched_item *entry; + int rc; OS_ENTER_CRITICAL(sr); - if (!ble_ll_sched_insert_if_empty(sch)) { - /* Nothing in schedule. Schedule as soon as possible - * If we are here it means sch has been added to the scheduler */ - rc = 0; - goto done; - } - - /* Try to find slot for test. */ - 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 (sch->end_time <= entry->start_time) { - rc = 0; - TAILQ_INSERT_BEFORE(entry, sch, link); - sch->enqueued = 1; - break; - } - - /* Check for overlapping events. For now drop if it overlaps with - * anything. We can make it smarter later on - */ - if (ble_ll_sched_is_overlap(sch, entry)) { - OS_EXIT_CRITICAL(sr); - return -1; - } - } - - if (!entry) { - rc = 0; - TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link); - sch->enqueued = 1; - } - -done: - - /* Get head of list to restart timer */ - sch = TAILQ_FIRST(&g_ble_ll_sched_q); - - ble_ll_rfmgmt_sched_changed(sch); + rc = ble_ll_sched_insert(sch, 0, preempt_any); OS_EXIT_CRITICAL(sr); - /* Restart timer */ - BLE_LL_ASSERT(sch != NULL); - os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time); + if (rc == 0) { + ble_ll_sched_restart(); + } return rc; } @@ -1803,6 +1389,7 @@ int ble_ll_sched_dtm(struct ble_ll_sched_item *sch) void ble_ll_sched_stop(void) { + g_ble_ll_sched_timer_running = 0; os_cputime_timer_stop(&g_ble_ll_sched_timer); } From 815d890d537cd60b50b2797ee56dfc5467e4b4c5 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 14 Oct 2021 15:44:30 +0200 Subject: [PATCH 095/306] nimble/transport: Use max ACL data size for RAM transport Since in RAM transport ACL data are passed simply as an mbuf pointer between host and controller we can use max ACL data size to avoid data fragmentation over HCI. This actually saves some RAM since we do not need extra buffers for fragmented HCI ACL data. --- nimble/transport/ram/syscfg.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/transport/ram/syscfg.yml b/nimble/transport/ram/syscfg.yml index 3b822fcc60..cbb57163ad 100644 --- a/nimble/transport/ram/syscfg.yml +++ b/nimble/transport/ram/syscfg.yml @@ -37,7 +37,7 @@ syscfg.defs: description: > This is the maximum size of the data portion of HCI ACL data packets. It does not include the HCI data header (of 4 bytes). - value: 255 + value: 65535 BLE_TRANS_RAM_SYSINIT_STAGE: description: > From eaa1e6771ed8fb8b8ce1c7bca6c46c32bb204978 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 14 Oct 2021 12:47:31 +0200 Subject: [PATCH 096/306] nimble/hci: Fix mbuf allocation for HCI ACL fragmentation We need to use proper user pkt header length when allocating new mbuf for HCI ACL data fragment, otherwise leading space won't be set properly and data may be overwritten. See 20c4817625fc4d33b0d9c2f23cb0fe96eba5e988 for reference. Note: technically this does not make much sense since we use max HCI ACL data size for combined build so fragmentation won't happen, but let's fix it anyway just in case someone uses other value for whatever reason. --- nimble/host/src/ble_gatts.c | 2 +- nimble/host/src/ble_hs_hci.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/nimble/host/src/ble_gatts.c b/nimble/host/src/ble_gatts.c index a635f2d7f4..83402e7242 100644 --- a/nimble/host/src/ble_gatts.c +++ b/nimble/host/src/ble_gatts.c @@ -364,7 +364,7 @@ ble_gatts_val_access(uint16_t conn_handle, uint16_t attr_handle, gatt_ctxt->om = *om; } else { new_om = 1; - gatt_ctxt->om = os_msys_get_pkthdr(0, 0); + gatt_ctxt->om = ble_hs_mbuf_att_pkt(); if (gatt_ctxt->om == NULL) { return BLE_ATT_ERR_INSUFFICIENT_RES; } diff --git a/nimble/host/src/ble_hs_hci.c b/nimble/host/src/ble_hs_hci.c index e5c3a741e5..53d36473b6 100644 --- a/nimble/host/src/ble_hs_hci.c +++ b/nimble/host/src/ble_hs_hci.c @@ -41,11 +41,20 @@ static uint32_t ble_hs_hci_sup_feat; static uint8_t ble_hs_hci_version; +#if MYNEWT_VAL(BLE_CONTROLLER) #define BLE_HS_HCI_FRAG_DATABUF_SIZE \ (BLE_ACL_MAX_PKT_SIZE + \ BLE_HCI_DATA_HDR_SZ + \ sizeof (struct os_mbuf_pkthdr) + \ + sizeof (struct ble_mbuf_hdr) + \ sizeof (struct os_mbuf)) +#else +#define BLE_HS_HCI_FRAG_DATABUF_SIZE \ + (BLE_ACL_MAX_PKT_SIZE + \ + BLE_HCI_DATA_HDR_SZ + \ + sizeof (struct os_mbuf_pkthdr) + \ + sizeof (struct os_mbuf)) +#endif #define BLE_HS_HCI_FRAG_MEMBLOCK_SIZE \ (OS_ALIGN(BLE_HS_HCI_FRAG_DATABUF_SIZE, 4)) @@ -421,7 +430,11 @@ ble_hs_hci_frag_alloc(uint16_t frag_size, void *arg) struct os_mbuf *om; /* Prefer the dedicated one-element fragment pool. */ +#if MYNEWT_VAL(BLE_CONTROLLER) + om = os_mbuf_get_pkthdr(&ble_hs_hci_frag_mbuf_pool, sizeof(struct ble_mbuf_hdr)); +#else om = os_mbuf_get_pkthdr(&ble_hs_hci_frag_mbuf_pool, 0); +#endif if (om != NULL) { om->om_data += BLE_HCI_DATA_HDR_SZ; return om; From 43308a629e5b10b0848114e280bc4515d7cee4e2 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 14 Oct 2021 11:26:05 +0200 Subject: [PATCH 097/306] nimble/ll: Add gpio debug for rfmgmt --- nimble/controller/src/ble_ll_rfmgmt.c | 5 +++++ nimble/controller/syscfg.yml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/nimble/controller/src/ble_ll_rfmgmt.c b/nimble/controller/src/ble_ll_rfmgmt.c index 3bf5d5fae6..986645f4a1 100644 --- a/nimble/controller/src/ble_ll_rfmgmt.c +++ b/nimble/controller/src/ble_ll_rfmgmt.c @@ -27,6 +27,7 @@ #include "controller/ble_ll.h" #include "controller/ble_ll_sched.h" #include "controller/ble_ll_rfmgmt.h" +#include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0 @@ -65,6 +66,7 @@ ble_ll_rfmgmt_enable(void) g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_ENABLING; g_ble_ll_rfmgmt_data.enabled_at = os_cputime_get32(); ble_phy_rfclk_enable(); + BLE_LL_DEBUG_GPIO(RFMGMT, 1); } } @@ -74,6 +76,7 @@ ble_ll_rfmgmt_disable(void) OS_ASSERT_CRITICAL(); if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) { + BLE_LL_DEBUG_GPIO(RFMGMT, 0); ble_phy_rfclk_disable(); g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_OFF; } @@ -212,6 +215,8 @@ ble_ll_rfmgmt_init(void) { struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data; + BLE_LL_DEBUG_GPIO_INIT(RFMGMT); + rfmgmt->state = RFMGMT_STATE_OFF; rfmgmt->ticks_to_enabled = diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index ea5590f8e4..1050dbb7cc 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -367,6 +367,11 @@ syscfg.defs: GPIO pin number to debug scheduler item execution times. Pin is set to high state while item is executed. value: -1 + BLE_LL_DEBUG_GPIO_RFMGMT: + description: > + GPIO pin number to debug rfmgmt activity. Pin is set to high state + while rfmgmt is active. + value: -1 # Below settings allow to change scheduler timings. These should be left at # default values unless you know what you are doing! From 0682fa32b95dee9e79cc33580f8c33acd9f4e91f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 17 Oct 2021 12:29:46 +0200 Subject: [PATCH 098/306] nimble/phy/nrf: Fix checking for resolved addr We should check if NRF_AAR was enabled prior to checking its result to avoid reading some uninitialied values if resolver was not enabled. --- nimble/drivers/nrf51/src/ble_hw.c | 9 ++------- nimble/drivers/nrf52/src/ble_hw.c | 9 ++------- nimble/drivers/nrf5340/src/ble_hw.c | 10 +++------- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/nimble/drivers/nrf51/src/ble_hw.c b/nimble/drivers/nrf51/src/ble_hw.c index 3c7296b845..437efd4f7c 100644 --- a/nimble/drivers/nrf51/src/ble_hw.c +++ b/nimble/drivers/nrf51/src/ble_hw.c @@ -474,13 +474,8 @@ ble_hw_resolv_list_size(void) int ble_hw_resolv_list_match(void) { - uint32_t index; - - if (NRF_AAR->EVENTS_END) { - if (NRF_AAR->EVENTS_RESOLVED) { - index = NRF_AAR->STATUS; - return (int)index; - } + if (NRF_AAR->ENABLE && NRF_AAR->EVENTS_END && NRF_AAR->EVENTS_RESOLVED) { + return (int)NRF_AAR->STATUS; } return -1; diff --git a/nimble/drivers/nrf52/src/ble_hw.c b/nimble/drivers/nrf52/src/ble_hw.c index 82e6d17ed7..8ab24eba5a 100644 --- a/nimble/drivers/nrf52/src/ble_hw.c +++ b/nimble/drivers/nrf52/src/ble_hw.c @@ -474,13 +474,8 @@ ble_hw_resolv_list_size(void) int ble_hw_resolv_list_match(void) { - uint32_t index; - - if (NRF_AAR->EVENTS_END) { - if (NRF_AAR->EVENTS_RESOLVED) { - index = NRF_AAR->STATUS; - return (int)index; - } + if (NRF_AAR->ENABLE && NRF_AAR->EVENTS_END && NRF_AAR->EVENTS_RESOLVED) { + return (int)NRF_AAR->STATUS; } return -1; diff --git a/nimble/drivers/nrf5340/src/ble_hw.c b/nimble/drivers/nrf5340/src/ble_hw.c index bbe6169779..92bf024979 100644 --- a/nimble/drivers/nrf5340/src/ble_hw.c +++ b/nimble/drivers/nrf5340/src/ble_hw.c @@ -461,13 +461,9 @@ ble_hw_resolv_list_size(void) int ble_hw_resolv_list_match(void) { - uint32_t index; - - if (NRF_AAR_NS->EVENTS_END) { - if (NRF_AAR_NS->EVENTS_RESOLVED) { - index = NRF_AAR_NS->STATUS; - return (int)index; - } + if (NRF_AAR_NS->ENABLE && NRF_AAR_NS->EVENTS_END && + NRF_AAR_NS->EVENTS_RESOLVED) { + return (int)NRF_AAR_NS->STATUS; } return -1; From aab952c4a3f5a3c3ebd2b30e9b294a0569b664a3 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 15 Nov 2019 10:47:03 +0100 Subject: [PATCH 099/306] nimble/ll: Add LLCP tracing via HCI events This adds option to trace LLCP PDUs via HCI events. Each LLCP PDU is sent in a vendor-specific HCI event which can be decoded e.g. by btmon. Identifier and format of HCI event os the same as used by controllers from Intel so it may be necessary to fake NimBLE's manufacturer id by setting 'BLE_LL_MFRG_ID: 2' so btmon can decode events properly. --- .../include/controller/ble_ll_ctrl.h | 2 ++ nimble/controller/src/ble_ll_ctrl.c | 10 +++++++ nimble/controller/src/ble_ll_hci_ev.c | 28 +++++++++++++++++++ nimble/controller/syscfg.yml | 5 ++++ 4 files changed, 45 insertions(+) diff --git a/nimble/controller/include/controller/ble_ll_ctrl.h b/nimble/controller/include/controller/ble_ll_ctrl.h index 15a45b2a08..bd38e583e9 100644 --- a/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/nimble/controller/include/controller/ble_ll_ctrl.h @@ -316,6 +316,8 @@ void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm); void ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm); void ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm); void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line); +void ble_ll_hci_ev_send_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, + void *pdu, size_t length); 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); diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c index 384a48756e..7ef63d132d 100644 --- a/nimble/controller/src/ble_ll_ctrl.c +++ b/nimble/controller/src/ble_ll_ctrl.c @@ -2473,6 +2473,11 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) len = dptr[1]; opcode = dptr[2]; +#if MYNEWT_VAL(BLE_LL_HCI_LLCP_TRACE) + ble_ll_hci_ev_send_llcp_trace(0x03, connsm->conn_handle, connsm->event_cntr, + &dptr[2], len); +#endif + /* * rspbuf points to first byte of response. The response buffer does not * contain the Data Channel PDU. Thus, the first byte of rspbuf is the @@ -2802,6 +2807,11 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) int rc; uint8_t opcode; +#if MYNEWT_VAL(BLE_LL_HCI_LLCP_TRACE) + ble_ll_hci_ev_send_llcp_trace(0x04, connsm->conn_handle, connsm->event_cntr, + txpdu->om_data, txpdu->om_len); +#endif + rc = 0; opcode = txpdu->om_data[0]; switch (opcode) { diff --git a/nimble/controller/src/ble_ll_hci_ev.c b/nimble/controller/src/ble_ll_hci_ev.c index 0d6da9a01e..ccbb1aa94d 100644 --- a/nimble/controller/src/ble_ll_hci_ev.c +++ b/nimble/controller/src/ble_ll_hci_ev.c @@ -551,3 +551,31 @@ ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line) ble_ll_hci_event_send(hci_ev); } } + +#if MYNEWT_VAL(BLE_LL_HCI_LLCP_TRACE) +void +ble_ll_hci_ev_send_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, + void *pdu, size_t length) +{ + struct ble_hci_ev_vendor_debug *ev; + struct ble_hci_ev *hci_ev; + + hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_VENDOR_DEBUG; + hci_ev->length = sizeof(*ev) + 8 + length; + ev = (void *) hci_ev->data; + + ev->id = 0x17; + ev->data[0] = type; + put_le16(&ev->data[1], handle); + put_le16(&ev->data[3], count); + ev->data[5] = 0; + ev->data[6] = 0; + ev->data[7] = 0; + memcpy(&ev->data[8], pdu, length); + + ble_ll_hci_event_send(hci_ev); + } +} +#endif diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index 1050dbb7cc..b1fb6b1fb9 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -163,6 +163,11 @@ syscfg.defs: PHY enabled all the time. value: MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) + BLE_LL_HCI_LLCP_TRACE: + description: > + Enables LLCP tracing using HCI vendor-specific events. + value: '0' + # Configuration for LL supported features. # # There are a total 8 features that the LL can support. These can be found From 99de1340e7fbdee6a604415972bd24ec5117a78d Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 12 Oct 2021 14:13:20 +0200 Subject: [PATCH 100/306] nimble/ll: Optimize sync sm scheduler handling Scheduler item in sync sm can be initialize only once, no need to do this on each event. Callbacks for ADV_SYNC_IND and ADV_CHAIN_IND are pretty much the same except for wfr calculations so we'll just have flag to indicate what is being scanned. --- nimble/controller/src/ble_ll_sync.c | 127 ++++++++-------------------- 1 file changed, 36 insertions(+), 91 deletions(-) diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c index 78d9456f64..f121c286b0 100644 --- a/nimble/controller/src/ble_ll_sync.c +++ b/nimble/controller/src/ble_ll_sync.c @@ -61,6 +61,7 @@ #define BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED 0x0080 #define BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED 0x0100 #define BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP 0x0200 +#define BLE_LL_SYNC_SM_FLAG_CHAIN 0x0400 #define BLE_LL_SYNC_CHMAP_LEN 5 #define BLE_LL_SYNC_ITVL_USECS 1250 @@ -137,6 +138,8 @@ static uint8_t *g_ble_ll_sync_create_comp_ev; static struct ble_ll_sync_sm *g_ble_ll_sync_sm_current; +static int ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch); + static int ble_ll_sync_on_list(const uint8_t *addr, uint8_t addr_type, uint8_t sid) { @@ -211,7 +214,12 @@ ble_ll_sync_sm_clear(struct ble_ll_sync_sm *sm) BLE_LL_ASSERT(sm->sync_ev_end.ev.ev_queued == 0); BLE_LL_ASSERT(sm->sch.enqueued == 0); + memset(sm, 0, sizeof(*sm)); + + sm->sch.sched_cb = ble_ll_sync_event_start_cb; + sm->sch.cb_arg = sm; + sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; } static uint8_t @@ -436,6 +444,7 @@ ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch) struct ble_ll_sync_sm *sm; uint32_t wfr_usecs; uint32_t start; + uint8_t chan; int rc; /* Set current connection state machine */ @@ -451,7 +460,9 @@ ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch) ble_ll_state_set(BLE_LL_STATE_SYNC); /* Set channel */ - ble_phy_setchan(sm->chan_index, sm->access_addr, sm->crcinit); + chan = sm->flags & BLE_LL_SYNC_SM_FLAG_CHAIN ? sm->chan_chain : + sm->chan_index; + ble_phy_setchan(chan, sm->access_addr, sm->crcinit); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) ble_phy_resolv_list_disable(); @@ -469,31 +480,35 @@ ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch) rc = ble_phy_rx_set_start_time(start, sch->remainder); if (rc && rc != BLE_PHY_ERR_RX_LATE) { STATS_INC(ble_ll_stats, sync_event_failed); - rc = BLE_LL_SCHED_STATE_DONE; ble_ll_event_send(&sm->sync_ev_end); ble_ll_sync_current_sm_over(); + rc = BLE_LL_SCHED_STATE_DONE; } else { - /* - * Set flag that tells to set last anchor point if a packet - * has been received. - */ - sm->flags |= BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; - - /* Set WFR timer. - * If establishing we always adjust with offset unit. - * If this is first packet of sync (one that was pointed by from - * SyncInfo we don't adjust WFT with window widening. - */ - if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { + if (sm->flags & BLE_LL_SYNC_SM_FLAG_CHAIN) { wfr_usecs = (sm->flags & BLE_LL_SYNC_SM_FLAG_OFFSET_300) ? 300 : 30; - if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_SYNC_INFO)) { - wfr_usecs += 2 * sm->window_widening; - } } else { - wfr_usecs = 2 * sm->window_widening; + /* Set flag that tells to set last anchor point if a packet + * has been received. + */ + sm->flags |= BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; + + /* Set WFR timer. + * If establishing we always adjust with offset unit. + * If this is first packet of sync (one that was pointed by from + * SyncInfo we don't adjust WFR with window widening. + */ + if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) { + wfr_usecs = (sm->flags & BLE_LL_SYNC_SM_FLAG_OFFSET_300) ? 300 + : 30; + if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_SYNC_INFO)) { + wfr_usecs += 2 * sm->window_widening; + } + } else { + wfr_usecs = 2 * sm->window_widening; + } } - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usecs); + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usecs); rc = BLE_LL_SCHED_STATE_RUNNING; } @@ -865,63 +880,6 @@ ble_ll_sync_parse_aux_ptr(const uint8_t *buf, uint8_t *chan, uint32_t *offset, *phy = (aux_ptr_field >> 21) & 0x07; } -static int -ble_ll_sync_chain_start_cb(struct ble_ll_sched_item *sch) -{ - struct ble_ll_sync_sm *sm; - uint32_t wfr_usecs; - uint32_t start; - int rc; - - /* Set current connection state machine */ - sm = sch->cb_arg; - g_ble_ll_sync_sm_current = sm; - BLE_LL_ASSERT(sm); - - /* Disable whitelisting */ - ble_ll_whitelist_disable(); - - /* Set LL state */ - ble_ll_state_set(BLE_LL_STATE_SYNC); - - /* Set channel */ - ble_phy_setchan(sm->chan_chain, sm->access_addr, sm->crcinit); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - ble_phy_resolv_list_disable(); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - ble_phy_encrypt_disable(); -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_set(sm->phy_mode, sm->phy_mode); -#endif - - start = sch->start_time + g_ble_ll_sched_offset_ticks; - rc = ble_phy_rx_set_start_time(start, sch->remainder); - if (rc && rc != BLE_PHY_ERR_RX_LATE) { - STATS_INC(ble_ll_stats, sync_chain_failed); - rc = BLE_LL_SCHED_STATE_DONE; - ble_ll_event_send(&sm->sync_ev_end); - ble_ll_sync_current_sm_over(); - } else { - /* - * Clear flag that tells to set last anchor point if a packet - * has been received, this is chain and we don't need it. - */ - sm->flags &= ~BLE_LL_SYNC_SM_FLAG_SET_ANCHOR; - - wfr_usecs = (sm->flags & BLE_LL_SYNC_SM_FLAG_OFFSET_300) ? 300 : 30; - - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usecs); - rc = BLE_LL_SCHED_STATE_RUNNING; - } - - return rc; -} - static int ble_ll_sync_schedule_chain(struct ble_ll_sync_sm *sm, struct ble_mbuf_hdr *hdr, const uint8_t *aux) @@ -954,9 +912,7 @@ ble_ll_sync_schedule_chain(struct ble_ll_sync_sm *sm, struct ble_mbuf_hdr *hdr, sm->chan_chain = chan; - sm->sch.sched_cb = ble_ll_sync_chain_start_cb; - sm->sch.cb_arg = sm; - sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; + sm->flags |= BLE_LL_SYNC_SM_FLAG_CHAIN; return ble_ll_sched_sync(&sm->sch, hdr->beg_cputime, hdr->rem_usecs, offset, sm->phy_mode); @@ -1308,10 +1264,7 @@ ble_ll_sync_event_end(struct ble_npl_event *ev) /* Event ended so we are no longer chaining */ sm->flags &= ~BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED; - - sm->sch.sched_cb = ble_ll_sync_event_start_cb; - sm->sch.cb_arg = sm; - sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_CHAIN; do { if (ble_ll_sync_next_event(sm, 0) < 0) { @@ -1473,10 +1426,6 @@ ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd, sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id, sm->num_used_chans, sm->chanmap); - sm->sch.sched_cb = ble_ll_sync_event_start_cb; - sm->sch.cb_arg = sm; - sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; - if (ble_ll_sched_sync(&sm->sch, rxhdr->beg_cputime, rxhdr->rem_usecs, offset, sm->phy_mode)) { return; @@ -2031,10 +1980,6 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id, sm->num_used_chans, sm->chanmap); - sm->sch.sched_cb = ble_ll_sync_event_start_cb; - sm->sch.cb_arg = sm; - sm->sch.sched_type = BLE_LL_SCHED_TYPE_SYNC; - /* get anchor for specified conn event */ conn_event_count = get_le16(sync_ind + 20); ble_ll_conn_get_anchor(connsm, conn_event_count, &sm->anchor_point, From 70021b6dd854350b37e782212c318cb25e4caeea Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Thu, 14 Oct 2021 13:36:32 +0200 Subject: [PATCH 101/306] npl/riot: update syscfg/syscfg.h --- porting/npl/riot/include/syscfg/syscfg.h | 96 ++++++++++++++++-------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/porting/npl/riot/include/syscfg/syscfg.h b/porting/npl/riot/include/syscfg/syscfg.h index e3d282e1d8..480616b819 100644 --- a/porting/npl/riot/include/syscfg/syscfg.h +++ b/porting/npl/riot/include/syscfg/syscfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.9.0 */ #ifndef H_MYNEWT_SYSCFG_ @@ -18,16 +18,16 @@ /*** Repository @apache-mynewt-core info */ #ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE ("6b205affd69a6f05787264fa2c70c621bbbdd325") +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE ("58d4be4b8e33dd4738a2a0c1c2016a9195542833") #endif #ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE -#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE ("0.0.0") +#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE ("0.0.1") #endif /*** Repository @apache-mynewt-mcumgr info */ #ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR ("64f5060bd8bb466367e0da94da8b425d5b9f6388") +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR ("12b496e37caf20a45ab5aee4209b06c5d79ef9b1") #endif #ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR @@ -36,7 +36,7 @@ /*** Repository @apache-mynewt-nimble info */ #ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE ("3e5d7a994e117b2758906154433a1aac860cc845-dirty") +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE ("99de1340e7fbdee6a604415972bd24ec5117a78d") #endif #ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE @@ -45,7 +45,7 @@ /*** Repository @mcuboot info */ #ifndef MYNEWT_VAL_REPO_HASH_MCUBOOT -#define MYNEWT_VAL_REPO_HASH_MCUBOOT ("579b30c29999860f9f7d843a25ff5453b6542cce") +#define MYNEWT_VAL_REPO_HASH_MCUBOOT ("137d79717764ed32d5da4b4b301f32f81b2bf40f") #endif #ifndef MYNEWT_VAL_REPO_VERSION_MCUBOOT @@ -73,6 +73,10 @@ #define MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS (1) #endif +#ifndef MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT +#define MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT (0) +#endif + #ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ #define MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ (16) #endif @@ -85,6 +89,10 @@ #define MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES (0) #endif +#ifndef MYNEWT_VAL_HAL_SBRK +#define MYNEWT_VAL_HAL_SBRK (1) +#endif + #ifndef MYNEWT_VAL_HAL_SYSTEM_RESET_CB #define MYNEWT_VAL_HAL_SYSTEM_RESET_CB (0) #endif @@ -157,10 +165,24 @@ #define MYNEWT_VAL_MCU_GPIO_USE_PORT_EVENT (0) #endif +#ifndef MYNEWT_VAL_MCU_HFCLK_SOURCE__HFINT +#define MYNEWT_VAL_MCU_HFCLK_SOURCE__HFINT (0) +#endif +#ifndef MYNEWT_VAL_MCU_HFCLK_SOURCE__HFXO +#define MYNEWT_VAL_MCU_HFCLK_SOURCE__HFXO (1) +#endif +#ifndef MYNEWT_VAL_MCU_HFCLK_SOURCE +#define MYNEWT_VAL_MCU_HFCLK_SOURCE (1) +#endif + #ifndef MYNEWT_VAL_MCU_I2C_RECOVERY_DELAY_USEC #define MYNEWT_VAL_MCU_I2C_RECOVERY_DELAY_USEC (100) #endif +#ifndef MYNEWT_VAL_MCU_ICACHE_ENABLED +#define MYNEWT_VAL_MCU_ICACHE_ENABLED (0) +#endif + /* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ #ifndef MYNEWT_VAL_MCU_LFCLK_SOURCE__LFRC #define MYNEWT_VAL_MCU_LFCLK_SOURCE__LFRC (0) @@ -204,10 +226,6 @@ #define MYNEWT_VAL_NFC_PINS_AS_GPIO (1) #endif -#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC -#define MYNEWT_VAL_OS_TICKS_PER_SEC (128) -#endif - #ifndef MYNEWT_VAL_PWM_0 #define MYNEWT_VAL_PWM_0 (0) #endif @@ -532,6 +550,10 @@ #define MYNEWT_VAL_OS_COREDUMP (0) #endif +#ifndef MYNEWT_VAL_OS_COREDUMP_CB +#define MYNEWT_VAL_OS_COREDUMP_CB (0) +#endif + /* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_CPUTIME_FREQ #define MYNEWT_VAL_OS_CPUTIME_FREQ (32768) @@ -650,6 +672,11 @@ #define MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME (0) #endif +/* Overridden by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC +#define MYNEWT_VAL_OS_TICKS_PER_SEC (128) +#endif + #ifndef MYNEWT_VAL_OS_TIME_DEBUG #define MYNEWT_VAL_OS_TIME_DEBUG (0) #endif @@ -671,6 +698,10 @@ #define MYNEWT_VAL_BASELIBC_ASSERT_FILE_LINE (0) #endif +#ifndef MYNEWT_VAL_BASELIBC_EXECUTE_GLOBAL_CONSTRUCTORS +#define MYNEWT_VAL_BASELIBC_EXECUTE_GLOBAL_CONSTRUCTORS (1) +#endif + #ifndef MYNEWT_VAL_BASELIBC_PRESENT #define MYNEWT_VAL_BASELIBC_PRESENT (1) #endif @@ -693,8 +724,12 @@ #define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10) #endif +#ifndef MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG +#define MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG (0) +#endif + #ifndef MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE -#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (2) +#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (9) #endif /*** @apache-mynewt-core/sys/log/common */ @@ -748,23 +783,6 @@ #define MYNEWT_VAL_LOG_LEVEL (255) #endif -/*** @apache-mynewt-core/sys/mfg */ -#ifndef MYNEWT_VAL_MFG_LOG_LVL -#define MYNEWT_VAL_MFG_LOG_LVL (15) -#endif - -#ifndef MYNEWT_VAL_MFG_LOG_MODULE -#define MYNEWT_VAL_MFG_LOG_MODULE (128) -#endif - -#ifndef MYNEWT_VAL_MFG_MAX_MMRS -#define MYNEWT_VAL_MFG_MAX_MMRS (2) -#endif - -#ifndef MYNEWT_VAL_MFG_SYSINIT_STAGE -#define MYNEWT_VAL_MFG_SYSINIT_STAGE (100) -#endif - /*** @apache-mynewt-core/sys/sys */ #ifndef MYNEWT_VAL_DEBUG_PANIC_ENABLED #define MYNEWT_VAL_DEBUG_PANIC_ENABLED (1) @@ -994,6 +1012,10 @@ #define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_EV (-1) #endif +#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_RFMGMT +#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_RFMGMT (-1) +#endif + #ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB #define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB (-1) #endif @@ -1019,6 +1041,10 @@ #define MYNEWT_VAL_BLE_LL_EXT_ADV_AUX_PTR_CNT (0) #endif +#ifndef MYNEWT_VAL_BLE_LL_HCI_LLCP_TRACE +#define MYNEWT_VAL_BLE_LL_HCI_LLCP_TRACE (0) +#endif + #ifndef MYNEWT_VAL_BLE_LL_MASTER_SCA #define MYNEWT_VAL_BLE_LL_MASTER_SCA (4) #endif @@ -1069,6 +1095,10 @@ #define MYNEWT_VAL_BLE_LL_SCA (60) #endif +#ifndef MYNEWT_VAL_BLE_LL_SCAN_AUX_SEGMENT_CNT +#define MYNEWT_VAL_BLE_LL_SCAN_AUX_SEGMENT_CNT (8) +#endif + #ifndef MYNEWT_VAL_BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY #define MYNEWT_VAL_BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY (0) #endif @@ -1487,16 +1517,16 @@ #define MYNEWT_VAL_BLE_SM_SC (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY -#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS +#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif #ifndef MYNEWT_VAL_BLE_SM_SC_LVL #define MYNEWT_VAL_BLE_SM_SC_LVL (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS -#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) #endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST @@ -1568,7 +1598,7 @@ #endif #ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE -#define MYNEWT_VAL_BLE_ACL_BUF_SIZE (255) +#define MYNEWT_VAL_BLE_ACL_BUF_SIZE (65535) #endif #ifndef MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE From 4fd03df5433617284294078ac4dc39e3b16a569c Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Wed, 20 Oct 2021 17:22:31 +0200 Subject: [PATCH 102/306] npl/riot: map nrf52_clock_hfxo_request/release() Compiling the hal_timer abstractions requires nrf52_clock_hfxo_request() and _release() functions to be available. This commit maps the appropriate RIOT functions in the NPL layer. --- .../npl/riot/include/nimble/nimble_npl_os.h | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/porting/npl/riot/include/nimble/nimble_npl_os.h b/porting/npl/riot/include/nimble/nimble_npl_os.h index ee0dfab340..4633cbd1a7 100644 --- a/porting/npl/riot/include/nimble/nimble_npl_os.h +++ b/porting/npl/riot/include/nimble/nimble_npl_os.h @@ -27,6 +27,10 @@ #include "sema.h" #include "ztimer.h" +#if defined(CPU_FAM_NRF51) || defined(CPU_FAM_NRF52) +#include "nrf_clock.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -270,6 +274,22 @@ ble_npl_hw_is_in_critical(void) return (bool)!irq_is_enabled(); } +/* XXX: these functions are required to build hal_timer.c, however with the +* default configuration they are never used... */ +#if defined(CPU_FAM_NRF51) || defined(CPU_FAM_NRF52) +static inline void +nrf52_clock_hfxo_request(void) +{ + clock_hfxo_request(); +} + +static inline void +nrf52_clock_hfxo_release(void) +{ + clock_hfxo_release(); +} +#endif + #ifdef __cplusplus } #endif From 8d66e40cc901ac37eccea54752df0803879c1e57 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Mon, 25 Oct 2021 12:34:16 +0200 Subject: [PATCH 103/306] controller: fix assert bug in ble_ll_sched_insert() When trying to schedule connection events for a connection while there are already advertising events as well as connections events for other connections in the queue, ble_ll_sched_insert() triggers an assertion failure. This happens, because `preemt_first` is not reset for the case that the new event can not be scheduled. This commit fixes this issue. --- nimble/controller/src/ble_ll_sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index 1eb7d549ea..1c7db41b9b 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -222,6 +222,7 @@ ble_ll_sched_insert(struct ble_ll_sched_item *sch, uint32_t max_delay, preempt_first = entry; } } else { + preempt_first = NULL; sch->start_time = entry->end_time; if ((max_delay == 0) || CPUTIME_GEQ(sch->start_time, @@ -231,7 +232,6 @@ ble_ll_sched_insert(struct ble_ll_sched_item *sch, uint32_t max_delay, } sch->end_time = sch->start_time + duration; - preempt_first = NULL; } } } From 21fa48c18cc5376f997c87ce27704035e097c42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 29 Oct 2021 10:05:47 +0200 Subject: [PATCH 104/306] host/mesh: fix send_pub_key We should copy from om_data, not om_databuf. --- nimble/host/mesh/src/provisioner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index c51a769674..2e592096e1 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -349,7 +349,7 @@ static void send_pub_key(void) sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32); /* PublicKeyProvisioner */ - memcpy(&bt_mesh_prov_link.conf_inputs[17], &buf->om_databuf[1], 64); + memcpy(&bt_mesh_prov_link.conf_inputs[17], &buf->om_data[1], 64); if (bt_mesh_prov_send(buf, public_key_sent)) { BT_ERR("Failed to send Public Key"); From 5c80f17a36a422837d9d5fa1d93a83831cb4da72 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 28 Oct 2021 10:31:44 +0200 Subject: [PATCH 105/306] nimble/phy/cmac: Fix rx-tx-rx transition setup In rare cases, tx-rx transition after rx may not be set properly and this can result in a connection that is not established properly. Transition type is set from ble_phy_tx which is called from sw_mac isr and it should be set before bs_start is fired since it will setup that transition. This is not a problem on 1st tx, but in case this happens after rx, it may happen that bs_start is called before ble_phy_tx sets transition type, so there will be no transition set. However, following events will have proper transition set so they will act accordingly. This probably can be recovered in most cases, but in case of extended connection we will not receive AUX_CONNECT_RSP and will keep "waiting" for it, so the connection will not be set properly before 1st conn event and that results in an assert. The fix is to block bs_ctrl interrupts on tx-rx transition to make sure bs_start will not happen until ble_phy_tx sets transition correctly. Similar flow is already used for 1st tx, i.e. bs_ctrl interrupts are disabled by ble_phy_set_start_time and enabled again in ble_phy_tx. Obviously, we also have to enable interrupts in ble_phy_disable in case flow is interrupted somewhere in the middle. --- nimble/drivers/dialog_cmac/src/ble_phy.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/nimble/drivers/dialog_cmac/src/ble_phy.c b/nimble/drivers/dialog_cmac/src/ble_phy.c index 74c67b68b5..212d19b671 100644 --- a/nimble/drivers/dialog_cmac/src/ble_phy.c +++ b/nimble/drivers/dialog_cmac/src/ble_phy.c @@ -935,6 +935,12 @@ ble_phy_irq_frame_rx_exc_phy_to_idle_4this(void) rf_chan = g_ble_phy_chan_to_rf[g_ble_phy_data.channel]; ble_rf_setup_tx(rf_chan, g_ble_phy_data.phy_mode_tx); g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; + + /* We do not want FIELD/FRAME interrupts until ble_phy_tx() has pushed all + * fields. + */ + NVIC_DisableIRQ(FRAME_IRQn); + NVIC_DisableIRQ(FIELD_IRQn); } static void @@ -1305,6 +1311,9 @@ ble_phy_disable(void) __enable_irq(); + NVIC_EnableIRQ(FRAME_IRQn); + NVIC_EnableIRQ(FIELD_IRQn); + g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; } @@ -1552,8 +1561,6 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) tx_late: STATS_INC(ble_phy_stats, tx_late); ble_phy_disable(); - NVIC_EnableIRQ(FRAME_IRQn); - NVIC_EnableIRQ(FIELD_IRQn); rc = BLE_PHY_ERR_TX_LATE; done: From f75ccfca9a25793de82a552abb13a0ce65b4d37f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 17 Oct 2021 13:09:40 +0200 Subject: [PATCH 106/306] nimble/ll: Fix marking AdvA as resolved when restoring addrd AdvA was resolved only if corresponding flag is set. It's possible to have rpa_index>0 and not resolved AdvA in case AdvA was an identity address but it was added to rl. --- nimble/controller/src/ble_ll_scan.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 9b123622cb..4fdf0f640b 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2439,14 +2439,19 @@ ble_ll_scan_rx_pkt_in_restore_addr_data(struct ble_mbuf_hdr *hdr, addrd->adv_addr_type = addrd->adva_type; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (rxinfo->rpa_index >= 0) { + addrd->rpa_index = rxinfo->rpa_index; + + if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_RESOLVED) { + BLE_LL_ASSERT(rxinfo->rpa_index >= 0); rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; addrd->adv_addr = rl->rl_identity_addr; addrd->adv_addr_type = rl->rl_addr_type; + addrd->adva_resolved = 1; } if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { addrd->targeta = ble_ll_get_our_devaddr(scansm->own_addr_type & 1); addrd->targeta_type = scansm->own_addr_type & 1; + addrd->targeta_resolved = 1; } #endif } From 4d95b1c3ccfdf2d30abc53ac6eeb8b0e7cc6362e Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sun, 17 Oct 2021 12:34:38 +0200 Subject: [PATCH 107/306] nimble/ll: Fix uninitialized members in addr_data --- nimble/controller/src/ble_ll_scan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 4fdf0f640b..9ce7877b10 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2447,11 +2447,16 @@ ble_ll_scan_rx_pkt_in_restore_addr_data(struct ble_mbuf_hdr *hdr, addrd->adv_addr = rl->rl_identity_addr; addrd->adv_addr_type = rl->rl_addr_type; addrd->adva_resolved = 1; + } else { + addrd->adva_resolved = 0; } + if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED) { addrd->targeta = ble_ll_get_our_devaddr(scansm->own_addr_type & 1); addrd->targeta_type = scansm->own_addr_type & 1; addrd->targeta_resolved = 1; + } else { + addrd->targeta_resolved = 0; } #endif } From 2443892ccc707886d04ef2cf802a41a935ec6cfd Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sat, 16 Oct 2021 01:20:00 +0200 Subject: [PATCH 108/306] nimble/ll: Use generic scanner for initiator This moves initiator state handling to generic scanner and removes existing spearate ll_initiating state from LL and associated code. By using generic code we no longer need to worry about maintaining two separate instances of similar code since e.g. privacy and filtering is done via the same code path. Also we no longer need old aux scanner code so all remaining parts of that code can be removed. This saves ~3K of flash (optimized build with all features enabled) and also some RAM (mostly depending on pool size used by old aux scanner). --- nimble/controller/include/controller/ble_ll.h | 1 - .../include/controller/ble_ll_conn.h | 35 +- .../include/controller/ble_ll_scan.h | 84 +- .../include/controller/ble_ll_sched.h | 1 - nimble/controller/src/ble_ll.c | 12 - nimble/controller/src/ble_ll_conn.c | 826 ++--------------- nimble/controller/src/ble_ll_conn_hci.c | 19 +- nimble/controller/src/ble_ll_conn_priv.h | 8 - nimble/controller/src/ble_ll_scan.c | 852 +++--------------- nimble/controller/src/ble_ll_scan_aux.c | 208 ++++- nimble/controller/src/ble_ll_sched.c | 94 -- nimble/include/nimble/ble.h | 3 + 12 files changed, 477 insertions(+), 1666 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index 4a832c6558..556883422c 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -216,7 +216,6 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; #define BLE_LL_STATE_STANDBY (0) #define BLE_LL_STATE_ADV (1) #define BLE_LL_STATE_SCANNING (2) -#define BLE_LL_STATE_INITIATING (3) #define BLE_LL_STATE_CONNECTION (4) #define BLE_LL_STATE_DTM (5) #define BLE_LL_STATE_SYNC (6) diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h index daf7db5848..7be3a43157 100644 --- a/nimble/controller/include/controller/ble_ll_conn.h +++ b/nimble/controller/include/controller/ble_ll_conn.h @@ -225,9 +225,6 @@ struct ble_ll_conn_sm /* RSSI */ int8_t conn_rssi; - /* For privacy */ - int8_t rpa_index; - /* Connection data length management */ uint8_t max_tx_octets; uint8_t max_rx_octets; @@ -328,6 +325,9 @@ struct ble_ll_conn_sm uint8_t own_addr_type; uint8_t peer_addr_type; uint8_t peer_addr[BLE_DEV_ADDR_LEN]; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + uint8_t peer_addr_resolved; +#endif /* * XXX: TODO. Could save memory. Have single event at LL and put these @@ -379,7 +379,6 @@ struct ble_ll_conn_sm /* XXX: for now, just store them all */ struct ble_ll_conn_params conn_cp; - struct ble_ll_scan_sm *scansm; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) struct hci_ext_create_conn initial_params; #endif @@ -426,6 +425,34 @@ uint8_t ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency); void ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, uint32_t *anchor, uint8_t *anchor_usecs); +struct ble_ll_scan_addr_data; +struct ble_ll_scan_pdu_data; + +uint8_t ble_ll_conn_tx_connect_ind_pducb(uint8_t *dptr, void *pducb_arg, + uint8_t *hdr_byte); +void ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm, + struct ble_ll_scan_pdu_data *pdu_data, + uint8_t adva_type, uint8_t *adva, + uint8_t inita_type, uint8_t *inita, + int rpa_index, uint8_t channel); + +/* Send CONNECT_IND/AUX_CONNECT_REQ */ +int ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu, + struct ble_ll_scan_addr_data *addrd, + uint8_t ext); +/* Cancel connection after AUX_CONNECT_REQ was sent */ +void ble_ll_conn_send_connect_req_cancel(void); +/* Signal connection created via CONNECT_IND */ +void ble_ll_conn_created_on_legacy(struct os_mbuf *rxpdu, + struct ble_ll_scan_addr_data *addrd, + uint8_t *targeta); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +/* Signal connection created via AUX_CONNECT_REQ */ +void ble_ll_conn_created_on_aux(struct os_mbuf *rxpdu, + struct ble_ll_scan_addr_data *addrd, + uint8_t *targeta); +#endif + #ifdef __cplusplus } #endif diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index d3097f2b11..eae0c39457 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -89,56 +89,6 @@ struct ble_ll_scan_phy struct ble_ll_scan_timing timing; }; -#define BLE_LL_AUX_HAS_ADVA 0x01 -#define BLE_LL_AUX_HAS_TARGETA 0x02 -#define BLE_LL_AUX_HAS_ADI 0x04 -#define BLE_LL_AUX_IS_MATCHED 0x08 -#define BLE_LL_AUX_IS_TARGETA_RESOLVED 0x10 - -#define BLE_LL_AUX_FLAG_HCI_SENT_ANY 0x02 -#define BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED 0x04 -#define BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED 0x08 -#define BLE_LL_AUX_FLAG_SCAN_COMPLETE 0x10 -#define BLE_LL_AUX_FLAG_SCAN_ERROR 0x20 -#define BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED 0x40 -#define BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED 0x80 - -struct ble_ll_aux_data { - uint8_t flags; - - /* - * Since aux_data can be accessed from ISR and LL, we have separate copies - * of flags to make sure that ISR does not modify flags while LL uses them. - * ISR updates 'flags_isr' and LL adds these to 'flags_ll' which it then - * uses for further processing allowing to update 'flags_isr' if another - * scan for given 'aux_data' is scheduled. Note that flags must not be unset - * while aux_data is valid. - */ - uint8_t flags_isr; - uint8_t flags_ll; - - uint8_t ref_cnt; - uint8_t chan; - uint8_t aux_phy; - uint8_t aux_primary_phy; - uint8_t mode; - uint8_t scanning; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - int8_t rpa_index; -#endif - uint16_t adi; - uint32_t offset; - uint8_t offset_units; - uint8_t adva[6]; - uint8_t adva_type; - uint8_t targeta[6]; - uint8_t targeta_type; - uint16_t evt_type; - struct ble_ll_sched_item sch; - struct ble_hci_ev *evt; - struct ble_npl_event ev; -}; - struct ble_ll_scan_pdu_data { uint8_t hdr_byte; /* ScanA for SCAN_REQ and InitA for CONNECT_IND */ @@ -197,11 +147,13 @@ struct ble_ll_scan_sm #endif uint8_t restart_timer_needed; - struct ble_ll_aux_data *cur_aux_data; struct ble_ll_scan_phy *scanp; struct ble_ll_scan_phy *scanp_next; struct ble_ll_scan_phy scan_phys[BLE_LL_SCAN_PHY_NUMBER]; + + /* Connection sm for initiator scan */ + struct ble_ll_conn_sm *connsm; }; /* Scan types */ @@ -244,13 +196,11 @@ int ble_ll_scan_can_chg_whitelist(void); /* Boolean function returning true if scanning enabled */ int ble_ll_scan_enabled(void); -/* Boolean function returns true if whitelist is enabled for scanning */ -int ble_ll_scan_whitelist_enabled(void); - /* Initialize the scanner when we start initiating */ struct hci_create_conn; -int ble_ll_scan_initiator_start(struct hci_create_conn *hcc, - struct ble_ll_scan_sm **sm); +int +ble_ll_scan_initiator_start(struct hci_create_conn *hcc, + struct ble_ll_conn_sm *connsm); /* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */ struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void); @@ -276,24 +226,14 @@ void ble_ll_scan_wfr_timer_exp(void); /* Called when scan could be interrupted */ void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm); -int ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *ble_hdr, - uint8_t **addr, uint8_t *addr_type, - uint8_t **inita, uint8_t *init_addr_type, - int *ext_mode); - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf, - bool *adva_present); - /* Initialize the extended scanner when we start initiating */ struct hci_ext_create_conn; -int ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, - struct ble_ll_scan_sm **sm); +int +ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, + struct ble_ll_conn_sm *connsm); /* Called to parse extended advertising*/ -struct ble_ll_aux_data *ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_scan); -void ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan); void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data); #endif @@ -316,8 +256,10 @@ int ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, uint8_t ext_adv, void ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, uint8_t ext_adv, uint16_t adi); -int ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, - struct ble_ll_scan_addr_data *addrd, uint8_t *scan_ok); +int +ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, + struct ble_ll_scan_addr_data *addrd, uint8_t *scan_ok); +int ble_ll_scan_rx_check_init(struct ble_ll_scan_addr_data *addrd); #ifdef __cplusplus } diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h index 15f331998c..45e148cbd6 100644 --- a/nimble/controller/include/controller/ble_ll_sched.h +++ b/nimble/controller/include/controller/ble_ll_sched.h @@ -67,7 +67,6 @@ extern uint8_t g_ble_ll_sched_offset_ticks; #define BLE_LL_SCHED_TYPE_ADV (1) #define BLE_LL_SCHED_TYPE_SCAN (2) #define BLE_LL_SCHED_TYPE_CONN (3) -#define BLE_LL_SCHED_TYPE_AUX_SCAN (4) #define BLE_LL_SCHED_TYPE_DTM (5) #define BLE_LL_SCHED_TYPE_PERIODIC (6) #define BLE_LL_SCHED_TYPE_SYNC (7) diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 8c7095a7e1..2702b7c53a 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -677,9 +677,6 @@ ble_ll_wfr_timer_exp(void *arg) case BLE_LL_STATE_SCANNING: ble_ll_scan_wfr_timer_exp(); break; - case BLE_LL_STATE_INITIATING: - ble_ll_conn_init_wfr_timer_exp(); - break; #if MYNEWT_VAL(BLE_LL_DTM) case BLE_LL_STATE_DTM: ble_ll_dtm_wfr_timer_exp(); @@ -842,9 +839,6 @@ ble_ll_rx_pkt_in(void) case BLE_LL_STATE_SCANNING: ble_ll_scan_rx_pkt_in(pdu_type, m, ble_hdr); break; - case BLE_LL_STATE_INITIATING: - ble_ll_init_rx_pkt_in(pdu_type, rxbuf, ble_hdr); - break; #if MYNEWT_VAL(BLE_LL_DTM) case BLE_LL_STATE_DTM: ble_ll_dtm_rx_pkt_in(m, ble_hdr); @@ -980,9 +974,6 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) case BLE_LL_STATE_ADV: rc = ble_ll_adv_rx_isr_start(pdu_type); break; - case BLE_LL_STATE_INITIATING: - rc = ble_ll_init_rx_isr_start(pdu_type, rxhdr); - break; case BLE_LL_STATE_SCANNING: rc = ble_ll_scan_rx_isr_start(pdu_type, &rxhdr->rxinfo.flags); break; @@ -1122,9 +1113,6 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) } rc = ble_ll_scan_rx_isr_end(rxpdu, crcok); break; - case BLE_LL_STATE_INITIATING: - rc = ble_ll_init_rx_isr_end(rxbuf, crcok, rxhdr); - break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_LL_STATE_SCAN_AUX: if (!badpkt) { diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 0f930d94e3..76dd18e4bc 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -674,64 +674,6 @@ ble_ll_conn_wfr_timer_exp(void) STATS_INC(ble_ll_conn_stats, wfr_expirations); } -void -ble_ll_conn_reset_pending_aux_conn_rsp(void) -{ -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - return; -#endif - struct ble_ll_conn_sm *connsm; - - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return; - } - - if (CONN_F_AUX_CONN_REQ(connsm)) { - STATS_INC(ble_ll_stats, aux_conn_rsp_err); - CONN_F_CONN_REQ_TXD(connsm) = 0; - CONN_F_AUX_CONN_REQ(connsm) = 0; - ble_ll_sched_rmv_elem(&connsm->conn_sch); - return; - } - - return; -} - -bool -ble_ll_conn_init_pending_aux_conn_rsp(void) -{ -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - return false; -#endif - struct ble_ll_conn_sm *connsm; - - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return false; - } - - return CONN_F_AUX_CONN_REQ(connsm); -} - -void -ble_ll_conn_init_wfr_timer_exp(void) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_conn_sm *connsm; - - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return; - } - - ble_ll_conn_reset_pending_aux_conn_rsp(); - connsm->inita_identity_used = 0; - - ble_ll_scan_interrupted(connsm->scansm); - -#endif -} /** * Callback for slave when it transmits a data pdu and the connection event * ends after the transmission. @@ -1764,6 +1706,13 @@ void ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, struct hci_ext_conn_params *hcc_params, int phy) { + connsm->slave_latency = hcc_params->conn_latency; + connsm->supervision_tmo = hcc_params->supervision_timeout; + + connsm->conn_itvl = hcc_params->conn_itvl; + connsm->conn_itvl_ticks = hcc_params->conn_itvl_ticks; + connsm->conn_itvl_usecs = hcc_params->conn_itvl_usecs; + /* Check the min/max CE lengths are less than connection interval */ if (hcc_params->min_ce_len > (connsm->conn_itvl * 2)) { connsm->min_ce_len = connsm->conn_itvl * 2; @@ -1833,7 +1782,6 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) connsm->sub_vers_nr = 0; connsm->reject_reason = BLE_ERR_SUCCESS; connsm->conn_rssi = BLE_LL_CONN_UNKNOWN_RSSI; - connsm->rpa_index = -1; connsm->inita_identity_used = 0; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) @@ -2667,8 +2615,8 @@ ble_ll_conn_event_end(struct ble_npl_event *ev) * @param txoffset The tx window offset for this connection */ -static void -ble_ll_conn_connect_ind_prepare(struct ble_ll_conn_sm *connsm, +void +ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm, struct ble_ll_scan_pdu_data *pdu_data, uint8_t adva_type, uint8_t *adva, uint8_t inita_type, uint8_t *inita, @@ -2753,110 +2701,8 @@ ble_ll_conn_connect_ind_prepare(struct ble_ll_conn_sm *connsm, pdu_data->hdr_byte = hdr; } -/* Returns true if the address matches the connection peer address having in - * mind privacy mode - */ -static int -ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva, int index) -{ - int rc; - uint8_t *peer_addr = NULL; - struct ble_ll_conn_sm *connsm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - struct ble_ll_resolv_entry *rl; -#endif - - /* XXX: Deal with different types of random addresses here! */ - connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return 0; - } - - switch (connsm->peer_addr_type) { - /* Fall-through intentional */ - case BLE_HCI_CONN_PEER_ADDR_PUBLIC: - case BLE_HCI_CONN_PEER_ADDR_RANDOM: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (ble_ll_addr_is_id(adva, addr_type)) { - /* Peer uses its identity address. Let's verify privacy mode. - * - * Note: Core Spec 5.0 Vol 6, Part B - * If the Host has added the peer device to the resolving list - * with an all-zero peer IRK, the Controller shall only accept - * the peer's identity address. - */ - if (ble_ll_resolv_enabled()) { - rl = ble_ll_resolv_list_find(adva, addr_type); - if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && - rl->rl_has_peer) { - return 0; - } - } - } - - /* Check if peer uses RPA. If so and it match, use it as controller - * supports privacy mode - */ - if ((index >= 0) && - (g_ble_ll_resolv_list[index].rl_addr_type == connsm->peer_addr_type)) { - peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; - } -#endif - /* - * If we are here it means we don't know the device, lets - * check if type is what we are looking for and later - * if address matches - */ - if ((connsm->peer_addr_type == addr_type) && !peer_addr) { - peer_addr = adva; - } - - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - case BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT: - if ((index < 0) || - (g_ble_ll_resolv_list[index].rl_addr_type != 0)) { - return 0; - } - peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; - break; - case BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT: - if ((index < 0) || - (g_ble_ll_resolv_list[index].rl_addr_type != 1)) { - return 0; - } - peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr; - break; -#endif - default: - peer_addr = NULL; - break; - } - - rc = 0; - if (peer_addr) { - if (!memcmp(peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN)) { - rc = 1; - } - } - - return rc; -} - -static void -ble_ll_conn_connect_ind_txend_to_standby(void *arg) -{ - ble_ll_state_set(BLE_LL_STATE_STANDBY); -} - -static void -ble_ll_conn_connect_ind_txend_to_init(void *arg) -{ - ble_ll_state_set(BLE_LL_STATE_INITIATING); -} - -static uint8_t -ble_ll_conn_connect_ind_tx_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) +uint8_t +ble_ll_conn_tx_connect_ind_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) { struct ble_ll_conn_sm *connsm; struct ble_ll_scan_pdu_data *pdu_data; @@ -2890,30 +2736,6 @@ ble_ll_conn_connect_ind_tx_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_by return 34; } -/** - * Send a connection requestion to an advertiser - * - * Context: Interrupt - * - * @param addr_type Address type of advertiser - * @param adva Address of advertiser - */ -int -ble_ll_conn_connect_ind_send(struct ble_ll_conn_sm *connsm, uint8_t end_trans) -{ - int rc; - - if (end_trans == BLE_PHY_TRANSITION_NONE) { - ble_phy_set_txend_cb(ble_ll_conn_connect_ind_txend_to_standby, NULL); - } else { - ble_phy_set_txend_cb(ble_ll_conn_connect_ind_txend_to_init, NULL); - } - - rc = ble_phy_tx(ble_ll_conn_connect_ind_tx_pducb, connsm, end_trans); - - return rc; -} - /** * Called when a schedule item overlaps the currently running connection * event. This generally should not happen, but if it does we stop the @@ -2933,595 +2755,141 @@ ble_ll_conn_event_halt(void) } } -/** - * Process a received PDU while in the initiating state. - * - * Context: Link Layer task. - * - * @param pdu_type - * @param rxbuf - * @param ble_hdr - */ -void -ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *ble_hdr) +int +ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu, + struct ble_ll_scan_addr_data *addrd, + uint8_t ext) { - uint8_t addr_type; - uint8_t *addr; - uint8_t *adv_addr; - uint8_t *inita; - uint8_t inita_type; struct ble_ll_conn_sm *connsm; - int ext_adv_mode = -1; + struct ble_mbuf_hdr *rxhdr; + int8_t rpa_index; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data = NULL; - - if (ble_hdr->rxinfo.user_data) { - /* aux_data just a local helper, no need to ref - * as ble_hdr->rxinfo.user_data is unref in the end of this function - */ - aux_data = ble_hdr->rxinfo.user_data; - } + struct hci_ext_conn_params *ecp; + uint8_t phy; #endif + int rc; - /* Get the connection state machine we are trying to create */ connsm = g_ble_ll_conn_create_sm; - if (!connsm) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (aux_data) { - ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); - ble_hdr->rxinfo.user_data = NULL; - } -#endif - return; - } - - if (!BLE_MBUF_HDR_CRC_OK(ble_hdr)) { - goto scan_continue; - } + rxhdr = BLE_MBUF_HDR_PTR(rxpdu); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (BLE_MBUF_HDR_AUX_INVALID(ble_hdr)) { - goto scan_continue; - } - - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { - if (BLE_MBUF_HDR_WAIT_AUX(ble_hdr)) { - /* Just continue scanning. We are waiting for AUX */ - if (!ble_ll_sched_aux_scan(ble_hdr, connsm->scansm, aux_data)) { - /* ref for aux ptr in the scheduler */ - ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); - ble_hdr->rxinfo.user_data = NULL; - ble_ll_scan_chk_resume(); - return; - } - goto scan_continue; - } - } - - if (CONN_F_AUX_CONN_REQ(connsm)) { - if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { - /* Wait for connection response, in this point of time aux is NULL */ - BLE_LL_ASSERT(ble_hdr->rxinfo.user_data == NULL); - return; - } + if (ext) { +#if BLE_LL_BT5_PHY_SUPPORTED + phy = rxhdr->rxinfo.phy; +#else + phy = BLE_PHY_1M; +#endif + ecp = &connsm->initial_params.params[phy - 1]; + ble_ll_conn_ext_set_params(connsm, ecp, phy); } #endif - /* If we have sent a connect request, we need to enter CONNECTION state */ - if (connsm && CONN_F_CONN_REQ_TXD(connsm)) { - /* Set address of advertiser to which we are connecting. */ - - if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr, - &adv_addr, &addr_type, - &inita, &inita_type, &ext_adv_mode)) { - /* Something got wrong, keep trying to connect */ - goto scan_continue; - } + if (ble_ll_sched_master_new(connsm, rxhdr, 0)) { + return -1; + } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* - * Did we resolve this address? If so, set correct peer address - * and peer address type. - */ - if (connsm->rpa_index >= 0) { - addr_type = g_ble_ll_resolv_list[connsm->rpa_index].rl_addr_type + 2; - addr = g_ble_ll_resolv_list[connsm->rpa_index].rl_identity_addr; - } else { - addr = adv_addr; - } + rpa_index = addrd->rpa_index; #else - addr = adv_addr; + rpa_index = -1; #endif + ble_ll_conn_prepare_connect_ind(connsm, ble_ll_scan_get_pdu_data(), + addrd->adva_type, addrd->adva, + addrd->targeta_type, addrd->targeta, + rpa_index, rxhdr->rxinfo.channel); - if (connsm->rpa_index >= 0) { - connsm->peer_addr_type = addr_type; - memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN); - - ble_ll_scan_set_peer_rpa(adv_addr); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* Update resolving list with current peer RPA */ - ble_ll_resolv_set_peer_rpa(connsm->rpa_index, rxbuf + BLE_LL_PDU_HDR_LEN); - if (ble_ll_is_rpa(inita, inita_type)) { - ble_ll_resolv_set_local_rpa(connsm->rpa_index, inita); - } - -#endif - } else if (ble_ll_scan_whitelist_enabled()) { - /* if WL is used we need to store peer addr also if it was not - * resolved - */ - connsm->peer_addr_type = addr_type; - memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN); - } - - /* Connection has been created. Stop scanning */ - g_ble_ll_conn_create_sm = NULL; - ble_ll_scan_sm_stop(0); - - /* For AUX Connect CSA2 is mandatory. Otherwise we need to check bit - * mask - */ - if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { - ble_ll_conn_set_csa(connsm, 1); - } else { - ble_ll_conn_set_csa(connsm, rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK); - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - /* Lets take last used phy */ - ble_ll_conn_init_phy(connsm, ble_hdr->rxinfo.phy); -#endif - if (aux_data) { - ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); - ble_hdr->rxinfo.user_data = NULL; - } -#endif - ble_ll_conn_created(connsm, NULL); - return; + ble_phy_set_txend_cb(NULL, NULL); + rc = ble_phy_tx(ble_ll_conn_tx_connect_ind_pducb, connsm, + ext ? BLE_PHY_TRANSITION_TX_RX : BLE_PHY_TRANSITION_NONE); + if (rc) { + ble_ll_conn_send_connect_req_cancel(); + return -1; } -scan_continue: -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* Drop last reference and keep continue to connect */ - if (aux_data) { - ble_ll_scan_aux_data_unref(ble_hdr->rxinfo.user_data); - ble_hdr->rxinfo.user_data = NULL; - } -#endif - ble_ll_scan_chk_resume(); + return 0; } -/** - * Called when a receive PDU has started and we are in the initiating state. - * - * Context: Interrupt - * - * @param pdu_type - * @param ble_hdr - * - * @return int - * 0: we will not attempt to reply to this frame - * 1: we may send a response to this frame. - */ -int -ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr) +void +ble_ll_conn_send_connect_req_cancel(void) { struct ble_ll_conn_sm *connsm; connsm = g_ble_ll_conn_create_sm; - if (!connsm) { - return 0; - } - - if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || - (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND || - pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP)) { - return 1; - } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && - connsm->scansm->ext_scanning) { - if (connsm->scansm->cur_aux_data) { - STATS_INC(ble_ll_stats, aux_received); - } - - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_EXT_ADV; - return 1; - } -#endif - - return 0; + ble_ll_sched_rmv_elem(&connsm->conn_sch); } -/** - * Called when a receive PDU has ended and we are in the initiating state. - * - * Context: Interrupt - * - * @param rxpdu - * @param crcok - * @param ble_hdr - * - * @return int - * < 0: Disable the phy after reception. - * == 0: Success. Do not disable the PHY. - * > 0: Do not disable PHY as that has already been done. - */ -int -ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, - struct ble_mbuf_hdr *ble_hdr) +static void +ble_ll_conn_master_start(uint8_t phy, uint8_t csa, + struct ble_ll_scan_addr_data *addrd, uint8_t *targeta) { - int rc; - int resolved; - int chk_wl; - int index; - uint8_t pdu_type; - uint8_t adv_addr_type; - uint8_t peer_addr_type; - uint8_t *adv_addr = NULL; - uint8_t *peer; - uint8_t *init_addr = NULL; - uint8_t init_addr_type; - uint8_t pyld_len; - uint8_t inita_is_rpa; - uint8_t conn_req_end_trans; - struct os_mbuf *rxpdu; struct ble_ll_conn_sm *connsm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - struct ble_ll_resolv_entry *rl; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct hci_ext_conn_params *hcp; - struct ble_ll_scan_sm *scansm; - uint8_t phy; -#endif - int ext_adv_mode = -1; - /* Get connection state machine to use if connection to be established */ connsm = g_ble_ll_conn_create_sm; - /* This could happen if connection init was cancelled while isr end was - * already pending - */ - if (!connsm) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - return -1; - } - - rc = -1; - pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; - pyld_len = rxbuf[1]; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - scansm = connsm->scansm; - if (scansm->cur_aux_data) { - ble_hdr->rxinfo.user_data = scansm->cur_aux_data; - scansm->cur_aux_data = NULL; - } -#endif - - if (!crcok) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* Invalid packet - make sure we do not wait for AUX_CONNECT_RSP */ - ble_ll_conn_reset_pending_aux_conn_rsp(); -#endif - - /* Ignore this packet */ - goto init_rx_isr_exit; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* If we sent AUX_CONNECT_REQ, we only expect AUX_CONNECT_RSP here */ - if (CONN_F_AUX_CONN_REQ(connsm)) { - if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { - STATS_INC(ble_ll_stats, aux_conn_rsp_err); - CONN_F_CONN_REQ_TXD(connsm) = 0; - CONN_F_AUX_CONN_REQ(connsm) = 0; - ble_ll_sched_rmv_elem(&connsm->conn_sch); - } - goto init_rx_isr_exit; - } -#endif - - inita_is_rpa = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { - if (!scansm->ext_scanning) { - goto init_rx_isr_exit; - } - - rc = ble_ll_scan_update_aux_data(ble_hdr, rxbuf, NULL); - if (rc < 0) { - /* No memory or broken packet */ - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID; - goto init_rx_isr_exit; - } - } -#endif - - /* Lets get addresses from advertising report*/ - if (ble_ll_scan_adv_decode_addr(pdu_type, rxbuf, ble_hdr, - &adv_addr, &adv_addr_type, - &init_addr, &init_addr_type, - &ext_adv_mode)) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_INVALID; -#endif - goto init_rx_isr_exit; - } - - switch (pdu_type) { - case BLE_ADV_PDU_TYPE_ADV_IND: - break; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_ADV_PDU_TYPE_ADV_EXT_IND: - rc = -1; - - /* If this is not connectable adv mode, lets skip it */ - if (!(ext_adv_mode & BLE_LL_EXT_ADV_MODE_CONN)) { - goto init_rx_isr_exit; - } - - if (!adv_addr) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT; - goto init_rx_isr_exit; - } - - if (!init_addr) { - break; - } - /* if there is direct address lets fall down and check it.*/ - // no break -#endif - case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: - inita_is_rpa = (uint8_t)ble_ll_is_rpa(init_addr, init_addr_type); - if (!inita_is_rpa) { - - /* Resolving will be done later. Check if identity InitA matches */ - if (!ble_ll_is_our_devaddr(init_addr, init_addr_type)) { - goto init_rx_isr_exit; - } - } -#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - else { - /* If privacy is off - reject RPA InitA*/ - goto init_rx_isr_exit; - } -#endif - - break; - default: - goto init_rx_isr_exit; - } - - /* Should we send a connect request? */ - index = -1; - peer = adv_addr; - peer_addr_type = adv_addr_type; + g_ble_ll_conn_create_sm = NULL; - resolved = 0; - chk_wl = ble_ll_scan_whitelist_enabled(); + connsm->peer_addr_type = addrd->adv_addr_type; + memcpy(connsm->peer_addr, addrd->adv_addr, 6); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (ble_ll_is_rpa(adv_addr, adv_addr_type) && ble_ll_resolv_enabled()) { - index = ble_hw_resolv_list_match(); - if (index >= 0) { - rl = &g_ble_ll_resolv_list[index]; - - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED; - connsm->rpa_index = index; - peer = rl->rl_identity_addr; - peer_addr_type = rl->rl_addr_type; - resolved = 1; - - /* Assure privacy */ - if ((rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && init_addr && - !inita_is_rpa && rl->rl_has_local) { - goto init_rx_isr_exit; - } - - /* - * If the InitA is a RPA, we must see if it resolves based on the - * identity address of the resolved ADVA. - */ - if (init_addr && inita_is_rpa) { - if (!ble_ll_resolv_rpa(init_addr, - g_ble_ll_resolv_list[index].rl_local_irk)) { - goto init_rx_isr_exit; - } - - /* Core Specification Vol 6, Part B, Section 6.4: - * "The Link Layer should not set the InitA field to the same - * value as the TargetA field in the received advertising PDU." - * - * We update the received PDU directly here, so ble_ll_init_rx_pkt_in - * can process it as is. - */ - memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN); - } - - } else { - if (chk_wl) { - goto init_rx_isr_exit; - } - - /* Could not resolved InitA */ - if (init_addr && inita_is_rpa) { - goto init_rx_isr_exit; - } - } - } else if (init_addr) { - - /* If resolving is off and InitA is RPA we reject advertising */ - if (inita_is_rpa && !ble_ll_resolv_enabled()) { - goto init_rx_isr_exit; - } - - /* Let's see if we have IRK with that peer.*/ - rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type); - - /* Lets make sure privacy mode is correct together with InitA in case it - * is identity address - */ - if (rl && !inita_is_rpa && - (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) && - rl->rl_has_local) { - goto init_rx_isr_exit; - } - - /* - * If the InitA is a RPA, we must see if it resolves based on the - * identity address of the resolved ADVA. - */ - if (inita_is_rpa) { - if (!rl || !ble_ll_resolv_rpa(init_addr, rl->rl_local_irk)) { - goto init_rx_isr_exit; - } - - /* Core Specification Vol 6, Part B, Section 6.4: - * "The Link Layer should not set the InitA field to the same - * value as the TargetA field in the received advertising PDU." - * - * We update the received PDU directly here, so ble_ll_init_rx_pkt_in - * can process it as is. - */ - 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 - - /* Check filter policy */ - if (chk_wl) { - if (!ble_ll_whitelist_match(peer, peer_addr_type, resolved)) { - goto init_rx_isr_exit; - } + if (addrd->adva_resolved) { + BLE_LL_ASSERT(addrd->rpa_index >= 0); + connsm->peer_addr_resolved = 1; + ble_ll_resolv_set_peer_rpa(addrd->rpa_index, addrd->adva); + ble_ll_scan_set_peer_rpa(addrd->adva); } else { - /* Must match the connection address */ - if (!ble_ll_conn_is_peer_adv(adv_addr_type, adv_addr, index)) { - goto init_rx_isr_exit; - } + connsm->peer_addr_resolved = 0; } - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH; - - /* For CONNECT_IND we don't go into RX state */ - conn_req_end_trans = BLE_PHY_TRANSITION_NONE; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* Check if we should send AUX_CONNECT_REQ and wait for AUX_CONNECT_RSP */ - if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { - conn_req_end_trans = BLE_PHY_TRANSITION_TX_RX; - } - - if (connsm->scansm->ext_scanning) { - phy = ble_hdr->rxinfo.phy; - - hcp = &connsm->initial_params.params[phy - 1]; - connsm->slave_latency = hcp->conn_latency; - connsm->supervision_tmo = hcp->supervision_timeout; - - connsm->conn_itvl = hcp->conn_itvl; - connsm->conn_itvl_ticks = hcp->conn_itvl_ticks; - connsm->conn_itvl_usecs = hcp->conn_itvl_usecs; + if (addrd->targeta_resolved) { + BLE_LL_ASSERT(addrd->rpa_index >= 0); + BLE_LL_ASSERT(targeta); + ble_ll_resolv_set_local_rpa(addrd->rpa_index, targeta); } #endif - /* Schedule new connection */ - if (ble_ll_sched_master_new(connsm, ble_hdr, pyld_len)) { - STATS_INC(ble_ll_conn_stats, cant_set_sched); - goto init_rx_isr_exit; - } - - /* Prepare data for connect request */ - ble_ll_conn_connect_ind_prepare(connsm, - ble_ll_scan_get_pdu_data(), - adv_addr_type, adv_addr, - init_addr_type, init_addr, - index, ble_hdr->rxinfo.channel); + ble_ll_conn_set_csa(connsm, csa); +#if BLE_LL_BT5_PHY_SUPPORTED + ble_ll_conn_init_phy(connsm, phy); +#endif + ble_ll_conn_created(connsm, NULL); +} - /* Setup to transmit the connect request */ - rc = ble_ll_conn_connect_ind_send(connsm, conn_req_end_trans); - if (rc) { - ble_ll_sched_rmv_elem(&connsm->conn_sch); - goto init_rx_isr_exit; - } +void +ble_ll_conn_created_on_legacy(struct os_mbuf *rxpdu, + struct ble_ll_scan_addr_data *addrd, + uint8_t *targeta) +{ + uint8_t *rxbuf; + uint8_t csa; - if (init_addr && !inita_is_rpa) { - connsm->inita_identity_used = 1; - } + rxbuf = rxpdu->om_data; + csa = rxbuf[0] & BLE_ADV_PDU_HDR_CHSEL_MASK; - CONN_F_CONN_REQ_TXD(connsm) = 1; + ble_ll_conn_master_start(BLE_PHY_1M, csa, addrd, targeta); +} #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { - /* Lets wait for AUX_CONNECT_RSP */ - CONN_F_AUX_CONN_REQ(connsm) = 1; - /* Keep aux data until we get scan response */ - scansm->cur_aux_data = ble_hdr->rxinfo.user_data; - ble_hdr->rxinfo.user_data = NULL; - STATS_INC(ble_ll_stats, aux_conn_req_tx); - } - - if (connsm->scansm->ext_scanning) { - phy = ble_hdr->rxinfo.phy; - - /* Update connection state machine with appropriate parameters for - * certain PHY - */ - ble_ll_conn_ext_set_params(connsm, - &connsm->initial_params.params[phy - 1], - phy); - - } +void +ble_ll_conn_created_on_aux(struct os_mbuf *rxpdu, + struct ble_ll_scan_addr_data *addrd, + uint8_t *targeta) +{ +#if BLE_LL_BT5_PHY_SUPPORTED + struct ble_mbuf_hdr *rxhdr; #endif + uint8_t phy; - STATS_INC(ble_ll_conn_stats, conn_req_txd); - -init_rx_isr_exit: - - /* - * We have to restart receive if we cant hand up pdu. We return 0 so that - * the phy does not get disabled. - */ - rxpdu = ble_ll_rxpdu_alloc(pyld_len + BLE_LL_PDU_HDR_LEN); - if (rxpdu == NULL) { - /* - * XXX: possible allocate the PDU when we start initiating? - * I cannot say I like this solution, but if we cannot allocate a PDU - * to hand up to the LL, we need to remove the connection we just - * scheduled since the connection state machine will not get processed - * by link layer properly. For now, just remove it from the scheduler - */ - if (CONN_F_CONN_REQ_TXD(connsm) == 1) { - CONN_F_CONN_REQ_TXD(connsm) = 0; - CONN_F_AUX_CONN_REQ(connsm) = 0; - ble_ll_sched_rmv_elem(&connsm->conn_sch); - } - ble_phy_restart_rx(); - rc = 0; - } else { - ble_phy_rxpdu_copy(rxbuf, rxpdu); - ble_ll_rx_pdu_in(rxpdu); - } - - if (rc) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } +#if BLE_LL_BT5_PHY_SUPPORTED + rxhdr = BLE_MBUF_HDR_PTR(rxpdu); + phy = rxhdr->rxinfo.phy; +#else + phy = BLE_PHY_1M; +#endif - return rc; + ble_ll_conn_master_start(phy, 1, addrd, targeta); } +#endif /* BLE_LL_CFG_FEAT_LL_EXT_ADV */ /** * Function called when a timeout has occurred for a connection. There are diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index fe384c4147..e53918f96c 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -179,13 +179,12 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, memcpy(enh_ev->local_rpa, rpa, BLE_DEV_ADDR_LEN); } - /* We need to adjust peer type if device connected using RPA - * and was resolved since RPA needs to be added to HCI event. - */ - if (connsm->peer_addr_type < BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT - && (connsm->rpa_index > -1)) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* Adjust address type if peer address was resolved */ + if (connsm->peer_addr_resolved) { enh_ev->peer_addr_type += 2; } +#endif if (enh_ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { @@ -220,10 +219,6 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, ev->conn_handle = htole16(connsm->conn_handle); ev->role = connsm->conn_role - 1; ev->peer_addr_type = connsm->peer_addr_type; - - if (ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { - ev->peer_addr_type -= 2; - } memcpy(ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN); ev->conn_itvl = htole16(connsm->conn_itvl); ev->conn_latency = htole16(connsm->slave_latency); @@ -520,7 +515,7 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) /* CSA will be selected when advertising is received */ /* Start scanning */ - rc = ble_ll_scan_initiator_start(&hcc, &connsm->scansm); + rc = ble_ll_scan_initiator_start(&hcc, connsm); if (rc) { SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); @@ -777,10 +772,8 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) ble_ll_conn_ext_master_init(connsm, &hcc); ble_ll_conn_sm_new(connsm); - /* CSA will be selected when advertising is received */ - /* Start scanning */ - rc = ble_ll_scan_ext_initiator_start(&hcc, &connsm->scansm); + rc = ble_ll_scan_ext_initiator_start(&hcc, connsm); if (rc) { SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h index 915a4d2a62..099ce77f50 100644 --- a/nimble/controller/src/ble_ll_conn_priv.h +++ b/nimble/controller/src/ble_ll_conn_priv.h @@ -148,18 +148,10 @@ void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len); int ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa); int ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); void ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr); -void ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *ble_hdr); -int ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr); -int ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok, - struct ble_mbuf_hdr *ble_hdr); void ble_ll_conn_wfr_timer_exp(void); -void ble_ll_conn_init_wfr_timer_exp(void); int ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2); uint32_t ble_ll_conn_get_ce_end_time(void); void ble_ll_conn_event_halt(void); -void ble_ll_conn_reset_pending_aux_conn_rsp(void); -bool ble_ll_conn_init_pending_aux_conn_rsp(void); /* HCI */ void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason); diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 9ce7877b10..0d9d36f666 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -25,7 +25,6 @@ #include "os/os.h" #include "os/os_cputime.h" #include "nimble/ble.h" -#include "nimble/nimble_opt.h" #include "nimble/hci_common.h" #include "nimble/ble_hci_trans.h" #include "controller/ble_phy.h" @@ -129,122 +128,9 @@ static struct os_mempool g_scan_dup_pool; static TAILQ_HEAD(ble_ll_scan_dup_list, ble_ll_scan_dup_entry) g_scan_dup_list; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#if MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT) != 0 -static os_membuf_t ext_scan_aux_mem[ OS_MEMPOOL_SIZE( - MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT), - sizeof (struct ble_ll_aux_data)) -]; -#else -#define ext_scan_aux_mem NULL -#endif - -static struct os_mempool ext_scan_aux_pool; - -static int ble_ll_scan_start(struct ble_ll_scan_sm *scansm, - struct ble_ll_sched_item *sch); - -static void -ble_ll_aux_scan_drop_event_cb(struct ble_npl_event *ev) -{ - struct ble_ll_aux_data *aux_data = ble_npl_event_get_arg(ev); - - ble_ll_scan_end_adv_evt(aux_data); - ble_ll_scan_aux_data_unref(aux_data); -} - -static void -ble_ll_aux_scan_drop(struct ble_ll_aux_data *aux_data) -{ - BLE_LL_ASSERT(aux_data); - - STATS_INC(ble_ll_stats, aux_scan_drop); - - ble_npl_event_init(&aux_data->ev, ble_ll_aux_scan_drop_event_cb, aux_data); - ble_ll_event_send(&aux_data->ev); -} - -static int -ble_ll_aux_scan_cb(struct ble_ll_sched_item *sch) -{ - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - uint8_t lls = ble_ll_state_get(); - uint32_t wfr_usec; - - STATS_INC(ble_ll_stats, aux_sched_cb); - - /* Drop the scheduled item if scan was disable or there is aux or scan - * response pending - */ - if (!scansm->scan_enabled || scansm->cur_aux_data || - scansm->scan_rsp_pending) { - ble_ll_aux_scan_drop(sch->cb_arg); - sch->cb_arg = NULL; - goto done; - } - - /* Check if there is no aux connect sent. If so drop the sched item */ - if (lls == BLE_LL_STATE_INITIATING && ble_ll_conn_init_pending_aux_conn_rsp()) { - ble_ll_aux_scan_drop(sch->cb_arg); - sch->cb_arg = NULL; - goto done; - } - - /* This function is called only when scanner is running. This can happen - * in 3 states: - * BLE_LL_STATE_SCANNING - * BLE_LL_STATE_INITIATING - * BLE_LL_STATE_STANDBY - */ - if (lls != BLE_LL_STATE_STANDBY) { - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - - /* When doing RX for AUX pkt, cur_aux_data keeps valid aux data */ - scansm->cur_aux_data = sch->cb_arg; - sch->cb_arg = NULL; - BLE_LL_ASSERT(scansm->cur_aux_data != NULL); - scansm->cur_aux_data->scanning = 1; - - if (ble_ll_scan_start(scansm, sch)) { - ble_ll_scan_interrupted(scansm); - goto done; - } - - STATS_INC(ble_ll_stats, aux_fired_for_read); - - wfr_usec = scansm->cur_aux_data->offset_units ? 300 : 30; - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_usec); - -done: - - return BLE_LL_SCHED_STATE_DONE; -} - static int -ble_ll_scan_ext_adv_init(struct ble_ll_aux_data **aux_data) -{ - struct ble_ll_aux_data *e; - - e = os_memblock_get(&ext_scan_aux_pool); - if (!e) { - return -1; - } - - memset(e, 0, sizeof(*e)); - e->sch.sched_cb = ble_ll_aux_scan_cb; - e->sch.sched_type = BLE_LL_SCHED_TYPE_AUX_SCAN; - e->ref_cnt = 1; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - e->rpa_index = -1; -#endif - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t)e, e->ref_cnt); - - *aux_data = e; - STATS_INC(ble_ll_stats, aux_allocated); +ble_ll_scan_start(struct ble_ll_scan_sm *scansm); - return 0; -} #endif static inline uint32_t @@ -481,28 +367,11 @@ ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data) } #endif -static void -ble_ll_scan_clean_cur_aux_data(void) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - - /* If scanner was reading aux ptr, we need to clean it up */ - if (scansm->cur_aux_data) { - ble_ll_scan_end_adv_evt(scansm->cur_aux_data); - ble_ll_scan_aux_data_unref(scansm->cur_aux_data); - scansm->cur_aux_data = NULL; - } -#endif -} - void ble_ll_scan_halt(void) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - ble_ll_scan_clean_cur_aux_data(); - /* Update backoff if we failed to receive scan response */ if (scansm->scan_rsp_pending) { scansm->scan_rsp_pending = 0; @@ -859,27 +728,6 @@ goto done; } } -static void -ble_ll_get_chan_to_scan(struct ble_ll_scan_sm *scansm, uint8_t *chan, - int *phy) -{ - struct ble_ll_scan_phy *scanp = scansm->scanp; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data = scansm->cur_aux_data; - - if (!scansm->ext_scanning || !aux_data || !aux_data->scanning) { - *chan = scanp->scan_chan; - *phy = scanp->phy; - return; - } - - *chan = aux_data->chan; - *phy = aux_data->aux_phy; -#else - *chan = scanp->scan_chan; - *phy = scanp->phy; -#endif -} /** * Called to enable the receiver for scanning. * @@ -890,29 +738,21 @@ ble_ll_get_chan_to_scan(struct ble_ll_scan_sm *scansm, uint8_t *chan, * @return int */ static int -ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch) +ble_ll_scan_start(struct ble_ll_scan_sm *scansm) { int rc; struct ble_ll_scan_phy *scanp = scansm->scanp; - uint8_t scan_chan; + uint8_t chan; #if (BLE_LL_BT5_PHY_SUPPORTED == 1) uint8_t phy_mode; -#endif int phy; +#endif BLE_LL_ASSERT(scansm->scan_rsp_pending == 0); - ble_ll_get_chan_to_scan(scansm, &scan_chan, &phy); - - /* XXX: right now scheduled item is only present if we schedule for aux - * scan just make sanity check that we have proper combination of - * sch and resulting scan_chan - */ - BLE_LL_ASSERT(!sch || scan_chan < BLE_PHY_ADV_CHAN_START); - BLE_LL_ASSERT(sch || scan_chan >= BLE_PHY_ADV_CHAN_START); - /* Set channel */ - rc = ble_phy_setchan(scan_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); + chan = scanp->scan_chan; + rc = ble_phy_setchan(chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); BLE_LL_ASSERT(rc == 0); /* @@ -934,20 +774,13 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch) #endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) + phy = scanp->phy; phy_mode = ble_ll_phy_to_phy_mode(phy, BLE_HCI_LE_PHY_CODED_ANY); ble_phy_mode_set(phy_mode, phy_mode); #endif - /* XXX: probably need to make sure hfxo is running too */ - /* XXX: can make this better; want to just start asap. */ - if (sch) { - rc = ble_phy_rx_set_start_time(sch->start_time + - g_ble_ll_sched_offset_ticks, - sch->remainder); - } else { - rc = ble_phy_rx_set_start_time(os_cputime_get32() + - g_ble_ll_sched_offset_ticks, 0); - } + rc = ble_phy_rx_set_start_time(os_cputime_get32() + + g_ble_ll_sched_offset_ticks, 0); if (!rc || rc == BLE_PHY_ERR_RX_LATE) { /* If we are late here, it is still OK because we keep scanning. * Clear error @@ -961,12 +794,7 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch) ble_ll_whitelist_disable(); } - /* Set link layer state to scanning */ - if (scanp->scan_type == BLE_SCAN_TYPE_INITIATE) { - ble_ll_state_set(BLE_LL_STATE_INITIATING); - } else { - ble_ll_state_set(BLE_LL_STATE_SCANNING); - } + ble_ll_state_set(BLE_LL_STATE_SCANNING); } return rc; @@ -1020,76 +848,6 @@ ble_ll_scan_is_inside_window(struct ble_ll_scan_phy *scanp, uint32_t time) CPUTIME_LT(time, start_time + scanp->timing.window); } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_scan_aux_data_free(struct ble_ll_aux_data *aux_data) -{ - if (aux_data) { - if (aux_data->evt) { - ble_hci_trans_buf_free((uint8_t *)aux_data->evt); - aux_data->evt = NULL; - } - os_memblock_put(&ext_scan_aux_pool, aux_data); - STATS_INC(ble_ll_stats, aux_freed); - } -} - -struct ble_ll_aux_data * -ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_data) -{ - os_sr_t sr; - - BLE_LL_ASSERT(aux_data); - - OS_ENTER_CRITICAL(sr); - aux_data->ref_cnt++; - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_REF, (uint32_t) aux_data, aux_data->ref_cnt); - - OS_EXIT_CRITICAL(sr); - - return aux_data; -} - -void -ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_data) -{ - os_sr_t sr; - - BLE_LL_ASSERT(aux_data); - - OS_ENTER_CRITICAL(sr); - aux_data->ref_cnt--; - ble_ll_trace_u32x2(BLE_LL_TRACE_ID_AUX_UNREF, (uint32_t) aux_data, aux_data->ref_cnt); - - if (aux_data->ref_cnt == 0) { - /* - * Some validation to make sure that we completed scan properly: - * - we either did not send any report or sent completed/truncated - * - we only sent one of completed/truncated - * - in case of error, we wither did not send anything or sent truncated - */ - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || - ((aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) && - (aux_data->flags_ll & (BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED | BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)))); - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED) || !(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); - BLE_LL_ASSERT(!(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) || - !(aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_ANY) || - (aux_data->flags_ll & BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED)); - - ble_ll_scan_aux_data_free(aux_data); - } - - OS_EXIT_CRITICAL(sr); -} - -static void -ble_ll_scan_sched_remove(struct ble_ll_sched_item *sch) -{ - ble_ll_scan_end_adv_evt(sch->cb_arg); - ble_ll_scan_aux_data_unref(sch->cb_arg); - sch->cb_arg = NULL; -} -#endif /** * Stop the scanning state machine */ @@ -1109,8 +867,7 @@ ble_ll_scan_sm_stop(int 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)) { + if (lls == BLE_LL_STATE_SCANNING) { /* Disable phy */ ble_phy_disable(); @@ -1122,6 +879,8 @@ ble_ll_scan_sm_stop(int chk_disable) OS_ENTER_CRITICAL(sr); + scansm->connsm = NULL; + /* Disable scanning state machine */ scansm->scan_enabled = 0; scansm->restart_timer_needed = 0; @@ -1129,8 +888,6 @@ ble_ll_scan_sm_stop(int chk_disable) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (scansm->ext_scanning) { ble_ll_sched_rmv_elem_type(BLE_LL_SCHED_TYPE_SCAN_AUX, ble_ll_scan_aux_sched_remove); - ble_ll_scan_clean_cur_aux_data(); - ble_ll_sched_rmv_elem_type(BLE_LL_SCHED_TYPE_AUX_SCAN, ble_ll_scan_sched_remove); scansm->ext_scanning = 0; } #endif @@ -1209,45 +966,15 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm) return BLE_ERR_SUCCESS; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_aux_scan_rsp_failed(struct ble_ll_scan_sm *scansm) -{ - if (!scansm->cur_aux_data) { - return; - } - - STATS_INC(ble_ll_stats, aux_scan_rsp_err); - ble_ll_scan_interrupted(scansm); -} -#endif - static void ble_ll_scan_interrupted_event_cb(struct ble_npl_event *ev) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct ble_ll_aux_data *aux_data; -#endif if (!scansm->scan_enabled) { return; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - aux_data = ble_npl_event_get_arg(ev); - - if (aux_data) { - if (scansm->scan_rsp_pending) { - STATS_INC(ble_ll_stats, aux_scan_rsp_err); - } - ble_ll_scan_end_adv_evt(aux_data); - ble_ll_scan_aux_data_unref(aux_data); - ble_npl_event_set_arg(ev, NULL); - STATS_INC(ble_ll_stats, aux_missed_adv); - } -#endif - /* * If we timed out waiting for a response, the scan response pending * flag should be set. Deal with scan backoff. Put device back into rx. @@ -1301,7 +1028,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev) return; } - if (scansm->cur_aux_data || scansm->scan_rsp_pending) { + if (scansm->scan_rsp_pending) { /* Aux scan in progress. Wait */ STATS_INC(ble_ll_stats, scan_timer_stopped); scansm->restart_timer_needed = 1; @@ -1366,15 +1093,6 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev) case BLE_LL_STATE_SCAN_AUX: start_scan = false; break; - case BLE_LL_STATE_INITIATING: - /* Must disable PHY since we will move to a new channel */ - ble_phy_disable(); - if (!inside_window) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - } - /* PHY is disabled - make sure we do not wait for AUX_CONNECT_RSP */ - ble_ll_conn_reset_pending_aux_conn_rsp(); - break; case BLE_LL_STATE_SCANNING: /* Must disable PHY since we will move to a new channel */ ble_phy_disable(); @@ -1390,7 +1108,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev) } if (start_scan) { - ble_ll_scan_start(scansm, NULL); + ble_ll_scan_start(scansm); } else { ble_ll_rfmgmt_release(); } @@ -1440,10 +1158,6 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags) } #endif - if (scansm->cur_aux_data && !scansm->scan_rsp_pending ) { - STATS_INC(ble_ll_stats, aux_received); - } - /* * If this is the first PDU after we sent the scan response (as * denoted by the scan rsp pending flag), we set a bit in the ble @@ -1460,9 +1174,6 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags) *rxflags |= BLE_MBUF_HDR_F_SCAN_RSP_RXD; } else { ble_ll_scan_req_backoff(scansm, 0); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_ll_aux_scan_rsp_failed(scansm); -#endif } } break; @@ -1473,326 +1184,24 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags) } break; #endif - default: - break; - } - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static uint8_t -ble_ll_ext_adv_phy_mode_to_local_phy(uint8_t adv_phy_mode) -{ - switch (adv_phy_mode) { - case 0x00: - return BLE_PHY_1M; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case 0x01: - return BLE_PHY_2M; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case 0x02: - return BLE_PHY_CODED; -#endif - } - - return 0; -} - -static int -ble_ll_ext_scan_parse_aux_ptr(struct ble_ll_aux_data *aux_data, uint8_t *buf) -{ - uint32_t aux_ptr_field = get_le32(buf) & 0x00FFFFFF; - - aux_data->chan = (aux_ptr_field) & 0x3F; - if (aux_data->chan >= BLE_PHY_NUM_DATA_CHANS) { - return -1; - } - - /* TODO use CA aux_ptr_field >> 6 */ - - aux_data->offset = 30 * ((aux_ptr_field >> 8) & 0x1FFF); - - if ((aux_ptr_field >> 7) & 0x01) { - aux_data->offset *= 10; - aux_data->offset_units = 1; - } - - if (aux_data->offset < BLE_LL_MAFS) { - return -1; - } - - aux_data->aux_phy = - ble_ll_ext_adv_phy_mode_to_local_phy((aux_ptr_field >> 21) & 0x07); - if (aux_data->aux_phy == 0) { - return -1; - } - - return 0; -} - -/** - * ble_ll_scan_update_aux_data - * - * Update aux_data stored in ble_hdr.rxinfo.user_data. If no aux_data is present - * (i.e. processing ADV_EXT_IND) this will try to allocate new aux_data. - * - * Context: Interrupt - * - * @param ble_hdr - * @param rxbuf - * - * @return int - * 1: do not scan for next AUX (no AuxPtr or malformed data) - * 0: scan for next AUX (valid AuxPtr found) - * -1: error - */ -int -ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf, - bool *adva_present) -{ - uint8_t pdu_hdr; - uint8_t pdu_len; - uint8_t adv_mode; - uint8_t eh_len; - uint8_t eh_flags; - uint8_t *eh; - struct ble_ll_aux_data *aux_data; - bool is_aux; - - aux_data = ble_hdr->rxinfo.user_data; - /* aux_data is initially not set only for ADV_EXT_IND */ - is_aux = aux_data; - - pdu_hdr = rxbuf[0]; - pdu_len = rxbuf[1]; - - /* PDU without at least Extended Header Length is invalid */ - if (pdu_len == 0) { - return -1; - } - - adv_mode = rxbuf[2] >> 6; - eh_len = rxbuf[2] & 0x3f; - eh_flags = rxbuf[3]; - eh = &rxbuf[4]; - - /* - * PDU without Extended Header is valid in case of last AUX_CHAIN_IND in - * chain so aux_data has to be set and advertising mode has to be 00b, - * otherwise it's an invalid PDU. - */ - if (eh_len == 0) { - if (!aux_data || adv_mode) { - return -1; - } - aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_COMPLETE; - return 1; - } - - /* - * If aux_data is not set, this is ADV_EXT_IND which starts new extended - * advertising event. - */ - if (!aux_data) { - if (ble_ll_scan_ext_adv_init(&aux_data)) { - return -1; - } - - aux_data->aux_primary_phy = ble_hdr->rxinfo.phy; - } else { - if (aux_data->flags_isr & BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED) { - aux_data->flags_isr |= BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED; - } else { - aux_data->flags_isr |= BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED; - } - } - - /* Now parse extended header... */ - - if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - aux_data->flags |= BLE_LL_AUX_HAS_ADVA; - memcpy(aux_data->adva, eh, 6); - aux_data->adva_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_MASK); - eh += BLE_LL_EXT_ADV_ADVA_SIZE; - - if (adva_present) { - *adva_present = true; - } - } else if (adva_present) { - *adva_present = false; - } - - if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - aux_data->flags |= BLE_LL_AUX_HAS_TARGETA; - memcpy(aux_data->targeta, eh, 6); - aux_data->targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK); - eh += BLE_LL_EXT_ADV_TARGETA_SIZE; - } - - - if (eh_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { - eh += 1; - } - - if (eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { - aux_data->flags |= BLE_LL_AUX_HAS_ADI; - if (is_aux) { - if (get_le16(eh) != aux_data->adi) { - aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_ERROR; - STATS_INC(ble_ll_stats, aux_chain_err); - } - } else { - aux_data->adi = get_le16(eh); - } - eh += BLE_LL_EXT_ADV_DATA_INFO_SIZE; - } - - if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { - if (ble_ll_ext_scan_parse_aux_ptr(aux_data, eh)) { - aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_ERROR; - } - } else if (!(adv_mode & BLE_LL_EXT_ADV_MODE_SCAN)) { - /* No AuxPtr for scannable PDU is ignored since we can still scan it */ - aux_data->flags_isr |= BLE_LL_AUX_FLAG_SCAN_COMPLETE; - } - - ble_hdr->rxinfo.user_data = aux_data; - - /* Do not scan for next AUX if either no AuxPtr or malformed data found */ - return !(eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) || - (aux_data->flags_isr & BLE_LL_AUX_FLAG_SCAN_ERROR); -} - -static int -ble_ll_scan_get_addr_from_ext_adv(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr, - uint8_t **addr, uint8_t *addr_type, - uint8_t **inita, uint8_t *inita_type, - int *ext_mode) -{ - uint8_t pdu_len; - uint8_t ext_hdr_len; - uint8_t ext_hdr_flags; - uint8_t *ext_hdr; - bool has_adva = false; - bool has_inita = false; - int i; - struct ble_ll_aux_data *aux_data = ble_hdr->rxinfo.user_data; - - *addr = NULL; - *inita = NULL; - - pdu_len = rxbuf[1]; - if (pdu_len == 0) { - return -1; - } - - *ext_mode = rxbuf[2] >> 6; - if (*ext_mode > BLE_LL_EXT_ADV_MODE_SCAN) { - return -1; - } - - ext_hdr_len = rxbuf[2] & 0x3F; - if (ext_hdr_len == 0) { - goto done; - } - - ext_hdr_flags = rxbuf[3]; - ext_hdr = &rxbuf[4]; - - i = 0; - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - if (ext_hdr_len < BLE_LL_EXT_ADV_ADVA_SIZE) { - return -1; - } - - *addr = ext_hdr + i; - *addr_type = - ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); - i += BLE_LL_EXT_ADV_ADVA_SIZE; - - has_adva = true; - } - - if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - *inita = ext_hdr + i; - *inita_type = - ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK); - i += BLE_LL_EXT_ADV_TARGETA_SIZE; - - has_inita = true; - } - -done: - /* Check if we had address already. If yes, replace it with new one */ - - if (aux_data) { - /* If address has been provided, we do have it already in aux_data.*/ - if (aux_data->flags & BLE_LL_AUX_HAS_ADVA) { - if (!has_adva) { - *addr = aux_data->adva; - *addr_type = aux_data->adva_type; - } else { - memcpy(aux_data->adva, *addr, 6); - aux_data->adva_type = *addr_type; - } + case BLE_SCAN_TYPE_INITIATE: + if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || + (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND)) { + rc = 1; } - if (aux_data->flags & BLE_LL_AUX_HAS_TARGETA) { - if (!has_inita) { - *inita = aux_data->targeta; - *inita_type = aux_data->targeta_type; - } else { - memcpy(aux_data->targeta, *inita, 6); - aux_data->targeta_type = *inita_type; - } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_EXT_IND && scansm->ext_scanning)) { + *rxflags |= BLE_MBUF_HDR_F_EXT_ADV; + rc = 1; } - } - - return 0; -} #endif - -int -ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *ble_hdr, - uint8_t **addr, uint8_t *addr_type, - uint8_t **inita, uint8_t *inita_type, - int *ext_mode) -{ - /* - * XXX this should be only used for legacy advertising, but need to refactor - * code in ble_ll_init first so it does not call this for ext - */ - - if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND && - pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { - /* Legacy advertising */ - *addr_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK); - *addr = rxbuf + BLE_LL_PDU_HDR_LEN; - - if (pdu_type != BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) { - *inita = NULL; - *inita_type = 0; - return 0; - } - - *inita = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN; - *inita_type = ble_ll_get_addr_type(rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK); - - return 0; + break; + default: + break; } - /* Extended advertising */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - return ble_ll_scan_get_addr_from_ext_adv(rxbuf, ble_hdr, addr, addr_type, - inita, inita_type, ext_mode); -#else - return -1; -#endif - - return 0; + return rc; } static void @@ -1918,11 +1327,12 @@ ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, resolved = false; #endif - /* Check on WL if required by scan filter policy */ - if ((scan_filt_policy & 0x01) && - !ble_ll_whitelist_match(addrd->adv_addr, addrd->adv_addr_type, - resolved)) { + if (scan_filt_policy & 0x01) { + /* Check on WL if required by scan filter policy */ + if (!ble_ll_whitelist_match(addrd->adv_addr, addrd->adv_addr_type, + resolved)) { return -2; + } } if (scan_ok) { @@ -1932,10 +1342,33 @@ ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, return 0; } +int +ble_ll_scan_rx_check_init(struct ble_ll_scan_addr_data *addrd) +{ + struct ble_ll_scan_sm *scansm; + struct ble_ll_conn_sm *connsm; + + scansm = &g_ble_ll_scan_sm; + connsm = scansm->connsm; + BLE_LL_ASSERT(connsm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if ((connsm->peer_addr_type > BLE_ADDR_RANDOM) && !addrd->adva_resolved) { + return -1; + } +#endif + if ((addrd->adv_addr_type != (connsm->peer_addr_type & 0x01)) || + memcmp(addrd->adv_addr, connsm->peer_addr, 6) != 0) { + return -1; + } + + return 0; +} + static int -ble_ll_scan_rx_isr_on_adv(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) +ble_ll_scan_rx_isr_end_on_adv(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; struct ble_ll_scan_phy *scanp = scansm->scanp; @@ -1949,12 +1382,20 @@ ble_ll_scan_rx_isr_on_adv(uint8_t pdu_type, uint8_t *rxbuf, addrd->rpa_index = ble_hw_resolv_list_match(); #endif - rc = ble_ll_scan_rx_filter(scansm->own_addr_type, scansm->scan_filt_policy, - addrd, &scan_ok); + rc = ble_ll_scan_rx_filter(scansm->own_addr_type, + scansm->scan_filt_policy, addrd, &scan_ok); if (rc < 0) { return 0; } + if ((scanp->scan_type == BLE_SCAN_TYPE_INITIATE) && + !(scansm->scan_filt_policy & 0x01)) { + rc = ble_ll_scan_rx_check_init(addrd); + if (rc < 0) { + return 0; + } + } + rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) rxinfo->rpa_index = addrd->rpa_index; @@ -1971,15 +1412,19 @@ ble_ll_scan_rx_isr_on_adv(uint8_t pdu_type, uint8_t *rxbuf, return 0; } - return (scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && + /* Allow responding to all PDUs when initiating since unwanted PDUs were + * already filtered out in isr_start. + */ + return ((scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || - (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)); + (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND))) || + (scanp->scan_type == BLE_SCAN_TYPE_INITIATE); } static int -ble_ll_scan_rx_isr_on_scan_rsp(uint8_t pdu_type, uint8_t *rxbuf, - struct ble_mbuf_hdr *hdr, - struct ble_ll_scan_addr_data *addrd) +ble_ll_scan_rx_isr_end_on_scan_rsp(uint8_t pdu_type, uint8_t *rxbuf, + struct ble_mbuf_hdr *hdr, + struct ble_ll_scan_addr_data *addrd) { struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; @@ -2119,10 +1564,10 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: - rc = ble_ll_scan_rx_isr_on_adv(pdu_type, rxbuf, hdr, &addrd); + rc = ble_ll_scan_rx_isr_end_on_adv(pdu_type, rxbuf, hdr, &addrd); break; case BLE_ADV_PDU_TYPE_SCAN_RSP: - rc = ble_ll_scan_rx_isr_on_scan_rsp(pdu_type, rxbuf, hdr, &addrd); + rc = ble_ll_scan_rx_isr_end_on_scan_rsp(pdu_type, rxbuf, hdr, &addrd); break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_ADV_PDU_TYPE_ADV_EXT_IND: @@ -2144,10 +1589,22 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) if (rc == -1) { goto scan_rx_isr_ignore; - } else if (rc == 1) { - if (ble_ll_scan_send_scan_req(pdu_type, rxbuf, hdr, &addrd)) { - /* Keep PHY active and LL in scanning state */ - return 0; + } + + if (rc == 1) { + switch (scansm->scanp->scan_type) { + case BLE_SCAN_TYPE_ACTIVE: + if (ble_ll_scan_send_scan_req(pdu_type, rxbuf, hdr, &addrd)) { + /* Keep PHY active and LL in scanning state */ + return 0; + } + break; + case BLE_SCAN_TYPE_INITIATE: + if (ble_ll_conn_send_connect_req(rxpdu, &addrd, 0) == 0) { + hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONNECT_IND_TXD; + return 0; + } + break; } } @@ -2193,7 +1650,7 @@ ble_ll_scan_chk_resume(void) if (ble_ll_state_get() == BLE_LL_STATE_STANDBY && ble_ll_scan_is_inside_window(scansm->scanp, now)) { /* Turn on the receiver and set state */ - ble_ll_scan_start(scansm, NULL); + ble_ll_scan_start(scansm); } OS_EXIT_CRITICAL(sr); } @@ -2219,11 +1676,6 @@ ble_ll_scan_timer_cb(void *arg) void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_npl_event_set_arg(&scansm->scan_interrupted_ev, scansm->cur_aux_data); - scansm->cur_aux_data = NULL; -#endif - ble_ll_event_send(&scansm->scan_interrupted_ev); } @@ -2236,16 +1688,7 @@ ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm) void ble_ll_scan_wfr_timer_exp(void) { - struct ble_ll_scan_sm *scansm; - uint8_t chan; - int phy; - int rc; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - uint8_t phy_mode; -#endif - uint32_t now; - - scansm = &g_ble_ll_scan_sm; + struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; /* Update backoff if we failed to receive scan response */ if (scansm->scan_rsp_pending) { @@ -2253,34 +1696,6 @@ ble_ll_scan_wfr_timer_exp(void) ble_ll_scan_req_backoff(scansm, 0); } - if (scansm->cur_aux_data) { - /* We actually care about interrupted scan only for EXT ADV because only - * then we might consider to send truncated event to the host. - */ - ble_ll_scan_interrupted(scansm); - - /* Need to disable phy since we are going to move to BLE_LL_STATE_STANDBY - * or we will need to change channel to primary one - */ - ble_phy_disable(); - - now = os_cputime_get32(); - if (!ble_ll_scan_is_inside_window(scansm->scanp, now)) { - /* Outside the window scan */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - return; - } - - ble_ll_get_chan_to_scan(scansm, &chan, &phy); -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - phy_mode = ble_ll_phy_to_phy_mode(phy, BLE_HCI_LE_PHY_CODED_ANY); - ble_phy_mode_set(phy_mode, phy_mode); -#endif - rc = ble_phy_setchan(chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); - BLE_LL_ASSERT(rc == 0); - } - - ble_phy_restart_rx(); } @@ -2509,7 +1924,10 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om, void ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hdr) { + struct ble_mbuf_hdr_rxinfo *rxinfo; + struct ble_ll_scan_sm *scansm; struct ble_ll_scan_addr_data addrd; + uint8_t *targeta; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { @@ -2519,7 +1937,26 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd } #endif - ble_ll_scan_rx_pkt_in_on_legacy(ptype, om, hdr, &addrd); + scansm = &g_ble_ll_scan_sm; + rxinfo = &hdr->rxinfo; + + if (scansm->scanp->scan_type == BLE_SCAN_TYPE_INITIATE) { + if (rxinfo->flags & BLE_MBUF_HDR_F_CONNECT_IND_TXD) { + /* We need to keep original TargetA in case it was resolved, so rl + * can be updated properly. + */ + ble_ll_scan_get_addr_data_from_legacy(ptype, om->om_data, &addrd); + targeta = addrd.targeta; + ble_ll_scan_rx_pkt_in_restore_addr_data(hdr, &addrd); + + ble_ll_scan_sm_stop(0); + ble_ll_conn_created_on_legacy(om, &addrd, targeta); + return; + } + } else { + ble_ll_scan_rx_pkt_in_on_legacy(ptype, om, hdr, &addrd); + } + ble_ll_scan_chk_resume(); } @@ -2975,7 +2412,7 @@ ble_ll_scan_can_chg_whitelist(void) int ble_ll_scan_initiator_start(struct hci_create_conn *hcc, - struct ble_ll_scan_sm **sm) + struct ble_ll_conn_sm *connsm) { struct ble_ll_scan_sm *scansm; struct ble_ll_scan_phy *scanp; @@ -2987,6 +2424,8 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) scansm->ext_scanning = 0; #endif + scansm->connsm = connsm; + scansm->scanp = &scansm->scan_phys[PHY_UNCODED]; scansm->scanp_next = NULL; @@ -3002,15 +2441,6 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc, #endif rc = ble_ll_scan_sm_start(scansm); - if (sm == NULL) { - return rc; - } - - if (rc == BLE_ERR_SUCCESS) { - *sm = scansm; - } else { - *sm = NULL; - } return rc; } @@ -3018,7 +2448,7 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) int ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, - struct ble_ll_scan_sm **sm) + struct ble_ll_conn_sm *connsm) { struct ble_ll_scan_sm *scansm; struct ble_ll_scan_phy *scanp_uncoded; @@ -3032,6 +2462,7 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, scansm->scanp = NULL; scansm->scanp_next = NULL; scansm->ext_scanning = 1; + scansm->connsm = connsm; params = &hcc->params[0]; scanp_uncoded = &scansm->scan_phys[PHY_UNCODED]; @@ -3080,15 +2511,6 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, } rc = ble_ll_scan_sm_start(scansm); - if (sm == NULL) { - return rc; - } - - if (rc == BLE_ERR_SUCCESS) { - *sm = scansm; - } else { - *sm = NULL; - } return rc; } @@ -3155,13 +2577,6 @@ ble_ll_scan_get_pdu_data(void) return &g_ble_ll_scan_sm.pdu_data; } -/* Returns true if whitelist is enabled for scanning */ -int -ble_ll_scan_whitelist_enabled(void) -{ - return g_ble_ll_scan_sm.scan_filt_policy & 1; -} - static void ble_ll_scan_common_init(void) { @@ -3243,13 +2658,11 @@ ble_ll_scan_reset(void) os_mempool_clear(&g_scan_dup_pool); TAILQ_INIT(&g_scan_dup_list); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - /* clear memory pool for AUX scan results */ - os_mempool_clear(&ext_scan_aux_pool); -#endif - /* Call the common init function again */ ble_ll_scan_common_init(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_ll_scan_aux_init(); +#endif } /** @@ -3263,15 +2676,6 @@ ble_ll_scan_init(void) { os_error_t err; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - err = os_mempool_init(&ext_scan_aux_pool, - MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT), - sizeof (struct ble_ll_aux_data), - ext_scan_aux_mem, - "ble_ll_aux_scan_pool"); - BLE_LL_ASSERT(err == 0); -#endif - err = os_mempool_init(&g_scan_dup_pool, MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS), sizeof(struct ble_ll_scan_dup_entry), diff --git a/nimble/controller/src/ble_ll_scan_aux.c b/nimble/controller/src/ble_ll_scan_aux.c index 128b45a7cc..94f776df9b 100644 --- a/nimble/controller/src/ble_ll_scan_aux.c +++ b/nimble/controller/src/ble_ll_scan_aux.c @@ -50,6 +50,8 @@ #define BLE_LL_SCAN_AUX_F_HAS_ADI 0x0080 #define BLE_LL_SCAN_AUX_F_RESOLVED_ADVA 0x0100 #define BLE_LL_SCAN_AUX_F_RESOLVED_TARGETA 0x0200 +#define BLE_LL_SCAN_AUX_F_CONNECTABLE 0x0400 +#define BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP 0x0800 #define BLE_LL_SCAN_AUX_H_SENT_ANY 0x01 #define BLE_LL_SCAN_AUX_H_DONE 0x02 @@ -668,6 +670,10 @@ ble_ll_scan_aux_break_ev(struct ble_npl_event *ev) void ble_ll_scan_aux_break(struct ble_ll_scan_aux_data *aux) { + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) { + ble_ll_conn_send_connect_req_cancel(); + } + ble_npl_event_init(&aux->break_ev, ble_ll_scan_aux_break_ev, aux); ble_ll_event_send(&aux->break_ev); } @@ -751,18 +757,29 @@ ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr) { struct ble_ll_scan_aux_data *aux; + BLE_LL_ASSERT(aux_data_current); + aux = aux_data_current; + + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) { + if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { + aux_data_current = NULL; + ble_ll_scan_aux_break(aux); + return -1; + } + return 0; + } + if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) { + aux_data_current = NULL; + ble_ll_scan_aux_break(aux); return -1; } - BLE_LL_ASSERT(aux_data_current); - aux = aux_data_current; - /* * Prepare TX transition when doing active scanning and receiving 1st PDU * since we may want to send AUX_SCAN_REQ. */ - if ((aux->scan_type == BLE_SCAN_TYPE_ACTIVE) && + if ((aux->scan_type != BLE_SCAN_TYPE_PASSIVE) && !(aux->flags & BLE_LL_SCAN_AUX_F_AUX_ADV)) { return 1; } @@ -1012,6 +1029,10 @@ ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm, return -1; } + /* Don't care about initiator here, there are no AdvA and TargetA + * in connectable ADV_EXT_IND so no filtering to do. + */ + if (!aux_ptr) { /* We do not allocate aux_data for ADV_EXT_IND without AuxPtr so * need to pass match data in rxinfo. @@ -1046,6 +1067,10 @@ ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm, aux->adi = adi; aux->flags |= BLE_LL_SCAN_AUX_F_HAS_ADI; + if (aux->scan_type == BLE_SCAN_TYPE_INITIATE) { + aux->flags |= BLE_LL_SCAN_AUX_F_CONNECTABLE; + } + if (do_match) { aux->flags |= BLE_LL_SCAN_AUX_F_MATCHED; ble_ll_scan_aux_update_aux_data_from_addrd(&addrd, aux); @@ -1187,6 +1212,7 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) struct ble_mbuf_hdr_rxinfo *rxinfo; struct ble_ll_scan_aux_data *aux; struct ble_mbuf_hdr *rxhdr; + uint8_t scan_filt_policy; uint8_t scan_ok; uint8_t adv_mode; uint8_t *rxbuf; @@ -1212,6 +1238,12 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) rxbuf = rxpdu->om_data; + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) { + aux->flags &= ~BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP; + rxinfo->flags |= BLE_MBUF_HDR_F_CONNECT_RSP_RXD; + goto done; + } + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_SCAN_RSP) { aux->flags &= ~BLE_LL_SCAN_AUX_F_W4_SCAN_RSP; aux->flags |= BLE_LL_SCAN_AUX_F_SCANNED; @@ -1251,9 +1283,10 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) addrd.rpa_index = aux->rpa_index; #endif + scan_filt_policy = ble_ll_scan_get_filt_policy(); + rc = ble_ll_scan_rx_filter(ble_ll_scan_get_own_addr_type(), - ble_ll_scan_get_filt_policy(), - &addrd, &scan_ok); + scan_filt_policy, &addrd, &scan_ok); if (rc < 0) { rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; /* @@ -1269,21 +1302,42 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) goto done; } + if ((aux->scan_type == BLE_SCAN_TYPE_INITIATE) && + !(scan_filt_policy & 0x01)) { + rc = ble_ll_scan_rx_check_init(&addrd); + if (rc < 0) { + goto done; + } + } + aux->flags |= BLE_LL_SCAN_AUX_F_MATCHED; ble_ll_scan_aux_update_aux_data_from_addrd(&addrd, aux); adv_mode = rxbuf[2] >> 6; - if ((aux->scan_type == BLE_SCAN_TYPE_ACTIVE) && - (adv_mode == BLE_LL_EXT_ADV_MODE_SCAN) && scan_ok) { - if (ble_ll_scan_aux_send_scan_req(aux, &addrd)) { + switch (aux->scan_type) { + case BLE_SCAN_TYPE_ACTIVE: + if ((adv_mode == BLE_LL_EXT_ADV_MODE_SCAN) && scan_ok && + ble_ll_scan_aux_send_scan_req(aux, &addrd)) { /* AUX_SCAN_REQ sent, keep PHY enabled to continue */ aux->flags |= BLE_LL_SCAN_AUX_F_W4_SCAN_RSP; rxinfo->flags |= BLE_MBUF_HDR_F_SCAN_REQ_TXD; aux_data_current = aux; return 0; } + break; + case BLE_SCAN_TYPE_INITIATE: + if (ble_ll_conn_send_connect_req(rxpdu, &addrd, 1) == 0) { + /* AUX_CONNECT_REQ sent, keep PHY enabled to continue */ + aux->flags |= BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP; + rxinfo->flags |= BLE_MBUF_HDR_F_CONNECT_REQ_TXD; + aux_data_current = aux; + return 0; + } else { + rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; + } + break; } done: @@ -1399,6 +1453,137 @@ ble_ll_scan_aux_sync_check(struct os_mbuf *rxpdu, } #endif + +static int +ble_ll_scan_aux_check_connect_rsp(uint8_t *rxbuf, + struct ble_ll_scan_pdu_data *pdu_data, + struct ble_ll_scan_addr_data *addrd) +{ + uint8_t pdu_hdr; + uint8_t pdu_len; + uint8_t adv_mode; + uint8_t eh_len; + uint8_t eh_flags; + uint8_t *eh_data; + uint8_t adva_type; + uint8_t *adva; + uint8_t targeta_type; + uint8_t *targeta; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + struct ble_ll_resolv_entry *rl = NULL; +#endif + + pdu_hdr = rxbuf[0]; + pdu_len = rxbuf[1]; + + if (pdu_len == 0) { + return -1; + } + + adv_mode = rxbuf[2] >> 6; + eh_len = rxbuf[2] & 0x3f; + + if ((adv_mode != 0) || (eh_len == 0)) { + return -1; + } + + eh_flags = rxbuf[3]; + eh_data = &rxbuf[4]; + + /* AUX_CONNECT_RSP without AdvA or TargetA is not valid */ + if (!(eh_flags & ((1 << BLE_LL_EXT_ADV_ADVA_BIT) | + (1 << BLE_LL_EXT_ADV_TARGETA_BIT)))) { + return -1; + } + + adva = eh_data; + adva_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_RAND); + eh_data += BLE_LL_EXT_ADV_ADVA_SIZE; + + targeta = eh_data; + targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_RAND); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* If AdvA was initially resolved, we need to check if current AdvA also + * resolved with the same IRK since it may have changes due to RPA timeout. + * Otherwise it shall be the same as in AUX_CONNECT_REQ. + */ + if (addrd->adva_resolved) { + if (!adva_type) { + return -1; + } + + BLE_LL_ASSERT(addrd->rpa_index >= 0); + rl = &g_ble_ll_resolv_list[addrd->rpa_index]; + + if (!ble_ll_resolv_rpa(adva, rl->rl_peer_irk)) { + return -1; + } + + addrd->adva = adva; + } else if ((adva_type != + !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) || + (memcmp(adva, pdu_data->adva, 6) != 0)) { + return -1; + } +#else + if ((adva_type != !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) || + (memcmp(adva, pdu_data->adva, 6) != 0)) { + return -1; + } +#endif /* BLE_LL_CFG_FEAT_LL_PRIVACY */ + + if ((targeta_type != !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) || + (memcmp(targeta, pdu_data->inita, 6) != 0)) { + return -1; + } + + return 0; +} + +static void +ble_ll_scan_aux_rx_pkt_in_for_initiator(struct os_mbuf *rxpdu, + struct ble_mbuf_hdr *rxhdr) +{ + struct ble_ll_scan_addr_data addrd; + struct ble_mbuf_hdr_rxinfo *rxinfo; + struct ble_ll_scan_aux_data *aux; + + rxinfo = &rxhdr->rxinfo; + aux = rxinfo->user_data; + + if (rxinfo->flags & BLE_MBUF_HDR_F_IGNORED) { + ble_ll_scan_chk_resume(); + goto done; + } + + if (!(rxinfo->flags & BLE_MBUF_HDR_F_CONNECT_RSP_RXD)) { + BLE_LL_ASSERT(rxinfo->flags & BLE_MBUF_HDR_F_CONNECT_REQ_TXD); + /* Waiting for AUX_CONNECT_RSP, do nothing */ + return; + } + + ble_ll_scan_aux_init_addrd_from_aux_data(aux, &addrd); + + if (ble_ll_scan_aux_check_connect_rsp(rxpdu->om_data, + ble_ll_scan_get_pdu_data(), + &addrd) < 0) { + ble_ll_scan_chk_resume(); + goto done; + } + + aux->flags &= ~BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP; + + ble_ll_scan_sm_stop(0); + ble_ll_conn_created_on_aux(rxpdu, &addrd, aux->targeta); + +done: + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) { + ble_ll_conn_send_connect_req_cancel(); + } + ble_ll_scan_aux_free(aux); +} + void ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr) { @@ -1416,6 +1601,11 @@ ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr) BLE_LL_ASSERT(aux); + if (aux->scan_type == BLE_SCAN_TYPE_INITIATE) { + ble_ll_scan_aux_rx_pkt_in_for_initiator(rxpdu, rxhdr); + return; + } + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) sync_check = ble_ll_sync_enabled() && !(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN); diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index 1c7db41b9b..03dea23a73 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -134,9 +134,6 @@ ble_ll_sched_preempt(struct ble_ll_sched_item *sch, case BLE_LL_SCHED_TYPE_SCAN_AUX: ble_ll_scan_aux_break(entry->cb_arg); break; - case BLE_LL_SCHED_TYPE_AUX_SCAN: - ble_ll_scan_end_adv_evt(entry->cb_arg); - break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) case BLE_LL_SCHED_TYPE_PERIODIC: ble_ll_adv_periodic_rmvd_from_sched(entry->cb_arg); @@ -1133,20 +1130,6 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) goto sched; } - /* If aux scan scheduled and LL is in state when scanner is running - * in 3 states: - * BLE_LL_STATE_SCANNING - * BLE_LL_STATE_INITIATING - * BLE_LL_STATE_STANDBY - * - * Let scanner to decide to disable phy or not. - */ - if (sch->sched_type == BLE_LL_SCHED_TYPE_AUX_SCAN) { - if (lls == BLE_LL_STATE_INITIATING || lls == BLE_LL_STATE_SCANNING) { - goto sched; - } - } - /* * This is either an advertising event or connection event start. If * we are scanning or initiating just stop it. @@ -1158,11 +1141,6 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) if (lls == BLE_LL_STATE_SCANNING) { ble_ll_state_set(BLE_LL_STATE_STANDBY); ble_ll_scan_halt(); - } else if (lls == BLE_LL_STATE_INITIATING) { - ble_ll_state_set(BLE_LL_STATE_STANDBY); - ble_ll_scan_halt(); - /* PHY is disabled - make sure we do not wait for AUX_CONNECT_RSP */ - ble_ll_conn_reset_pending_aux_conn_rsp(); } else if (lls == BLE_LL_STATE_ADV) { STATS_INC(ble_ll_stats, sched_state_adv_errs); ble_ll_adv_halt(); @@ -1262,78 +1240,6 @@ ble_ll_sched_next_time(uint32_t *next_event_time) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/** - * Called to schedule a aux scan. - * - * Context: Interrupt - * - * @param ble_hdr - * @param scansm - * @param aux_scan - * - * @return 0 on success, 1 otherwise - */ -int -ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, - struct ble_ll_scan_sm *scansm, - struct ble_ll_aux_data *aux_scan) -{ - int rc = 1; - os_sr_t sr; - uint32_t off_ticks; - uint32_t off_rem_usecs; - uint32_t start_time; - uint32_t start_time_rem_usecs; - uint32_t end_time; - uint32_t dur; - struct ble_ll_sched_item *sch; - int phy_mode; - - sch = &aux_scan->sch; - BLE_LL_ASSERT(sch->cb_arg == NULL); - - off_ticks = os_cputime_usecs_to_ticks(aux_scan->offset); - off_rem_usecs = aux_scan->offset - os_cputime_ticks_to_usecs(off_ticks); - - start_time = ble_hdr->beg_cputime + off_ticks; - start_time_rem_usecs = ble_hdr->rem_usecs + off_rem_usecs; - if (start_time_rem_usecs >= 31) { - start_time++; - start_time_rem_usecs -= 31; - } - start_time -= g_ble_ll_sched_offset_ticks; - - /* Let's calculate time we reserve for aux packet. For now we assume to wait - * for fixed number of bytes and handle possible interrupting it in - * ble_ll_sched_execute_item(). This is because aux packet can be up to - * 256bytes and we don't want to block sched that long - */ - phy_mode = ble_ll_phy_to_phy_mode(aux_scan->aux_phy, - BLE_HCI_LE_PHY_CODED_ANY); - dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_AUX_PDU_LEN), - phy_mode); - end_time = start_time + os_cputime_usecs_to_ticks(dur); - - sch->start_time = start_time; - sch->remainder = start_time_rem_usecs; - sch->end_time = end_time; - - OS_ENTER_CRITICAL(sr); - - rc = ble_ll_sched_insert(sch, 0, preempt_none); - - if (rc == 0) { - sch->cb_arg = ble_ll_scan_aux_data_ref(aux_scan); - STATS_INC(ble_ll_stats, aux_scheduled); - } - - OS_EXIT_CRITICAL(sr); - - ble_ll_sched_restart(); - - return rc; -} - int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, uint8_t pdu_time_rem, uint32_t offset_us) diff --git a/nimble/include/nimble/ble.h b/nimble/include/nimble/ble.h index 1ddd5773d0..d349afebb0 100644 --- a/nimble/include/nimble/ble.h +++ b/nimble/include/nimble/ble.h @@ -88,6 +88,9 @@ struct ble_mbuf_hdr_rxinfo * set for the same PDU (e.g. one use by scanner, other one used by * connection) */ +#define BLE_MBUF_HDR_F_CONNECT_IND_TXD (0x4000) +#define BLE_MBUF_HDR_F_CONNECT_REQ_TXD (0x4000) +#define BLE_MBUF_HDR_F_CONNECT_RSP_RXD (0x0008) #define BLE_MBUF_HDR_F_CONN_CREDIT (0x8000) #define BLE_MBUF_HDR_F_IGNORED (0x8000) #define BLE_MBUF_HDR_F_SCAN_REQ_TXD (0x4000) From df6ac21d2f3a5d845dd490dbdd148628d030e2e1 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 19 Oct 2021 17:55:49 +0200 Subject: [PATCH 109/306] nimble/ll: Refactor conn init param handling This fixes handling of parameters used for conn init. Firstly, we only need conn init params when intiating new connection so we can have single, global instance of that params - no need to store them in conns. This saves 72 bytes of RAM per connsm. Secondly, we do not need to store all parameters from HCI command since some of them are only used to initialize scanner and those can be used immediately. We only need to store connection parameters for ext conn create. This also allows to share more code between legacy and ext conn create code paths. --- .../include/controller/ble_ll_conn.h | 27 - .../include/controller/ble_ll_scan.h | 13 +- .../controller/include/controller/ble_phy.h | 5 + nimble/controller/src/ble_ll.c | 2 +- nimble/controller/src/ble_ll_conn.c | 147 ++---- nimble/controller/src/ble_ll_conn_hci.c | 464 +++++++++--------- nimble/controller/src/ble_ll_conn_priv.h | 52 +- nimble/controller/src/ble_ll_hci.c | 4 +- nimble/controller/src/ble_ll_resolv.c | 2 +- nimble/controller/src/ble_ll_scan.c | 81 +-- 10 files changed, 353 insertions(+), 444 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h index 7be3a43157..0de54afb3d 100644 --- a/nimble/controller/include/controller/ble_ll_conn.h +++ b/nimble/controller/include/controller/ble_ll_conn.h @@ -188,29 +188,6 @@ struct hci_conn_update uint16_t max_ce_len; }; -struct hci_ext_conn_params -{ - uint16_t scan_itvl; - uint16_t scan_window; - uint32_t conn_itvl; - uint16_t conn_itvl_ticks; - uint8_t conn_itvl_usecs; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint16_t min_ce_len; - uint16_t max_ce_len; -}; - -struct hci_ext_create_conn -{ - uint8_t filter_policy; - uint8_t own_addr_type; - uint8_t peer_addr_type; - uint8_t peer_addr[BLE_DEV_ADDR_LEN]; - uint8_t init_phy_mask; - struct hci_ext_conn_params params[3]; -}; - /* Connection state machine */ struct ble_ll_conn_sm { @@ -379,10 +356,6 @@ struct ble_ll_conn_sm /* XXX: for now, just store them all */ struct ble_ll_conn_params conn_cp; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct hci_ext_create_conn initial_params; -#endif - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) uint8_t sync_transfer_mode; uint16_t sync_transfer_skip; diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index eae0c39457..04ca48177b 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -197,10 +197,11 @@ int ble_ll_scan_can_chg_whitelist(void); int ble_ll_scan_enabled(void); /* Initialize the scanner when we start initiating */ -struct hci_create_conn; +struct ble_ll_conn_create_scan; +struct ble_ll_conn_create_params; int -ble_ll_scan_initiator_start(struct hci_create_conn *hcc, - struct ble_ll_conn_sm *connsm); +ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext, + struct ble_ll_conn_create_scan *cc_scan); /* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */ struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void); @@ -227,12 +228,6 @@ void ble_ll_scan_wfr_timer_exp(void); void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/* Initialize the extended scanner when we start initiating */ -struct hci_ext_create_conn; -int -ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, - struct ble_ll_conn_sm *connsm); - /* Called to parse extended advertising*/ void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data); #endif diff --git a/nimble/controller/include/controller/ble_phy.h b/nimble/controller/include/controller/ble_phy.h index cd8350d657..47f3afd4ec 100644 --- a/nimble/controller/include/controller/ble_phy.h +++ b/nimble/controller/include/controller/ble_phy.h @@ -202,6 +202,11 @@ void ble_phy_resolv_list_disable(void); #define BLE_PHY_MASK_2M (BLE_HCI_LE_PHY_2M_PREF_MASK) #define BLE_PHY_MASK_CODED (BLE_HCI_LE_PHY_CODED_PREF_MASK) +/* PHY indices (for a zero-based array) */ +#define BLE_PHY_IDX_1M (0) +#define BLE_PHY_IDX_2M (1) +#define BLE_PHY_IDX_CODED (2) + #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)) uint32_t ble_phy_mode_pdu_start_off(int phy); void ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode); diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 2702b7c53a..014f7e2809 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -577,7 +577,7 @@ ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext) * Test specification extends this also to initiating. */ - if (g_ble_ll_conn_create_sm || ble_ll_scan_enabled() || + if (g_ble_ll_conn_create_sm.connsm || ble_ll_scan_enabled() || (!hci_adv_ext && ble_ll_adv_enabled())) { return BLE_ERR_CMD_DISALLOWED; } diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 76dd18e4bc..eb61414f2c 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -143,8 +143,7 @@ struct ble_ll_conn_global_params g_ble_ll_conn_params; struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params; #endif -/* Pointer to connection state machine we are trying to create */ -struct ble_ll_conn_sm *g_ble_ll_conn_create_sm; +struct ble_ll_conn_create_sm g_ble_ll_conn_create_sm; /* Pointer to current connection */ struct ble_ll_conn_sm *g_ble_ll_conn_cur_sm; @@ -421,25 +420,23 @@ ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *csm) } #endif -static void -ble_ll_conn_calc_itvl_ticks(struct ble_ll_conn_sm *connsm) +void +ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint32_t *itvl_ticks, + uint8_t *itvl_usecs) { uint32_t ticks; uint32_t usecs; - /* - * Precalculate the number of ticks and remaining microseconds for - * the connection interval - */ - usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS; + usecs = itvl * BLE_LL_CONN_ITVL_USECS; ticks = os_cputime_usecs_to_ticks(usecs); - connsm->conn_itvl_usecs = (uint8_t)(usecs - - os_cputime_ticks_to_usecs(ticks)); - if (connsm->conn_itvl_usecs == 31) { - connsm->conn_itvl_usecs = 0; + usecs = usecs - os_cputime_ticks_to_usecs(ticks); + if (usecs == 31) { + usecs = 0; ++ticks; } - connsm->conn_itvl_ticks = ticks; + + *itvl_ticks = ticks; + *itvl_usecs = usecs; } /** @@ -1578,37 +1575,23 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm) */ void ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, - struct hci_create_conn *hcc) + struct ble_ll_conn_create_scan *cc_scan, + struct ble_ll_conn_create_params *cc_params) { ble_ll_conn_master_common_init(connsm); - /* Set slave latency and supervision timeout */ - connsm->slave_latency = hcc->conn_latency; - connsm->supervision_tmo = hcc->supervision_timeout; - - /* Set own address type and peer address if needed */ - connsm->own_addr_type = hcc->own_addr_type; - if (hcc->filter_policy == 0) { - memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN); - connsm->peer_addr_type = hcc->peer_addr_type; - } - - /* XXX: for now, just make connection interval equal to max */ - connsm->conn_itvl = hcc->conn_itvl_max; - - /* Check the min/max CE lengths are less than connection interval */ - if (hcc->min_ce_len > (connsm->conn_itvl * 2)) { - connsm->min_ce_len = connsm->conn_itvl * 2; - } else { - connsm->min_ce_len = hcc->min_ce_len; - } + connsm->own_addr_type = cc_scan->own_addr_type; + memcpy(&connsm->peer_addr, &cc_scan->peer_addr, BLE_DEV_ADDR_LEN); + connsm->peer_addr_type = cc_scan->peer_addr_type; - if (hcc->max_ce_len > (connsm->conn_itvl * 2)) { - connsm->max_ce_len = connsm->conn_itvl * 2; - } else { - connsm->max_ce_len = hcc->max_ce_len; - } + connsm->conn_itvl = cc_params->conn_itvl; + connsm->conn_itvl_ticks = cc_params->conn_itvl_ticks; + connsm->conn_itvl_usecs = cc_params->conn_itvl_usecs; + connsm->slave_latency = cc_params->conn_latency; + connsm->supervision_tmo = cc_params->supervision_timeout; + connsm->min_ce_len = cc_params->min_ce_len; + connsm->max_ce_len = cc_params->max_ce_len; } static void @@ -1684,54 +1667,20 @@ ble_ll_conn_init_phy(struct ble_ll_conn_sm *connsm, int phy) #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - -void -ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm, - struct hci_ext_create_conn *hcc) -{ - - ble_ll_conn_master_common_init(connsm); - - /* Set own address type and peer address if needed */ - connsm->own_addr_type = hcc->own_addr_type; - if (hcc->filter_policy == 0) { - memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN); - connsm->peer_addr_type = hcc->peer_addr_type; - } - - connsm->initial_params = *hcc; -} - -void -ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, - struct hci_ext_conn_params *hcc_params, int phy) +static void +ble_ll_conn_create_set_params(struct ble_ll_conn_sm *connsm, uint8_t phy) { - connsm->slave_latency = hcc_params->conn_latency; - connsm->supervision_tmo = hcc_params->supervision_timeout; + struct ble_ll_conn_create_params *cc_params; - connsm->conn_itvl = hcc_params->conn_itvl; - connsm->conn_itvl_ticks = hcc_params->conn_itvl_ticks; - connsm->conn_itvl_usecs = hcc_params->conn_itvl_usecs; + cc_params = &g_ble_ll_conn_create_sm.params[phy - 1]; - /* Check the min/max CE lengths are less than connection interval */ - if (hcc_params->min_ce_len > (connsm->conn_itvl * 2)) { - connsm->min_ce_len = connsm->conn_itvl * 2; - } else { - connsm->min_ce_len = hcc_params->min_ce_len; - } + connsm->slave_latency = cc_params->conn_latency; + connsm->supervision_tmo = cc_params->supervision_timeout; - if (hcc_params->max_ce_len > (connsm->conn_itvl * 2)) { - connsm->max_ce_len = connsm->conn_itvl * 2; - } else { - connsm->max_ce_len = hcc_params->max_ce_len; - } - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_ll_conn_init_phy(connsm, phy); -#endif + connsm->conn_itvl = cc_params->conn_itvl; + connsm->conn_itvl_ticks = cc_params->conn_itvl_ticks; + connsm->conn_itvl_usecs = cc_params->conn_itvl_usecs; } - - #endif static void @@ -1862,8 +1811,6 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) connsm); #endif - ble_ll_conn_calc_itvl_ticks(connsm); - /* Add to list of active connections */ SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle); } @@ -2170,7 +2117,10 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS; connsm->tx_win_off = upd->winoffset; connsm->conn_itvl = upd->interval; - ble_ll_conn_calc_itvl_ticks(connsm); + + ble_ll_conn_itvl_to_ticks(connsm->conn_itvl, &connsm->conn_itvl_ticks, + &connsm->conn_itvl_usecs); + if (upd->winoffset != 0) { usecs = upd->winoffset * BLE_LL_CONN_ITVL_USECS; ticks = os_cputime_usecs_to_ticks(usecs); @@ -2651,7 +2601,7 @@ ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm, } } else { /* Get pointer to our device address */ - connsm = g_ble_ll_conn_create_sm; + connsm = g_ble_ll_conn_create_sm.connsm; if ((connsm->own_addr_type & 1) == 0) { addr = g_dev_addr; } else { @@ -2764,12 +2714,11 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr; int8_t rpa_index; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - struct hci_ext_conn_params *ecp; uint8_t phy; #endif int rc; - connsm = g_ble_ll_conn_create_sm; + connsm = g_ble_ll_conn_create_sm.connsm; rxhdr = BLE_MBUF_HDR_PTR(rxpdu); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) @@ -2779,8 +2728,7 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu, #else phy = BLE_PHY_1M; #endif - ecp = &connsm->initial_params.params[phy - 1]; - ble_ll_conn_ext_set_params(connsm, ecp, phy); + ble_ll_conn_create_set_params(connsm, phy); } #endif @@ -2806,6 +2754,12 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu, return -1; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && BLE_LL_BT5_PHY_SUPPORTED + if (ext) { + ble_ll_conn_init_phy(connsm, phy); + } +#endif + return 0; } @@ -2814,7 +2768,7 @@ ble_ll_conn_send_connect_req_cancel(void) { struct ble_ll_conn_sm *connsm; - connsm = g_ble_ll_conn_create_sm; + connsm = g_ble_ll_conn_create_sm.connsm; ble_ll_sched_rmv_elem(&connsm->conn_sch); } @@ -2825,8 +2779,8 @@ ble_ll_conn_master_start(uint8_t phy, uint8_t csa, { struct ble_ll_conn_sm *connsm; - connsm = g_ble_ll_conn_create_sm; - g_ble_ll_conn_create_sm = NULL; + connsm = g_ble_ll_conn_create_sm.connsm; + g_ble_ll_conn_create_sm.connsm = NULL; connsm->peer_addr_type = addrd->adv_addr_type; memcpy(connsm->peer_addr, addrd->adv_addr, 6); @@ -3688,6 +3642,9 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr, goto err_slave_start; } + ble_ll_conn_itvl_to_ticks(connsm->conn_itvl, &connsm->conn_itvl_ticks, + &connsm->conn_itvl_usecs); + /* Start the connection state machine */ connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE; ble_ll_conn_sm_new(connsm); @@ -3751,7 +3708,7 @@ ble_ll_conn_module_reset(void) } /* Reset connection we are attempting to create */ - g_ble_ll_conn_create_sm = NULL; + g_ble_ll_conn_create_sm.connsm = NULL; /* Now go through and end all the connections */ while (1) { diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index e53918f96c..decc4851f0 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -43,19 +43,22 @@ static ble_npl_time_t g_ble_ll_last_num_comp_pkt_evt; extern uint8_t *g_ble_ll_conn_comp_ev; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static const uint8_t ble_ll_valid_conn_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK +static const uint8_t ble_ll_conn_create_valid_phy_mask = ( + BLE_HCI_LE_PHY_1M_PREF_MASK | #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - | BLE_HCI_LE_PHY_2M_PREF_MASK + BLE_HCI_LE_PHY_2M_PREF_MASK | #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - | BLE_HCI_LE_PHY_CODED_PREF_MASK + BLE_HCI_LE_PHY_CODED_PREF_MASK | #endif - ); -static const uint8_t ble_ll_conn_required_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK + 0); + +static const uint8_t ble_ll_conn_create_required_phy_mask = ( + BLE_HCI_LE_PHY_1M_PREF_MASK | #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - | BLE_HCI_LE_PHY_CODED_PREF_MASK + BLE_HCI_LE_PHY_CODED_PREF_MASK | #endif - ); + 0); #endif /** @@ -401,18 +404,74 @@ ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason) } } +int +ble_ll_conn_hci_create_check_scan(struct ble_ll_conn_create_scan *p) +{ + if (p->filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if ((p->filter_policy == 0) && + (p->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (p->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (p->init_phy_mask & ~ble_ll_conn_create_valid_phy_mask) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!(p->init_phy_mask & ble_ll_conn_create_required_phy_mask)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } +#endif + + return 0; +} + static int -ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window) +ble_ll_conn_hci_create_check_params(struct ble_ll_conn_create_params *cc_params) { - /* Check interval and window */ - if ((itvl < BLE_HCI_SCAN_ITVL_MIN) || - (itvl > BLE_HCI_SCAN_ITVL_MAX) || - (window < BLE_HCI_SCAN_WINDOW_MIN) || - (window > BLE_HCI_SCAN_WINDOW_MAX) || - (itvl < window)) { + uint32_t supervision_tmo_us; + uint32_t conn_itvl_us; + + if ((cc_params->conn_itvl < BLE_HCI_CONN_ITVL_MIN) || + (cc_params->conn_itvl > BLE_HCI_CONN_ITVL_MAX) || + (cc_params->conn_latency > BLE_HCI_CONN_LATENCY_MAX) || + (cc_params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || + (cc_params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Supervision timeout must be longer than (1 + latency) * interval * 2 */ + supervision_tmo_us = cc_params->supervision_timeout * + BLE_HCI_CONN_SPVN_TMO_UNITS * 1000; + conn_itvl_us = cc_params->conn_itvl * BLE_LL_CONN_ITVL_USECS; + + if (supervision_tmo_us <= (1 + cc_params->conn_latency) * conn_itvl_us * 2) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cc_params->min_ce_len > cc_params->max_ce_len) { return BLE_ERR_INV_HCI_CMD_PARMS; } + /* Adjust min/max ce length to be less than interval */ + if (cc_params->min_ce_len > cc_params->conn_itvl) { + cc_params->min_ce_len = cc_params->conn_itvl; + } + if (cc_params->max_ce_len > cc_params->conn_itvl) { + cc_params->max_ce_len = cc_params->conn_itvl; + } + + /* Precalculate conn interval */ + ble_ll_conn_itvl_to_ticks(cc_params->conn_itvl, &cc_params->conn_itvl_ticks, + &cc_params->conn_itvl_usecs); + return 0; } @@ -426,11 +485,14 @@ ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window) * @return int */ int -ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) +ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len) { const struct ble_hci_le_create_conn_cp *cmd = (const void *) cmdbuf; + struct ble_ll_conn_create_scan cc_scan; + struct ble_ll_conn_create_params cc_params; struct ble_ll_conn_sm *connsm; - struct hci_create_conn hcc = { 0 }; + uint16_t conn_itvl_min; + uint16_t conn_itvl_max; int rc; if (len < sizeof(*cmd)) { @@ -438,7 +500,7 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) } /* If we are already creating a connection we should leave */ - if (g_ble_ll_conn_create_sm) { + if (g_ble_ll_conn_create_sm.connsm) { return BLE_ERR_CMD_DISALLOWED; } @@ -447,57 +509,48 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_CMD_DISALLOWED; } - /* Retrieve command data */ - hcc.scan_itvl = le16toh(cmd->scan_itvl); - hcc.scan_window = le16toh(cmd->scan_window); - - rc = ble_ll_conn_hci_chk_scan_params(hcc.scan_itvl, hcc.scan_window); - if (rc) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Check filter policy */ - hcc.filter_policy = cmd->filter_policy; - if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; + cc_scan.own_addr_type = cmd->own_addr_type; + cc_scan.filter_policy = cmd->filter_policy; + if (cc_scan.filter_policy == 0) { + cc_scan.peer_addr_type = cmd->peer_addr_type; + memcpy(&cc_scan.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + } else { + cc_scan.peer_addr_type = 0; + memset(&cc_scan.peer_addr, 0, BLE_DEV_ADDR_LEN); } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + cc_scan.init_phy_mask = BLE_HCI_LE_PHY_1M_PREF_MASK; +#endif - /* Get peer address type and address only if no whitelist used */ - if (hcc.filter_policy == 0) { - hcc.peer_addr_type = cmd->peer_addr_type; - if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } + cc_scan.scan_params[PHY_UNCODED].itvl = le16toh(cmd->scan_itvl); + cc_scan.scan_params[PHY_UNCODED].window = le16toh(cmd->scan_window); - memcpy(&hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + rc = ble_ll_conn_hci_create_check_scan(&cc_scan); + if (rc) { + return rc; } - /* Get own address type (used in connection request) */ - hcc.own_addr_type = cmd->own_addr_type; - if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + conn_itvl_min = le16toh(cmd->min_conn_itvl); + conn_itvl_max = le16toh(cmd->max_conn_itvl); + + /* Check min/max interval here since generic check does not have min/max + * parameters to check. + */ + if (conn_itvl_min > conn_itvl_max) { return BLE_ERR_INV_HCI_CMD_PARMS; } - /* Check connection interval, latency and supervision timeoout */ - hcc.conn_itvl_min = le16toh(cmd->min_conn_itvl); - hcc.conn_itvl_max = le16toh(cmd->max_conn_itvl); - hcc.conn_latency = le16toh(cmd->conn_latency); - hcc.supervision_timeout = le16toh(cmd->tmo); - rc = ble_ll_conn_hci_chk_conn_params(hcc.conn_itvl_min, - hcc.conn_itvl_max, - hcc.conn_latency, - hcc.supervision_timeout); + cc_params.conn_itvl = conn_itvl_max; + cc_params.conn_latency = le16toh(cmd->conn_latency); + cc_params.supervision_timeout = le16toh(cmd->tmo); + cc_params.min_ce_len = le16toh(cmd->min_ce); + cc_params.max_ce_len = le16toh(cmd->max_ce); + + rc = ble_ll_conn_hci_create_check_params(&cc_params); if (rc) { return rc; } - /* Min/max connection event lengths */ - hcc.min_ce_len = le16toh(cmd->min_ce); - hcc.max_ce_len = le16toh(cmd->max_ce); - if (hcc.min_ce_len > hcc.max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - /* Make sure we can allocate an event to send the connection complete */ if (ble_ll_init_alloc_conn_comp_ev()) { return BLE_ERR_MEM_CAPACITY; @@ -510,18 +563,14 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) } /* Initialize state machine in master role and start state machine */ - ble_ll_conn_master_init(connsm, &hcc); + ble_ll_conn_master_init(connsm, &cc_scan, &cc_params); ble_ll_conn_sm_new(connsm); - /* CSA will be selected when advertising is received */ /* Start scanning */ - rc = ble_ll_scan_initiator_start(&hcc, connsm); + rc = ble_ll_scan_initiator_start(connsm, 0, &cc_scan); if (rc) { SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); - } else { - /* Set the connection state machine we are trying to create. */ - g_ble_ll_conn_create_sm = connsm; } return rc; @@ -529,68 +578,117 @@ ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static void -ble_ll_conn_hcc_params_set_fallback(struct hci_ext_create_conn *hcc, - const struct hci_ext_conn_params *fallback) +ble_ll_conn_hci_ext_create_set_fb_params(uint8_t init_phy_mask, + struct ble_ll_conn_create_params *cc_params_fb) { - BLE_LL_ASSERT(fallback); - - if (!(hcc->init_phy_mask & BLE_PHY_MASK_1M)) { - hcc->params[0] = *fallback; + if ((init_phy_mask & BLE_PHY_MASK_1M) == 0) { + g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_1M] = *cc_params_fb; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - if (!(hcc->init_phy_mask & BLE_PHY_MASK_2M)) { - hcc->params[1] = *fallback; + if ((init_phy_mask & BLE_PHY_MASK_2M) == 0) { + g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_2M] = *cc_params_fb; } #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (!(hcc->init_phy_mask & BLE_PHY_MASK_CODED)) { - hcc->params[2] = *fallback; + if ((init_phy_mask & BLE_PHY_MASK_CODED) == 0) { + g_ble_ll_conn_create_sm.params[BLE_PHY_IDX_CODED] = *cc_params_fb; } #endif } -static void -ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint16_t *itvl_ticks, - uint8_t *itvl_usecs) +static int +ble_ll_conn_hci_ext_create_parse_params(const struct conn_params *params, + uint8_t phy, + struct ble_ll_conn_create_scan *cc_scan, + struct ble_ll_conn_create_params *cc_params) { - uint32_t ticks; - uint32_t usecs; + uint16_t conn_itvl_min; + uint16_t conn_itvl_max; + uint16_t scan_itvl; + uint16_t scan_window; + int rc; + + conn_itvl_min = le16toh(params->conn_min_itvl); + conn_itvl_max = le16toh(params->conn_max_itvl); + + /* Check min/max interval here since generic check does not have min/max + * parameters to check. + */ + if (conn_itvl_min > conn_itvl_max) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cc_params->conn_itvl = conn_itvl_max; + cc_params->conn_latency = le16toh(params->conn_latency); + cc_params->supervision_timeout = le16toh(params->supervision_timeout); + cc_params->min_ce_len = le16toh(params->min_ce); + cc_params->max_ce_len = le16toh(params->max_ce); + + rc = ble_ll_conn_hci_create_check_params(cc_params); + if (rc) { + return rc; + } + + if (phy != BLE_PHY_2M) { + scan_itvl = le16toh(params->scan_itvl); + scan_window = le16toh(params->scan_window); - usecs = itvl * BLE_LL_CONN_ITVL_USECS; - ticks = os_cputime_usecs_to_ticks(usecs); - usecs = usecs - os_cputime_ticks_to_usecs(ticks); - if (usecs == 31) { - usecs = 0; - ++ticks; + if ((scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || + (scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || + (scan_window < BLE_HCI_SCAN_WINDOW_MIN) || + (scan_window > BLE_HCI_SCAN_WINDOW_MAX) || + (scan_itvl < scan_window)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (phy == BLE_PHY_1M) { + cc_scan->scan_params[PHY_UNCODED].itvl = scan_itvl; + cc_scan->scan_params[PHY_UNCODED].window = scan_window; + } else { + cc_scan->scan_params[PHY_CODED].itvl = scan_itvl; + cc_scan->scan_params[PHY_CODED].window = scan_window; + } } - *itvl_ticks = ticks; - *itvl_usecs = usecs; + return 0; } int -ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) +ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len) { - const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *) cmdbuf; + static const struct init_phy { + uint8_t idx; + uint8_t mask; + uint8_t phy; + } init_phys[] = { + {BLE_PHY_IDX_1M, BLE_PHY_MASK_1M, BLE_PHY_1M}, +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + {BLE_PHY_IDX_2M, BLE_PHY_MASK_2M, BLE_PHY_2M}, +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + {BLE_PHY_IDX_CODED, BLE_PHY_MASK_CODED, BLE_PHY_CODED}, +#endif + }; + + const struct ble_hci_le_ext_create_conn_cp *cmd = (const void *)cmdbuf; const struct conn_params *params = cmd->conn_params; - const struct hci_ext_conn_params *fallback_params = NULL; - struct hci_ext_create_conn hcc = { 0 }; + struct ble_ll_conn_create_scan cc_scan; + struct ble_ll_conn_create_params *cc_params; + struct ble_ll_conn_create_params *cc_params_fb; struct ble_ll_conn_sm *connsm; - uint16_t conn_itvl_min; - uint16_t conn_itvl_max; + const struct init_phy *init_phy; int rc; /* validate length */ - if (len < sizeof(*cmd)) { + if (len < sizeof(*cmd) + + __builtin_popcount(cmd->init_phy_mask) * sizeof(*params)) { return BLE_ERR_INV_HCI_CMD_PARMS; } - len -= sizeof(*cmd); - /* If we are already creating a connection we should leave */ - if (g_ble_ll_conn_create_sm) { + if (g_ble_ll_conn_create_sm.connsm) { return BLE_ERR_CMD_DISALLOWED; } @@ -599,161 +697,47 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_CMD_DISALLOWED; } - hcc.filter_policy = cmd->filter_policy; - if (hcc.filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - hcc.own_addr_type = cmd->own_addr_type; - if (hcc.own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Validate peer address type only if no whitelist used */ - if (hcc.filter_policy == 0) { - hcc.peer_addr_type = cmd->peer_addr_type; - - if (hcc.peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - memcpy(hcc.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); - } - - hcc.init_phy_mask = cmd->init_phy_mask; - if (hcc.init_phy_mask & ~ble_ll_valid_conn_phy_mask) { - return BLE_ERR_INV_HCI_CMD_PARMS; + cc_scan.own_addr_type = cmd->own_addr_type; + cc_scan.filter_policy = cmd->filter_policy; + if (cc_scan.filter_policy == 0) { + cc_scan.peer_addr_type = cmd->peer_addr_type; + memcpy(cc_scan.peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); + } else { + cc_scan.peer_addr_type = 0; + memset(cc_scan.peer_addr, 0, BLE_DEV_ADDR_LEN); } + cc_scan.init_phy_mask = cmd->init_phy_mask; - if (!(hcc.init_phy_mask & ble_ll_conn_required_phy_mask)) { - /* At least one of those need to be set */ - return BLE_ERR_INV_HCI_CMD_PARMS; + rc = ble_ll_conn_hci_create_check_scan(&cc_scan); + if (rc) { + return rc; } - if (hcc.init_phy_mask & BLE_PHY_MASK_1M) { - if (len < sizeof(*params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - len -= sizeof(*params); + cc_params_fb = NULL; - hcc.params[0].scan_itvl = le16toh(params->scan_itvl); - hcc.params[0].scan_window = le16toh(params->scan_window); + for (int i = 0; i < ARRAY_SIZE(init_phys); i++) { + init_phy = &init_phys[i]; - rc = ble_ll_conn_hci_chk_scan_params(hcc.params[0].scan_itvl, - hcc.params[0].scan_window); - if (rc) { - return rc; + if ((cc_scan.init_phy_mask & init_phy->mask) == 0) { + continue; } - conn_itvl_min = le16toh(params->conn_min_itvl); - conn_itvl_max = le16toh(params->conn_max_itvl); - hcc.params[0].conn_latency = le16toh(params->conn_latency); - hcc.params[0].supervision_timeout = le16toh(params->supervision_timeout); + cc_params = &g_ble_ll_conn_create_sm.params[init_phy->idx]; - rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max, - hcc.params[0].conn_latency, - hcc.params[0].supervision_timeout); + rc = ble_ll_conn_hci_ext_create_parse_params(params, init_phy->phy, + &cc_scan, cc_params); if (rc) { return rc; } - /* Min/max connection event lengths */ - hcc.params[0].min_ce_len = le16toh(params->min_ce); - hcc.params[0].max_ce_len = le16toh(params->max_ce); - if (hcc.params[0].min_ce_len > hcc.params[0].max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; + if (!cc_params_fb) { + cc_params_fb = cc_params; } - - hcc.params[0].conn_itvl = conn_itvl_max; - ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[0].conn_itvl_ticks, - &hcc.params[0].conn_itvl_usecs); - - fallback_params = &hcc.params[0]; params++; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - if (hcc.init_phy_mask & BLE_PHY_MASK_2M) { - if (len < sizeof(*params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - len -= sizeof(*params); - - conn_itvl_min = le16toh(params->conn_min_itvl); - conn_itvl_max = le16toh(params->conn_max_itvl); - hcc.params[1].conn_latency = le16toh(params->conn_latency); - hcc.params[1].supervision_timeout = le16toh(params->supervision_timeout); - - rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max, - hcc.params[1].conn_latency, - hcc.params[1].supervision_timeout); - if (rc) { - return rc; - } - - /* Min/max connection event lengths */ - hcc.params[1].min_ce_len = le16toh(params->min_ce); - hcc.params[1].max_ce_len = le16toh(params->max_ce); - if (hcc.params[1].min_ce_len > hcc.params[1].max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - hcc.params[1].conn_itvl = conn_itvl_max; - ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[1].conn_itvl_ticks, - &hcc.params[1].conn_itvl_usecs); - - if (!fallback_params) { - fallback_params = &hcc.params[1]; - } - params++; - } -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - if (hcc.init_phy_mask & BLE_PHY_MASK_CODED) { - if (len < sizeof(*params)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - len -= sizeof(*params); - - hcc.params[2].scan_itvl = le16toh(params->scan_itvl); - hcc.params[2].scan_window = le16toh(params->scan_window); - - rc = ble_ll_conn_hci_chk_scan_params(hcc.params[2].scan_itvl, - hcc.params[2].scan_window); - if (rc) { - return rc; - } - - conn_itvl_min = le16toh(params->conn_min_itvl); - conn_itvl_max = le16toh(params->conn_max_itvl); - hcc.params[2].conn_latency = le16toh(params->conn_latency); - hcc.params[2].supervision_timeout = le16toh(params->supervision_timeout); - - rc = ble_ll_conn_hci_chk_conn_params(conn_itvl_min, conn_itvl_max, - hcc.params[2].conn_latency, - hcc.params[2].supervision_timeout); - if (rc) { - return rc; - } - - /* Min/max connection event lengths */ - hcc.params[2].min_ce_len = le16toh(params->min_ce); - hcc.params[2].max_ce_len = le16toh(params->max_ce); - if (hcc.params[2].min_ce_len > hcc.params[2].max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - hcc.params[2].conn_itvl = conn_itvl_max; - ble_ll_conn_itvl_to_ticks(conn_itvl_max, &hcc.params[2].conn_itvl_ticks, - &hcc.params[2].conn_itvl_usecs); - - if (!fallback_params) { - fallback_params = &hcc.params[2]; - } - params++; - } -#endif + ble_ll_conn_hci_ext_create_set_fb_params(cc_scan.init_phy_mask, + cc_params_fb); /* Make sure we can allocate an event to send the connection complete */ if (ble_ll_init_alloc_conn_comp_ev()) { @@ -766,20 +750,16 @@ ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_CONN_LIMIT; } - ble_ll_conn_hcc_params_set_fallback(&hcc, fallback_params); - /* Initialize state machine in master role and start state machine */ - ble_ll_conn_ext_master_init(connsm, &hcc); + ble_ll_conn_master_init(connsm, &cc_scan, + &g_ble_ll_conn_create_sm.params[0]); ble_ll_conn_sm_new(connsm); /* Start scanning */ - rc = ble_ll_scan_ext_initiator_start(&hcc, connsm); + rc = ble_ll_scan_initiator_start(connsm, 1, &cc_scan); if (rc) { SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); - } else { - /* Set the connection state machine we are trying to create. */ - g_ble_ll_conn_create_sm = connsm; } return rc; @@ -1125,10 +1105,10 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) * return disallowed as well */ OS_ENTER_CRITICAL(sr); - connsm = g_ble_ll_conn_create_sm; + connsm = g_ble_ll_conn_create_sm.connsm; if (connsm && (connsm->conn_state == BLE_LL_CONN_STATE_IDLE)) { /* stop scanning and end the connection event */ - g_ble_ll_conn_create_sm = NULL; + g_ble_ll_conn_create_sm.connsm = NULL; ble_ll_scan_sm_stop(1); ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID); diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h index 099ce77f50..d1a4a3e884 100644 --- a/nimble/controller/src/ble_ll_conn_priv.h +++ b/nimble/controller/src/ble_ll_conn_priv.h @@ -93,8 +93,38 @@ STAILQ_HEAD(ble_ll_conn_free_list, ble_ll_conn_sm); extern struct ble_ll_conn_active_list g_ble_ll_conn_active_list; extern struct ble_ll_conn_free_list g_ble_ll_conn_free_list; -/* Pointer to connection state machine we are trying to create */ -extern struct ble_ll_conn_sm *g_ble_ll_conn_create_sm; +struct ble_ll_conn_create_scan { + uint8_t filter_policy; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t peer_addr[BLE_DEV_ADDR_LEN]; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + uint8_t init_phy_mask; +#endif + struct { + uint16_t itvl; + uint16_t window; + } scan_params[2]; +}; + +struct ble_ll_conn_create_params { + uint32_t conn_itvl; + uint32_t conn_itvl_ticks; + uint8_t conn_itvl_usecs; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +}; + +struct ble_ll_conn_create_sm { + struct ble_ll_conn_sm *connsm; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + struct ble_ll_conn_create_params params[3]; +#endif +}; + +extern struct ble_ll_conn_create_sm g_ble_ll_conn_create_sm; /* Generic interface */ struct ble_ll_len_req; @@ -123,15 +153,8 @@ void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, uint8_t hdr_byte, uint16_t length); struct ble_ll_conn_sm *ble_ll_conn_sm_get(void); void ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, - struct hci_create_conn *hcc); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -void ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm, - struct hci_ext_create_conn *hcc); - -void ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm, - struct hci_ext_conn_params *hcc_params, - int phy); -#endif + struct ble_ll_conn_create_scan *cc_scan, + struct ble_ll_conn_create_params *cc_params); struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle); void ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm); @@ -158,7 +181,7 @@ void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm); 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_create(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, @@ -205,6 +228,9 @@ bool ble_ll_conn_cth_flow_enable(bool enabled); void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf); #endif +void ble_ll_conn_itvl_to_ticks(uint32_t itvl, + uint32_t *itvl_ticks, uint8_t *itvl_usecs); + int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg); int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg); @@ -213,7 +239,7 @@ int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len, int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *connsm); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len); #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 7cd3621c6d..547b661594 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -910,7 +910,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_hci_scan_set_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_CREATE_CONN: - rc = ble_ll_conn_create(cmdbuf, len); + rc = ble_ll_conn_hci_create(cmdbuf, len); break; case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL: if (len == 0) { @@ -1113,7 +1113,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_hci_ext_scan_set_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_EXT_CREATE_CONN: - rc = ble_ll_ext_conn_create(cmdbuf, len); + rc = ble_ll_conn_hci_ext_create(cmdbuf, len); break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) diff --git a/nimble/controller/src/ble_ll_resolv.c b/nimble/controller/src/ble_ll_resolv.c index 02af93040a..f85e26a8ad 100644 --- a/nimble/controller/src/ble_ll_resolv.c +++ b/nimble/controller/src/ble_ll_resolv.c @@ -57,7 +57,7 @@ ble_ll_is_controller_busy(void) #endif return ble_ll_adv_enabled() || ble_ll_scan_enabled() || - g_ble_ll_conn_create_sm; + g_ble_ll_conn_create_sm.connsm; } /** * Called to determine if a change is allowed to the resolving list at this diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 0d9d36f666..736383197a 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2411,65 +2411,37 @@ ble_ll_scan_can_chg_whitelist(void) } int -ble_ll_scan_initiator_start(struct hci_create_conn *hcc, - struct ble_ll_conn_sm *connsm) -{ - struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_phy *scanp; - int rc; - - scansm = &g_ble_ll_scan_sm; - scansm->own_addr_type = hcc->own_addr_type; - scansm->scan_filt_policy = hcc->filter_policy; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - scansm->ext_scanning = 0; -#endif - scansm->connsm = connsm; - - scansm->scanp = &scansm->scan_phys[PHY_UNCODED]; - scansm->scanp_next = NULL; - - scanp = scansm->scanp; - scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl); - scanp->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window); - scanp->scan_type = BLE_SCAN_TYPE_INITIATE; - scanp->configured = 1; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - scanp = &scansm->scan_phys[PHY_CODED]; - scanp->configured = 0; -#endif - - rc = ble_ll_scan_sm_start(scansm); - - return rc; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int -ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, - struct ble_ll_conn_sm *connsm) +ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext, + struct ble_ll_conn_create_scan *cc_scan) { struct ble_ll_scan_sm *scansm; struct ble_ll_scan_phy *scanp_uncoded; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) struct ble_ll_scan_phy *scanp_coded; - struct hci_ext_conn_params *params; +#endif + uint8_t init_phy_mask; int rc; scansm = &g_ble_ll_scan_sm; - scansm->own_addr_type = hcc->own_addr_type; - scansm->scan_filt_policy = hcc->filter_policy; + scansm->own_addr_type = cc_scan->own_addr_type; + scansm->scan_filt_policy = cc_scan->filter_policy; scansm->scanp = NULL; scansm->scanp_next = NULL; - scansm->ext_scanning = 1; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + scansm->ext_scanning = ext; + init_phy_mask = cc_scan->init_phy_mask; +#else + init_phy_mask = BLE_PHY_MASK_1M; +#endif scansm->connsm = connsm; - params = &hcc->params[0]; scanp_uncoded = &scansm->scan_phys[PHY_UNCODED]; - if (hcc->init_phy_mask & BLE_PHY_MASK_1M) { + if (init_phy_mask & BLE_PHY_MASK_1M) { scanp_uncoded->configured = 1; - scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); - scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); + scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks( + cc_scan->scan_params[PHY_UNCODED].itvl); + scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks( + cc_scan->scan_params[PHY_UNCODED].window); scanp_uncoded->scan_type = BLE_SCAN_TYPE_INITIATE; scansm->scanp = scanp_uncoded; } else { @@ -2477,12 +2449,13 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - params = &hcc->params[2]; scanp_coded = &scansm->scan_phys[PHY_CODED]; - if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) { + if (init_phy_mask & BLE_PHY_MASK_CODED) { scanp_coded->configured = 1; - scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl); - scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window); + scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks( + cc_scan->scan_params[PHY_CODED].itvl); + scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks( + cc_scan->scan_params[PHY_CODED].window); scanp_coded->scan_type = BLE_SCAN_TYPE_INITIATE; if (scansm->scanp) { scansm->scanp_next = scanp_coded; @@ -2492,9 +2465,6 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, } else { scanp_coded->configured = 0; } -#else - scanp_coded = NULL; -#endif /* if any of PHYs is configured for continuous scan we alter interval to * fit other PHY @@ -2509,12 +2479,15 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, scanp_uncoded->timing.interval += scanp_coded->timing.window; } } +#endif rc = ble_ll_scan_sm_start(scansm); + if (rc == 0) { + g_ble_ll_conn_create_sm.connsm = connsm; + } return rc; } -#endif /** * Checks to see if the scanner is enabled. From 9f8fab797bc491a5cf8e406b4f0a156912cdaa3a Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 21 Oct 2021 17:05:49 +0200 Subject: [PATCH 110/306] nimble/ll: Remove redundant variable in local scope --- nimble/controller/src/ble_ll_conn.c | 1 - 1 file changed, 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index eb61414f2c..4456eb77b7 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -2080,7 +2080,6 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) connsm->anchor_point += connsm->conn_itvl_ticks; connsm->anchor_point_usecs += connsm->conn_itvl_usecs; } else { - uint32_t ticks; ticks = os_cputime_usecs_to_ticks(itvl); connsm->anchor_point += ticks; connsm->anchor_point_usecs += (itvl - os_cputime_ticks_to_usecs(ticks)); From 12cd822cfa11c719efed339db4eea25b52210b3d Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 21 Oct 2021 17:06:22 +0200 Subject: [PATCH 111/306] nimble/ll: Remove unused #includes --- nimble/controller/src/ble_ll_conn.c | 3 --- nimble/controller/src/ble_ll_conn_hci.c | 1 - 2 files changed, 4 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 4456eb77b7..53b717c5da 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -25,10 +25,8 @@ #include "os/os.h" #include "os/os_cputime.h" #include "nimble/ble.h" -#include "nimble/nimble_opt.h" #include "nimble/hci_common.h" #include "nimble/ble_hci_trans.h" -#include "ble/xcvr.h" #include "controller/ble_ll.h" #include "controller/ble_ll_hci.h" #include "controller/ble_ll_scan.h" @@ -40,7 +38,6 @@ #include "controller/ble_ll_trace.h" #include "controller/ble_ll_rfmgmt.h" #include "controller/ble_phy.h" -#include "controller/ble_hw.h" #include "controller/ble_ll_utils.h" #include "ble_ll_conn_priv.h" diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index decc4851f0..17be064622 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -23,7 +23,6 @@ #include "syscfg/syscfg.h" #include "os/os.h" #include "nimble/ble.h" -#include "nimble/nimble_opt.h" #include "nimble/hci_common.h" #include "nimble/ble_hci_trans.h" #include "controller/ble_ll.h" From dc47bc58577b34cca71140ce21e54a80210459dd Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 21 Oct 2021 17:07:21 +0200 Subject: [PATCH 112/306] nimble/ll: Remove unused #defines --- nimble/controller/include/controller/ble_ll_conn.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h index 0de54afb3d..207d27eded 100644 --- a/nimble/controller/include/controller/ble_ll_conn.h +++ b/nimble/controller/include/controller/ble_ll_conn.h @@ -45,16 +45,6 @@ extern "C" { /* Channel map size */ #define BLE_LL_CONN_CHMAP_LEN (5) -/* Definitions for source clock accuracy */ -#define BLE_MASTER_SCA_251_500_PPM (0) -#define BLE_MASTER_SCA_151_250_PPM (1) -#define BLE_MASTER_SCA_101_150_PPM (2) -#define BLE_MASTER_SCA_76_100_PPM (3) -#define BLE_MASTER_SCA_51_75_PPM (4) -#define BLE_MASTER_SCA_31_50_PPM (5) -#define BLE_MASTER_SCA_21_30_PPM (6) -#define BLE_MASTER_SCA_0_20_PPM (7) - /* Definition for RSSI when the RSSI is unknown */ #define BLE_LL_CONN_UNKNOWN_RSSI (127) From 868881bc892bb175c1c41c0b54c0bb86204c39d1 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 21 Oct 2021 17:10:52 +0200 Subject: [PATCH 113/306] nimble/ll: Remove max_tx_octets_phy_mode from connsm This is never accessed so looks like we do not need it (anymore)... --- .../include/controller/ble_ll_conn.h | 1 - nimble/controller/src/ble_ll_conn.c | 23 ------------------- 2 files changed, 24 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h index 207d27eded..7128dcb966 100644 --- a/nimble/controller/include/controller/ble_ll_conn.h +++ b/nimble/controller/include/controller/ble_ll_conn.h @@ -205,7 +205,6 @@ struct ble_ll_conn_sm uint16_t rem_max_rx_time; uint16_t eff_max_tx_time; uint16_t eff_max_rx_time; - uint8_t max_tx_octets_phy_mode[BLE_PHY_NUM_MODE]; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) uint16_t host_req_max_tx_time; #endif diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 53b717c5da..08bc1fca27 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -1591,23 +1591,6 @@ ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, connsm->max_ce_len = cc_params->max_ce_len; } -static void -ble_ll_update_max_tx_octets_phy_mode(struct ble_ll_conn_sm *connsm) -{ - uint32_t usecs; - - usecs = connsm->eff_max_tx_time; - - connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_1M] = - ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_1M); - connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_2M] = - ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_2M); - connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_CODED_125KBPS] = - ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_CODED_125KBPS); - connsm->max_tx_octets_phy_mode[BLE_PHY_MODE_CODED_500KBPS] = - ble_ll_pdu_max_tx_octets_get(usecs, BLE_PHY_MODE_CODED_500KBPS); -} - #if (BLE_LL_BT5_PHY_SUPPORTED == 1) static void @@ -1657,8 +1640,6 @@ ble_ll_conn_init_phy(struct ble_ll_conn_sm *connsm, int phy) connsm->rem_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; - - ble_ll_update_max_tx_octets_phy_mode(connsm); } #endif @@ -1791,8 +1772,6 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) connsm->host_req_max_tx_time = 0; #endif - ble_ll_update_max_tx_octets_phy_mode(connsm); - /* Reset encryption data */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) memset(&connsm->enc_data, 0, sizeof(struct ble_ll_conn_enc_data)); @@ -1842,8 +1821,6 @@ ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm) if (eff_time != connsm->eff_max_tx_time) { connsm->eff_max_tx_time = eff_time; send_event = 1; - - ble_ll_update_max_tx_octets_phy_mode(connsm); } eff_bytes = min(connsm->rem_max_tx_octets, connsm->max_rx_octets); if (eff_bytes != connsm->eff_max_rx_octets) { From da46f181fcb568e6156bc1ddc438a67e28a6f5d0 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 21 Oct 2021 19:50:03 +0200 Subject: [PATCH 114/306] nimble/ll: Use common helper for conn params check Turns out we already have one, so let's use it in new code. --- nimble/controller/src/ble_ll_conn_hci.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index 17be064622..7e47377381 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -435,23 +435,13 @@ ble_ll_conn_hci_create_check_scan(struct ble_ll_conn_create_scan *p) static int ble_ll_conn_hci_create_check_params(struct ble_ll_conn_create_params *cc_params) { - uint32_t supervision_tmo_us; - uint32_t conn_itvl_us; - - if ((cc_params->conn_itvl < BLE_HCI_CONN_ITVL_MIN) || - (cc_params->conn_itvl > BLE_HCI_CONN_ITVL_MAX) || - (cc_params->conn_latency > BLE_HCI_CONN_LATENCY_MAX) || - (cc_params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || - (cc_params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Supervision timeout must be longer than (1 + latency) * interval * 2 */ - supervision_tmo_us = cc_params->supervision_timeout * - BLE_HCI_CONN_SPVN_TMO_UNITS * 1000; - conn_itvl_us = cc_params->conn_itvl * BLE_LL_CONN_ITVL_USECS; + int rc; - if (supervision_tmo_us <= (1 + cc_params->conn_latency) * conn_itvl_us * 2) { + rc = ble_ll_conn_hci_chk_conn_params(cc_params->conn_itvl, + cc_params->conn_itvl, + cc_params->conn_latency, + cc_params->supervision_timeout); + if (rc) { return BLE_ERR_INV_HCI_CMD_PARMS; } From 971633179581faff002d906c7a5d0e168b4236cd Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 28 Oct 2021 15:37:54 +0200 Subject: [PATCH 115/306] nimble/host/include/host/ble_gap: add ble_gap_ext_adv_active() --- nimble/host/include/host/ble_gap.h | 12 ++++++++++++ nimble/host/src/ble_gap.c | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index fa7ee562df..af9c978bcc 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -1314,6 +1314,18 @@ int ble_gap_ext_adv_remove(uint8_t instance); * other error code on failure. */ int ble_gap_ext_adv_clear(void); + +/** + * Indicates whether an advertisement procedure is currently in progress on + * the specified Instance + * + * @param instance Instance Id + * + * @return 0 if there is no active advertising procedure for the instance, + * 1 otherwise + * + */ +int ble_gap_ext_adv_active(uint8_t instance); #endif /* Periodic Advertising */ diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 3125870fa6..06829142b3 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -1303,6 +1303,16 @@ ble_gap_adv_active_instance(uint8_t instance) } #endif +#if MYNEWT_VAL(BLE_EXT_ADV) +int ble_gap_ext_adv_active(uint8_t instance) +{ + if (instance >= BLE_ADV_INSTANCES) { + return 0; + } + return ble_gap_adv_active_instance(instance); +} +#endif + /** * Clears advertisement and discovery state. This function is necessary * when the controller loses its active state (e.g. on stack reset). From 7f31820ea13c1632b69166477a33b3acd1ff7e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reynir=20Bj=C3=B6rnsson?= Date: Tue, 2 Nov 2021 20:59:52 +0100 Subject: [PATCH 116/306] complaint -> compliant --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index b41b1b283e..b07f1f88d0 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -46,7 +46,7 @@ ideal wireless technology for the Internet of Things (IoT). - LE Secure Connections featuring FIPS-compliant algorithms. - LE Data Length Extension for higher throughput - **Coming Soon**: Assigning an Internet Protocol (IP) address - (complaint with the IPv6 or 6LoWPAN standard) to a Bluetooth device + (compliant with the IPv6 or 6LoWPAN standard) to a Bluetooth device through Internet Protocol Support Profile (IPSP) The Bluetooth 5 is backward compatible with previous Bluetooth version From 8135e511854e3c665408cbe331e257fd7aa91226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 29 Sep 2021 08:43:39 +0200 Subject: [PATCH 117/306] apps/bttester: implement NRPA rotation As per CORE v5.3, Vol 3, Part C 10.7.1 NRPA should also rotate, same as RPA is doing right now. For time beeing let's implement this in tester application, before it's implemented in host. This affects GAP/BROB/BCST/BV-04-C --- apps/bttester/src/gap.c | 48 +++++++++++++++++++++++++++++++++++++++- apps/bttester/syscfg.yml | 4 ++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/apps/bttester/src/gap.c b/apps/bttester/src/gap.c index acac9989f0..63150e2877 100644 --- a/apps/bttester/src/gap.c +++ b/apps/bttester/src/gap.c @@ -63,6 +63,10 @@ static struct os_callout connected_ev_co; static struct gap_device_connected_ev connected_ev; #define CONNECTED_EV_DELAY_MS(itvl) 8 * BLE_HCI_CONN_ITVL * itvl / 1000 static int connection_attempts; +#if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA) +static int64_t advertising_start; +static struct os_callout bttester_nrpa_rotate_timer; +#endif static const struct ble_gap_conn_params dflt_conn_params = { .scan_itvl = 0x0010, @@ -248,6 +252,38 @@ static struct ble_gap_adv_params adv_params = { .disc_mode = BLE_GAP_DISC_MODE_NON, }; +#if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA) +static void rotate_nrpa_cb(struct os_event *ev) +{ + int rc; + ble_addr_t addr; + int32_t duration_ms = BLE_HS_FOREVER; + int32_t remaining_time; + os_time_t remaining_ticks; + + if (adv_params.disc_mode == BLE_GAP_DISC_MODE_LTD) { + duration_ms = MYNEWT_VAL(BTTESTER_LTD_ADV_TIMEOUT); + } + + ble_gap_adv_stop(); + rc = ble_hs_id_gen_rnd(1, &addr); + assert(rc == 0); + rc = ble_hs_id_set_rnd(addr.val); + assert(rc == 0); + + ble_gap_adv_start(own_addr_type, NULL, duration_ms, + &adv_params, gap_event_cb, NULL); + + remaining_time = os_get_uptime_usec() - advertising_start; + if (remaining_time > 0) { + advertising_start = os_get_uptime_usec(); + os_time_ms_to_ticks(remaining_time, &remaining_ticks); + os_callout_reset(&bttester_nrpa_rotate_timer, + remaining_ticks); + } +} +#endif + static void set_connectable(uint8_t *data, uint16_t len) { const struct gap_set_connectable_cmd *cmd = (void *) data; @@ -418,6 +454,13 @@ static void start_advertising(const uint8_t *data, uint16_t len) duration_ms = MYNEWT_VAL(BTTESTER_LTD_ADV_TIMEOUT); } +#if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA) + if (MYNEWT_VAL(BTTESTER_NRPA_TIMEOUT) < duration_ms / 1000) { + advertising_start = os_get_uptime_usec(); + os_callout_reset(&bttester_nrpa_rotate_timer, + OS_TICKS_PER_SEC * MYNEWT_VAL(BTTESTER_NRPA_TIMEOUT)); + } +#endif err = ble_gap_adv_start(own_addr_type, NULL, duration_ms, &adv_params, gap_event_cb, NULL); if (err) { @@ -1675,7 +1718,10 @@ uint8_t tester_init_gap(void) return BTP_STATUS_FAILED; } #endif - +#if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA) + os_callout_init(&bttester_nrpa_rotate_timer, os_eventq_dflt_get(), + rotate_nrpa_cb, NULL); +#endif adv_buf = NET_BUF_SIMPLE(ADV_BUF_LEN); tester_init_gap_cb(BTP_STATUS_SUCCESS); diff --git a/apps/bttester/syscfg.yml b/apps/bttester/syscfg.yml index 7f99ded013..f00afeb10f 100644 --- a/apps/bttester/syscfg.yml +++ b/apps/bttester/syscfg.yml @@ -75,6 +75,10 @@ syscfg.defs: description: Maximum MTU size the application can handle value: 230 + BTTESTER_NRPA_TIMEOUT: + description: NRPA rotation timeout in seconds + value: 5 + syscfg.vals: OS_MAIN_STACK_SIZE: 512 SHELL_TASK: 0 From 4f70d00335d70252cd54b8287883d73f1dbbd0c8 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 30 Sep 2021 19:26:05 +0200 Subject: [PATCH 118/306] nimble/ll: Fix scan window/interval limits for ext scan Max scan window and interval is different for ext scan, we should allow proper value to be used. Also change func name to have proper prefix and define values to hex values, as defined Core spec. --- nimble/controller/src/ble_ll_scan.c | 10 +++++----- nimble/include/nimble/hci_common.h | 10 ++++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 736383197a..901bda7c43 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2028,7 +2028,7 @@ ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static int -ble_ll_check_scan_params(uint8_t type, uint16_t itvl, uint16_t window) +ble_ll_scan_check_phy_params(uint8_t type, uint16_t itvl, uint16_t window) { /* Check scan type */ if ((type != BLE_HCI_SCAN_TYPE_PASSIVE) && @@ -2038,9 +2038,9 @@ ble_ll_check_scan_params(uint8_t type, uint16_t itvl, uint16_t window) /* Check interval and window */ if ((itvl < BLE_HCI_SCAN_ITVL_MIN) || - (itvl > BLE_HCI_SCAN_ITVL_MAX) || + (itvl > BLE_HCI_SCAN_ITVL_MAX_EXT) || (window < BLE_HCI_SCAN_WINDOW_MIN) || - (window > BLE_HCI_SCAN_WINDOW_MAX) || + (window > BLE_HCI_SCAN_WINDOW_MAX_EXT) || (itvl < window)) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -2098,7 +2098,7 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) interval = le16toh(params->itvl); window = le16toh(params->window); - rc = ble_ll_check_scan_params(params->type, interval, window); + rc = ble_ll_scan_check_phy_params(params->type, interval, window); if (rc) { return rc; } @@ -2122,7 +2122,7 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) interval = le16toh(params->itvl); window = le16toh(params->window); - rc = ble_ll_check_scan_params(params->type, interval, window); + rc = ble_ll_scan_check_phy_params(params->type, interval, window); if (rc) { return rc; } diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 92031c3c16..9acb76238f 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -1152,11 +1152,13 @@ struct ble_hci_vs_rd_static_addr_rp { /* Scan interval and scan window timing */ #define BLE_HCI_SCAN_ITVL (625) /* usecs */ -#define BLE_HCI_SCAN_ITVL_MIN (4) /* units */ -#define BLE_HCI_SCAN_ITVL_MAX (16384) /* units */ +#define BLE_HCI_SCAN_ITVL_MIN (0x0004) /* units */ +#define BLE_HCI_SCAN_ITVL_MAX (0x4000) /* units */ +#define BLE_HCI_SCAN_ITVL_MAX_EXT (0xffff) /* units */ #define BLE_HCI_SCAN_ITVL_DEF (16) /* units */ -#define BLE_HCI_SCAN_WINDOW_MIN (4) /* units */ -#define BLE_HCI_SCAN_WINDOW_MAX (16384) /* units */ +#define BLE_HCI_SCAN_WINDOW_MIN (0x0004) /* units */ +#define BLE_HCI_SCAN_WINDOW_MAX (0x4000) /* units */ +#define BLE_HCI_SCAN_WINDOW_MAX_EXT (0xffff) /* units */ #define BLE_HCI_SCAN_WINDOW_DEF (16) /* units */ /* From 7875bc285575ada3e29f47019ba6a2129f4d417f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 30 Sep 2021 19:33:38 +0200 Subject: [PATCH 119/306] nimble/ll: Cleanup function names Use common prefix ble_ll_scan_hci for all HCI commands handlers in ble_ll_scan. --- nimble/controller/include/controller/ble_ll_scan.h | 8 ++++---- nimble/controller/src/ble_ll_hci.c | 8 ++++---- nimble/controller/src/ble_ll_scan.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index 04ca48177b..77f9fa4265 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -163,14 +163,14 @@ struct ble_ll_scan_sm /*---- HCI ----*/ /* Set scanning parameters */ -int ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_scan_hci_set_params(const uint8_t *cmdbuf, uint8_t len); /* Turn scanning on/off */ -int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_scan_hci_set_enable(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_scan_hci_set_ext_enable(const uint8_t *cmdbuf, uint8_t len); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_scan_hci_set_ext_params(const uint8_t *cmdbuf, uint8_t len); #endif /*--- Controller Internal API ---*/ diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 547b661594..c2603c989d 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -904,10 +904,10 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_hci_adv_set_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_SCAN_PARAMS: - rc = ble_ll_scan_set_scan_params(cmdbuf, len); + rc = ble_ll_scan_hci_set_params(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_SCAN_ENABLE: - rc = ble_ll_hci_scan_set_enable(cmdbuf, len); + rc = ble_ll_scan_hci_set_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_CREATE_CONN: rc = ble_ll_conn_hci_create(cmdbuf, len); @@ -1107,10 +1107,10 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM: - rc = ble_ll_set_ext_scan_params(cmdbuf, len); + rc = ble_ll_scan_hci_set_ext_params(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE: - rc = ble_ll_hci_ext_scan_set_enable(cmdbuf, len); + rc = ble_ll_scan_hci_set_ext_enable(cmdbuf, len); break; case BLE_HCI_OCF_LE_EXT_CREATE_CONN: rc = ble_ll_conn_hci_ext_create(cmdbuf, len); diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 901bda7c43..8539257c2a 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -1961,7 +1961,7 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd } int -ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len) +ble_ll_scan_hci_set_params(const uint8_t *cmdbuf, uint8_t len) { const struct ble_hci_le_set_scan_params_cp *cmd = (const void *)cmdbuf; uint16_t scan_itvl; @@ -2049,7 +2049,7 @@ ble_ll_scan_check_phy_params(uint8_t type, uint16_t itvl, uint16_t window) } int -ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len) +ble_ll_scan_hci_set_ext_params(const uint8_t *cmdbuf, uint8_t len) { const struct ble_hci_le_set_ext_scan_params_cp *cmd = (const void *) cmdbuf; const struct scan_params *params = cmd->scans; @@ -2361,7 +2361,7 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, return rc; } -int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) +int ble_ll_scan_hci_set_enable(const uint8_t *cmdbuf, uint8_t len) { const struct ble_hci_le_set_scan_enable_cp *cmd = (const void *) cmdbuf; @@ -2374,7 +2374,7 @@ int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len) +int ble_ll_scan_hci_set_ext_enable(const uint8_t *cmdbuf, uint8_t len) { const struct ble_hci_le_set_ext_scan_enable_cp *cmd = (const void *) cmdbuf; From 9559689bc076bb1a46be78f56a7c302609324b22 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Thu, 23 Sep 2021 06:29:19 +1000 Subject: [PATCH 120/306] nimble: Fix a few types in many places --- apps/blecsc/src/main.c | 2 +- docs/btshell/btshell_GAP.rst | 2 +- nimble/controller/src/ble_ll_adv.c | 2 +- nimble/controller/src/ble_ll_conn.c | 4 ++-- nimble/drivers/nrf51/src/ble_phy.c | 4 ++-- nimble/drivers/nrf52/src/ble_phy.c | 2 +- nimble/host/mesh/src/pb_adv.c | 2 +- nimble/host/mesh/src/subnet.h | 2 +- nimble/host/src/ble_att_svr.c | 2 +- nimble/host/src/ble_gap.c | 2 +- nimble/host/src/ble_sm_lgcy.c | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/blecsc/src/main.c b/apps/blecsc/src/main.c index 60f0b3d8f7..5cca6b77ec 100644 --- a/apps/blecsc/src/main.c +++ b/apps/blecsc/src/main.c @@ -58,7 +58,7 @@ static struct os_callout blecsc_measure_timer; /* Variable holds current CSC measurement state */ static struct ble_csc_measurement_state csc_measurement_state; -/* Variable holds simulted speed (kilometers per hour) */ +/* Variable holds simulated speed (kilometers per hour) */ static uint16_t csc_sim_speed_kph = CSC_SIM_SPEED_KPH_MIN; /* Variable holds simulated cadence (RPM) */ diff --git a/docs/btshell/btshell_GAP.rst b/docs/btshell/btshell_GAP.rst index ce6475554d..738d146c5b 100644 --- a/docs/btshell/btshell_GAP.rst +++ b/docs/btshell/btshell_GAP.rst @@ -411,7 +411,7 @@ Advertising with Extended Advertising enabled +------------------------------+--------------------------+----------------------------+-------------------------------------------------------------------------------------+ | | scan\_req\_notif | [``0``-1] | Enable SCAN\_REQ notifications | +------------------------------+--------------------------+----------------------------+-------------------------------------------------------------------------------------+ -| **advertise-set-addr** | | | Configure *random* adress for instance | +| **advertise-set-addr** | | | Configure *random* address for instance | +------------------------------+--------------------------+----------------------------+-------------------------------------------------------------------------------------+ | | instance | [``0``-UINT8\_MAX] | Advertising instance | +------------------------------+--------------------------+----------------------------+-------------------------------------------------------------------------------------+ diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 19270accde..88c4ae12b1 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -4479,7 +4479,7 @@ ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) #endif /* - * It is possible that advertising was stopped and a packet plcaed on the + * It is possible that advertising was stopped and a packet placed on the * LL receive packet queue. In this case, just ignore the received packet * as the advertising state machine is no longer "valid" */ diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 08bc1fca27..55ca20e900 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -3163,7 +3163,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) /* * Check the packet CRC. A connection event can continue even if the * received PDU does not pass the CRC check. If we receive two consecutive - * CRC errors we end the conection event. + * CRC errors we end the connection event. */ if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) { /* @@ -3753,7 +3753,7 @@ ble_ll_conn_module_init(void) uint16_t i; struct ble_ll_conn_sm *connsm; - /* Initialize list of active conections */ + /* Initialize list of active connections */ SLIST_INIT(&g_ble_ll_conn_active_list); STAILQ_INIT(&g_ble_ll_conn_free_list); diff --git a/nimble/drivers/nrf51/src/ble_phy.c b/nimble/drivers/nrf51/src/ble_phy.c index b7e6329721..d3bc3c2ecc 100644 --- a/nimble/drivers/nrf51/src/ble_phy.c +++ b/nimble/drivers/nrf51/src/ble_phy.c @@ -408,7 +408,7 @@ ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs) /** * Function is used to set PPI so that we can time out waiting for a reception * to occur. This happens for two reasons: we have sent a packet and we are - * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are + * waiting for a response (txrx should be set to ENABLE_TXRX) or we are * starting a connection event and we are a slave and we are waiting for the * master to send us a packet (txrx should be set to ENABLE_RX). * @@ -1357,7 +1357,7 @@ ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) NRF_RADIO->RXADDRESSES = (1 << 1); NRF_RADIO->CRCINIT = crcinit; } else { - /* Logical adddress 0 preconfigured */ + /* Logical address 0 preconfigured */ NRF_RADIO->TXADDRESS = 0; NRF_RADIO->RXADDRESSES = (1 << 0); NRF_RADIO->CRCINIT = BLE_LL_CRCINIT_ADV; diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c index 2f6ce08e72..6c520ab8b8 100644 --- a/nimble/drivers/nrf52/src/ble_phy.c +++ b/nimble/drivers/nrf52/src/ble_phy.c @@ -669,7 +669,7 @@ ble_phy_set_start_now(void) /** * Function is used to set PPI so that we can time out waiting for a reception * to occur. This happens for two reasons: we have sent a packet and we are - * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are + * waiting for a response (txrx should be set to ENABLE_TXRX) or we are * starting a connection event and we are a slave and we are waiting for the * master to send us a packet (txrx should be set to ENABLE_RX). * diff --git a/nimble/host/mesh/src/pb_adv.c b/nimble/host/mesh/src/pb_adv.c index 653ec03fa9..50b8419e10 100644 --- a/nimble/host/mesh/src/pb_adv.c +++ b/nimble/host/mesh/src/pb_adv.c @@ -845,7 +845,7 @@ static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data) link.cb = cb; link.cb_data = cb_data; - /* Make sure we're scanning for provisioning inviations */ + /* Make sure we're scanning for provisioning invitations */ bt_mesh_scan_enable(); /* Enable unprovisioned beacon sending */ bt_mesh_beacon_enable(); diff --git a/nimble/host/mesh/src/subnet.h b/nimble/host/mesh/src/subnet.h index 154b5d4e31..7a82999789 100644 --- a/nimble/host/mesh/src/subnet.h +++ b/nimble/host/mesh/src/subnet.h @@ -37,7 +37,7 @@ struct bt_mesh_subnet { uint8_t beacons_last; /* Number of beacons during last * observation window */ - uint8_t beacons_cur; /* Number of beaconds observed during + uint8_t beacons_cur; /* Number of beacons observed during * currently ongoing window. */ diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index 4fdf27e843..9af0e0d043 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -30,7 +30,7 @@ * ATT server - Attribute Protocol * * Notes on buffer reuse: - * Most request handlers reuse the request buffer for the reponse. This is + * Most request handlers reuse the request buffer for the response. This is * done to prevent out-of-memory conditions. However, there are two handlers * which do not reuse the request buffer: * 1. Write request. diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 06829142b3..8f7e5ca60a 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -5784,7 +5784,7 @@ ble_gap_enc_event(uint16_t conn_handle, int status, return; } - /* If encryption succeded and encryption has been restored for bonded device, + /* If encryption succeeded and encryption has been restored for bonded device, * notify gatt server so it has chance to send notification/indication if needed. */ if (security_restored) { diff --git a/nimble/host/src/ble_sm_lgcy.c b/nimble/host/src/ble_sm_lgcy.c index 0259ff4682..1a500fb746 100644 --- a/nimble/host/src/ble_sm_lgcy.c +++ b/nimble/host/src/ble_sm_lgcy.c @@ -36,7 +36,7 @@ #define IOACT_INPUT BLE_SM_IOACT_INPUT #define IOACT_DISP BLE_SM_IOACT_DISP -/* This is the initiator passkey action action dpeneding on the io +/* This is the initiator passkey action action depending on the io * capabilties of both parties */ static const uint8_t ble_sm_lgcy_init_ioa[5 /*resp*/ ][5 /*init*/ ] = From b67d108e943b6359512338d8f8bd12366dd006b2 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 4 Oct 2021 14:01:44 +0200 Subject: [PATCH 121/306] nimble/ll: Fix return values from scheduler callbacks Make sure we use 'running' and 'done' properly. This did not matter so far since return value from sched_cb is not used anywhere, but this is going to change. --- nimble/controller/src/ble_ll_dtm.c | 5 +++-- nimble/controller/src/ble_ll_scan_aux.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/nimble/controller/src/ble_ll_dtm.c b/nimble/controller/src/ble_ll_dtm.c index de3b168b22..8c9167799a 100644 --- a/nimble/controller/src/ble_ll_dtm.c +++ b/nimble/controller/src/ble_ll_dtm.c @@ -261,7 +261,7 @@ ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch) ble_ll_state_set(BLE_LL_STATE_DTM); - return BLE_LL_SCHED_STATE_DONE; + return BLE_LL_SCHED_STATE_RUNNING; resched: /* Reschedule from LL task if late for this PDU */ @@ -427,9 +427,10 @@ ble_ll_dtm_rx_sched_cb(struct ble_ll_sched_item *sch) if (ble_ll_dtm_rx_start() != 0) { ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); STATS_INC(ble_ll_dtm_stats, rx_failed); + return BLE_LL_SCHED_STATE_DONE; } - return BLE_LL_SCHED_STATE_DONE; + return BLE_LL_SCHED_STATE_RUNNING; } static int diff --git a/nimble/controller/src/ble_ll_scan_aux.c b/nimble/controller/src/ble_ll_scan_aux.c index 94f776df9b..a521679a20 100644 --- a/nimble/controller/src/ble_ll_scan_aux.c +++ b/nimble/controller/src/ble_ll_scan_aux.c @@ -163,7 +163,7 @@ ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch) ble_ll_state_set(BLE_LL_STATE_SCAN_AUX); - return BLE_LL_SCHED_STATE_DONE; + return BLE_LL_SCHED_STATE_RUNNING; } static struct ble_ll_scan_aux_data * From 7f63bd094e0ae5a3596b36fc9a116c1bf52330fb Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 6 Oct 2021 09:58:16 +0200 Subject: [PATCH 122/306] nimble/ll: Optimize sched restart When sched_q head changed we only should stop sched timer to make sure it does not fire after we leave critical section and we can restart it then without need for additional locking. We do not need to change rfmgmt because in case new sched_q head is later then previous one, rfmgmt will fire too early and we'll either disable it immediately on restart or keep it enabled for upcoming item, depending on timing. --- nimble/controller/src/ble_ll_sched.c | 31 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index 03dea23a73..7a2e6f3a1c 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -37,7 +37,6 @@ #define BLE_LL_SCHED_MAX_DELAY_ANY (0x7fffffff) static struct hal_timer g_ble_ll_sched_timer; -static uint8_t g_ble_ll_sched_timer_running; uint8_t g_ble_ll_sched_offset_ticks; @@ -63,6 +62,7 @@ typedef int (* ble_ll_sched_preempt_cb_t)(struct ble_ll_sched_item *sch, /* Queue for timers */ static TAILQ_HEAD(ll_sched_qhead, ble_ll_sched_item) g_ble_ll_sched_q; +static uint8_t g_ble_ll_sched_q_head_changed; #if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING) struct ble_ll_sched_obj g_ble_ll_sched_data; @@ -155,13 +155,13 @@ ble_ll_sched_preempt(struct ble_ll_sched_item *sch, static inline void ble_ll_sched_q_head_changed(void) { - struct ble_ll_sched_item *first; + if (g_ble_ll_sched_q_head_changed) { + return; + } - g_ble_ll_sched_timer_running = 0; - os_cputime_timer_stop(&g_ble_ll_sched_timer); + g_ble_ll_sched_q_head_changed = 1; - first = TAILQ_FIRST(&g_ble_ll_sched_q); - ble_ll_rfmgmt_sched_changed(first); + os_cputime_timer_stop(&g_ble_ll_sched_timer); } static inline void @@ -169,10 +169,17 @@ ble_ll_sched_restart(void) { struct ble_ll_sched_item *first; + if (!g_ble_ll_sched_q_head_changed) { + return; + } + + g_ble_ll_sched_q_head_changed = 0; + first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (!g_ble_ll_sched_timer_running && first) { - g_ble_ll_sched_timer_running = 1; + ble_ll_rfmgmt_sched_changed(first); + + if (first) { os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time); } } @@ -1182,8 +1189,6 @@ ble_ll_sched_run(void *arg) BLE_LL_DEBUG_GPIO(SCHED_RUN, 1); - g_ble_ll_sched_timer_running = 0; - /* Look through schedule queue */ sch = TAILQ_FIRST(&g_ble_ll_sched_q); if (sch) { @@ -1203,7 +1208,10 @@ ble_ll_sched_run(void *arg) /* Remove schedule item and execute the callback */ TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link); sch->enqueued = 0; + g_ble_ll_sched_q_head_changed = 1; + ble_ll_sched_execute_item(sch); + ble_ll_sched_restart(); } @@ -1295,7 +1303,6 @@ int ble_ll_sched_dtm(struct ble_ll_sched_item *sch) void ble_ll_sched_stop(void) { - g_ble_ll_sched_timer_running = 0; os_cputime_timer_stop(&g_ble_ll_sched_timer); } @@ -1338,5 +1345,7 @@ ble_ll_sched_init(void) g_ble_ll_sched_data.sch_ticks_per_period; #endif + g_ble_ll_sched_q_head_changed = 0; + return 0; } From ed4563741cf75353105fa6ae42a997343b1152ad Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 3 Nov 2021 13:36:34 +0100 Subject: [PATCH 123/306] nimble/ll: Add fast path for aux chain scheduling For short aux offsets we can to usecs to ticks conversion using only 32-bit arithmetics without integer division. This is much faster than generic routine, especially on M0 (e.g. CMAC) which does not have hw support for integer division. The faster calculation is even more accurate than generic one since it's never off by 1 tick. This is a temporary solution until we have more generic timer routines that do the same kind of optimizations. --- nimble/controller/src/ble_ll_sched.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index 7a2e6f3a1c..5217557851 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -786,6 +786,22 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm) return rc; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +static inline uint32_t +usecs_to_ticks_fast(uint32_t usecs) +{ + uint32_t ticks; + + if (usecs <= 31249) { + ticks = (usecs * 137439) / 4194304; + } else { + ticks = os_cputime_usecs_to_ticks(usecs); + } + + return ticks; +} +#endif + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) /* * Determines if the schedule item overlaps the currently running schedule @@ -887,7 +903,7 @@ ble_ll_sched_sync(struct ble_ll_sched_item *sch, os_sr_t sr; int rc = 0; - off_ticks = os_cputime_usecs_to_ticks(offset); + off_ticks = usecs_to_ticks_fast(offset); off_rem_usecs = offset - os_cputime_ticks_to_usecs(off_ticks); start_time = beg_cputime + off_ticks; @@ -899,7 +915,7 @@ ble_ll_sched_sync(struct ble_ll_sched_item *sch, dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN), phy_mode); - end_time = start_time + os_cputime_usecs_to_ticks(dur); + end_time = start_time + usecs_to_ticks_fast(dur); start_time -= g_ble_ll_sched_offset_ticks; @@ -1257,12 +1273,12 @@ ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, int rc; offset_us += pdu_time_rem; - offset_ticks = os_cputime_usecs_to_ticks(offset_us); + offset_ticks = usecs_to_ticks_fast(offset_us); sch->start_time = pdu_time + offset_ticks - g_ble_ll_sched_offset_ticks; sch->remainder = offset_us - os_cputime_ticks_to_usecs(offset_ticks); /* TODO: make some sane slot reservation */ - sch->end_time = sch->start_time + os_cputime_usecs_to_ticks(5000); + sch->end_time = sch->start_time + usecs_to_ticks_fast(5000); OS_ENTER_CRITICAL(sr); From 5271e1f95586f479fd546fe5ed3acdc920951c3c Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 2 Nov 2021 17:32:20 +0100 Subject: [PATCH 124/306] nimble/ll: Add debugging for sched active item This replaces sched_item_cb debug GPIO with sched_item that is set to high state for the entire duration of sched item active time, i.e. from sched run to LL standby. Note that sched_item_cb debugging is not that useful since it's almost the same as sched_run, so we better replace it instead of keeping both to avoid syscfg clutter. --- nimble/controller/src/ble_ll.c | 5 +++++ nimble/controller/src/ble_ll_sched.c | 9 ++++++--- nimble/controller/syscfg.yml | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 014f7e2809..1a8e4622c3 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -45,6 +45,7 @@ #include "controller/ble_ll_trace.h" #include "controller/ble_ll_sync.h" #include "ble_ll_conn_priv.h" +#include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_DTM) #include "ble_ll_dtm_priv.h" @@ -1241,6 +1242,10 @@ void ble_ll_state_set(uint8_t ll_state) { g_ble_ll_data.ll_state = ll_state; + + if (ll_state == BLE_LL_STATE_STANDBY) { + BLE_LL_DEBUG_GPIO(SCHED_ITEM, 0); + } } /** diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index 5217557851..0a9be9c8ae 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -1183,11 +1183,14 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) } sched: - BLE_LL_DEBUG_GPIO(SCHED_ITEM_CB, 1); BLE_LL_ASSERT(sch->sched_cb); + BLE_LL_DEBUG_GPIO(SCHED_ITEM, 1); rc = sch->sched_cb(sch); - BLE_LL_DEBUG_GPIO(SCHED_ITEM_CB, 0); + if (rc != BLE_LL_SCHED_STATE_RUNNING) { + BLE_LL_DEBUG_GPIO(SCHED_ITEM, 0); + } + return rc; } @@ -1331,7 +1334,7 @@ ble_ll_sched_stop(void) int ble_ll_sched_init(void) { - BLE_LL_DEBUG_GPIO_INIT(SCHED_ITEM_CB); + BLE_LL_DEBUG_GPIO_INIT(SCHED_ITEM); BLE_LL_DEBUG_GPIO_INIT(SCHED_RUN); /* diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index b1fb6b1fb9..13b6780c1b 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -367,10 +367,10 @@ syscfg.defs: GPIO pin number to debug scheduler running (on timer). Pin is set to high state while scheduler is running. value: -1 - BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB: + BLE_LL_DEBUG_GPIO_SCHED_ITEM: description: > GPIO pin number to debug scheduler item execution times. Pin is set - to high state while item is executed. + to high state while item is active. value: -1 BLE_LL_DEBUG_GPIO_RFMGMT: description: > From 5cb95b3951e53c1975c7eb5be52ac9b8ec959754 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 3 Nov 2021 13:38:17 +0100 Subject: [PATCH 125/306] nimble/ll: Use get_le24 to read AuxPtr No need to read more bytes and discard bits, we have helper that reads exactly 24 bits :) --- nimble/controller/src/ble_ll_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c index f121c286b0..e4ca5edd80 100644 --- a/nimble/controller/src/ble_ll_sync.c +++ b/nimble/controller/src/ble_ll_sync.c @@ -863,7 +863,7 @@ static void ble_ll_sync_parse_aux_ptr(const uint8_t *buf, uint8_t *chan, uint32_t *offset, uint8_t *offset_units, uint8_t *phy) { - uint32_t aux_ptr_field = get_le32(buf) & 0x00FFFFFF; + uint32_t aux_ptr_field = get_le24(buf); *chan = aux_ptr_field & 0x3F; From 47cabcd893bdcb98842190911ff31fad0658a57e Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 3 Nov 2021 13:44:45 +0100 Subject: [PATCH 126/306] nimble/ll: Remove magic number --- nimble/controller/src/ble_ll_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c index e4ca5edd80..4b2004953d 100644 --- a/nimble/controller/src/ble_ll_sync.c +++ b/nimble/controller/src/ble_ll_sync.c @@ -581,7 +581,7 @@ ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power, /* Ignore CTE for now */ if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_CTE_INFO_BIT)) { - i += 1; + i += BLE_LL_EXT_ADV_CTE_INFO_SIZE; } /* there should be no ADI in Sync or chain, skip it */ From 5e6bb6f878ccf7a3bcc7c10cf025de0ca5ff8762 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 8 Nov 2021 15:07:26 +0100 Subject: [PATCH 127/306] apps/blestress: Fix tx_stress_13 We should not free mbuf in BLE_GAP_EVENT_NOTIFY_RX since it's freed by host after returning from event callback. --- apps/blestress/src/tx_stress.c | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/blestress/src/tx_stress.c b/apps/blestress/src/tx_stress.c index 4416c568cb..217d5b5d1b 100644 --- a/apps/blestress/src/tx_stress.c +++ b/apps/blestress/src/tx_stress.c @@ -1271,7 +1271,6 @@ tx_stress_13_gap_event(struct ble_gap_event *event, void *arg) case BLE_GAP_EVENT_NOTIFY_RX: MODLOG_DFLT(INFO, "Notify RX event\n"); console_printf("\033[0;32m>\033[0m"); - os_mbuf_free_chain(event->notify_rx.om); ++tx_stress_ctx->rcv_num; return 0; From 0b36c1ac0328d01761a64613c15f296c27865b1a Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 8 Nov 2021 15:37:19 +0100 Subject: [PATCH 128/306] apps/blestress: Fix log in tx_stress_14 --- apps/blestress/src/tx_stress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/blestress/src/tx_stress.c b/apps/blestress/src/tx_stress.c index 217d5b5d1b..1711f9fbf8 100644 --- a/apps/blestress/src/tx_stress.c +++ b/apps/blestress/src/tx_stress.c @@ -1389,7 +1389,7 @@ tx_stress_14_gap_event(struct ble_gap_event *event, void *arg) if (++tx_stress_ctx->rcv_num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) { rc = ble_gap_terminate(event->notify_rx.conn_handle, BLE_ERR_REM_USER_CONN_TERM); - MODLOG_DFLT(INFO, "rc=%d\n"); + MODLOG_DFLT(INFO, "rc=%d\n", rc); assert(rc == 0); return 0; } From 33aa9b4612abaab7e6627c932e73b6f67dfa2294 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 5 Nov 2021 15:10:36 +0100 Subject: [PATCH 129/306] nimble/ll: Ignore aux PDUs while not ext scanning We do not really want to process aux PDUs when using legacy scanning. --- nimble/controller/src/ble_ll_scan.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 8539257c2a..e99f431717 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -1928,6 +1928,22 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd struct ble_ll_scan_sm *scansm; struct ble_ll_scan_addr_data addrd; uint8_t *targeta; + uint8_t max_pdu_type; + + scansm = &g_ble_ll_scan_sm; + rxinfo = &hdr->rxinfo; + + /* Ignore PDUs we do not expect here */ + max_pdu_type = BLE_ADV_PDU_TYPE_ADV_SCAN_IND; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (scansm->ext_scanning) { + /* Note: We do not expect AUX_CONNECT_RSP here */ + max_pdu_type = BLE_ADV_PDU_TYPE_ADV_EXT_IND; + } +#endif + if (ptype > max_pdu_type) { + return; + } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { @@ -1937,9 +1953,6 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd } #endif - scansm = &g_ble_ll_scan_sm; - rxinfo = &hdr->rxinfo; - if (scansm->scanp->scan_type == BLE_SCAN_TYPE_INITIATE) { if (rxinfo->flags & BLE_MBUF_HDR_F_CONNECT_IND_TXD) { /* We need to keep original TargetA in case it was resolved, so rl From e7507652387ebbd9f8c83ec594721d6a1bdce871 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 5 Nov 2021 15:26:54 +0100 Subject: [PATCH 130/306] nimble/ll: Fix aux handling in initiator If AUX_ADV_IND is ignored due to address mismatch in initiator it should be marked as ignored, otherwise LL will assert since it assumes that while initiating any valid PDU is either AUX_CONNECT_RSP or it was an AUX_ADV_IND with AUX_CONNECT_REQ sent. In our case it will be an AUX_ADV_IND without AUX_CONNECT_REQ sent... --- nimble/controller/src/ble_ll_scan_aux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nimble/controller/src/ble_ll_scan_aux.c b/nimble/controller/src/ble_ll_scan_aux.c index a521679a20..477fa81241 100644 --- a/nimble/controller/src/ble_ll_scan_aux.c +++ b/nimble/controller/src/ble_ll_scan_aux.c @@ -1306,6 +1306,7 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) !(scan_filt_policy & 0x01)) { rc = ble_ll_scan_rx_check_init(&addrd); if (rc < 0) { + rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; goto done; } } From 3153e2057607a53f022c5a9675618305afe2b43a Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 5 Nov 2021 15:39:58 +0100 Subject: [PATCH 131/306] nimble/ll: Fix LE Coded scan parameters handling Make sure we only try to setup LE Coded in scanner if both ext adv (i.e. also ext scan) and LE Coded PHY are enabled. --- nimble/controller/src/ble_ll_scan.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index e99f431717..47b7d0bd7f 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2069,7 +2069,9 @@ ble_ll_scan_hci_set_ext_params(const uint8_t *cmdbuf, uint8_t len) struct ble_ll_scan_phy new_params[BLE_LL_SCAN_PHY_NUMBER] = { }; struct ble_ll_scan_phy *uncoded = &new_params[PHY_UNCODED]; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) struct ble_ll_scan_phy *coded = &new_params[PHY_CODED]; +#endif uint16_t interval; uint16_t window; int rc; @@ -2147,7 +2149,6 @@ ble_ll_scan_hci_set_ext_params(const uint8_t *cmdbuf, uint8_t len) /* That means user wants to use this PHY for scanning */ coded->configured = 1; } -#endif /* if any of PHYs is configured for continuous scan we alter interval to * fit other PHY @@ -2161,6 +2162,7 @@ ble_ll_scan_hci_set_ext_params(const uint8_t *cmdbuf, uint8_t len) uncoded->timing.interval += coded->timing.window; } } +#endif g_ble_ll_scan_params.own_addr_type = cmd->own_addr_type; g_ble_ll_scan_params.scan_filt_policy = cmd->filter_policy; @@ -2429,7 +2431,7 @@ ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext, { struct ble_ll_scan_sm *scansm; struct ble_ll_scan_phy *scanp_uncoded; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) struct ble_ll_scan_phy *scanp_coded; #endif uint8_t init_phy_mask; @@ -2461,7 +2463,7 @@ ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext, scanp_uncoded->configured = 0; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) scanp_coded = &scansm->scan_phys[PHY_CODED]; if (init_phy_mask & BLE_PHY_MASK_CODED) { scanp_coded->configured = 1; From 99942496b6a47efa1f45b5cd4b6726e38b7c4cfc Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 5 Nov 2021 15:51:01 +0100 Subject: [PATCH 132/306] nimble/ll: Fix rx abort on aux scan If rx on aux scan is aborted, we need to set LL back to standby. --- nimble/controller/src/ble_ll_scan_aux.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nimble/controller/src/ble_ll_scan_aux.c b/nimble/controller/src/ble_ll_scan_aux.c index 477fa81241..f1e56bd3eb 100644 --- a/nimble/controller/src/ble_ll_scan_aux.c +++ b/nimble/controller/src/ble_ll_scan_aux.c @@ -764,6 +764,7 @@ ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr) if (pdu_type != BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP) { aux_data_current = NULL; ble_ll_scan_aux_break(aux); + ble_ll_state_set(BLE_LL_STATE_STANDBY); return -1; } return 0; @@ -772,6 +773,7 @@ ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr) if (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) { aux_data_current = NULL; ble_ll_scan_aux_break(aux); + ble_ll_state_set(BLE_LL_STATE_STANDBY); return -1; } From 17a724066414d76675d5d756c994048a43d5fda9 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 8 Nov 2021 13:48:17 +0100 Subject: [PATCH 133/306] nimble/ll: Fix starting ctrl proc timer We cannot just initialize callout prior to restarting since this will wipe it out and thus break callouts queue if it was already added there. Instead, initialize once on module init. --- nimble/controller/src/ble_ll_conn.c | 4 +++ nimble/controller/src/ble_ll_ctrl.c | 12 ++++---- nimble/controller/src/ble_ll_ctrl_priv.h | 35 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 nimble/controller/src/ble_ll_ctrl_priv.h diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 55ca20e900..ebeddd7498 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -40,6 +40,7 @@ #include "controller/ble_phy.h" #include "controller/ble_ll_utils.h" #include "ble_ll_conn_priv.h" +#include "ble_ll_ctrl_priv.h" #if (BLETEST_THROUGHPUT_TEST == 1) extern void bletest_completed_pkt(uint16_t handle); @@ -3772,6 +3773,9 @@ ble_ll_conn_module_init(void) /* Initialize fixed schedule elements */ connsm->conn_sch.sched_type = BLE_LL_SCHED_TYPE_CONN; connsm->conn_sch.cb_arg = connsm; + + ble_ll_ctrl_init_conn_sm(connsm); + ++connsm; } diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c index 7ef63d132d..b6c6036ec1 100644 --- a/nimble/controller/src/ble_ll_ctrl.c +++ b/nimble/controller/src/ble_ll_ctrl.c @@ -559,11 +559,6 @@ ble_ll_ctrl_proc_rsp_timer_cb(struct ble_npl_event *ev) static void ble_ll_ctrl_start_rsp_timer(struct ble_ll_conn_sm *connsm) { - ble_npl_callout_init(&connsm->ctrl_proc_rsp_timer, - &g_ble_ll_data.ll_evq, - ble_ll_ctrl_proc_rsp_timer_cb, - connsm); - /* Re-start timer. Control procedure timeout is 40 seconds */ ble_npl_callout_reset(&connsm->ctrl_proc_rsp_timer, ble_npl_time_ms_to_ticks32(BLE_LL_CTRL_PROC_TIMEOUT_MS)); @@ -2886,3 +2881,10 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) os_mbuf_free_chain(txpdu); return rc; } + +void +ble_ll_ctrl_init_conn_sm(struct ble_ll_conn_sm *connsm) +{ + ble_npl_callout_init(&connsm->ctrl_proc_rsp_timer, &g_ble_ll_data.ll_evq, + ble_ll_ctrl_proc_rsp_timer_cb, connsm); +} diff --git a/nimble/controller/src/ble_ll_ctrl_priv.h b/nimble/controller/src/ble_ll_ctrl_priv.h new file mode 100644 index 0000000000..ca1c83d390 --- /dev/null +++ b/nimble/controller/src/ble_ll_ctrl_priv.h @@ -0,0 +1,35 @@ +/* + * 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_CTRL_PRIV_ +#define H_BLE_LL_CTRL_PRIV_ + +#include "controller/ble_ll_conn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void ble_ll_ctrl_init_conn_sm(struct ble_ll_conn_sm *connsm); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_CTRL_PRIV_ */ From 513ea2738655bb10010dcf1d7e646b6e1ed3a355 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 8 Nov 2021 11:23:14 +0100 Subject: [PATCH 134/306] Revert "nimble/ll: Fix encrypted data PDU payload length calculation" This reverts commit c185dd6719b1cc9e08abada79e16e866118d3501. --- nimble/controller/src/ble_ll_conn.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index ebeddd7498..20b578aa7b 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -855,7 +855,6 @@ static uint16_t ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) { uint16_t phy_max_tx_octets; - uint16_t mic_len; uint16_t ret; #if (BLE_LL_BT5_PHY_SUPPORTED == 1) @@ -878,19 +877,11 @@ ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) ret = pyld_len; - mic_len = 0; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (CONN_F_ENCRYPTED(connsm)) { - mic_len = BLE_LL_DATA_MIC_LEN; - } -#endif - - - if (ret > connsm->eff_max_tx_octets - mic_len) { + if (ret > connsm->eff_max_tx_octets) { ret = connsm->eff_max_tx_octets; } - if (ret > phy_max_tx_octets - mic_len) { + if (ret > phy_max_tx_octets) { ret = phy_max_tx_octets; } From 4a89a4c5cb1a33e8eae3c01a2108fedfb7eb180e Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 8 Nov 2021 11:23:31 +0100 Subject: [PATCH 135/306] nimble/ll: Fix encrypted payload length ble_ll_pdu_max_tx_octets_get() returns number of bytes that can be added between LL header and CRC so the complete PDU is no longer than maxTxTime allowed. However, if link is encrypted there will be also MIC added after the payload so effectively we need to stript that extra 4 bytes from allowed payload length. --- nimble/controller/src/ble_ll_conn.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 20b578aa7b..30a381e1ec 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -854,7 +854,7 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) static uint16_t ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) { - uint16_t phy_max_tx_octets; + uint16_t max_pyld_len; uint16_t ret; #if (BLE_LL_BT5_PHY_SUPPORTED == 1) @@ -867,22 +867,28 @@ ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) phy_mode = connsm->phy_data.tx_phy_mode; } - phy_max_tx_octets = ble_ll_pdu_max_tx_octets_get(connsm->eff_max_tx_time, - phy_mode); + max_pyld_len = ble_ll_pdu_max_tx_octets_get(connsm->eff_max_tx_time, + phy_mode); #else - phy_max_tx_octets = ble_ll_pdu_max_tx_octets_get(connsm->eff_max_tx_time, - BLE_PHY_MODE_1M); + max_pyld_len = ble_ll_pdu_max_tx_octets_get(connsm->eff_max_tx_time, + BLE_PHY_MODE_1M); #endif ret = pyld_len; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (CONN_F_ENCRYPTED(connsm)) { + max_pyld_len -= BLE_LL_DATA_MIC_LEN; + } +#endif + if (ret > connsm->eff_max_tx_octets) { ret = connsm->eff_max_tx_octets; } - if (ret > phy_max_tx_octets) { - ret = phy_max_tx_octets; + if (ret > max_pyld_len) { + ret = max_pyld_len; } return ret; From 91c5d9a39319b31b81d6655f4dec16e06259cd4a Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Sat, 6 Nov 2021 00:45:44 +0100 Subject: [PATCH 136/306] nimble/ll: Add more convenient way to set pub dev addr This adds BLE_LL_PUBLIC_DEV_ADDR which allows to conveniently set public device address as 48-bit number. It has priority over existing BLE_PUBLIC_DEV_ADDR which allows to do the same but in a very nasty way via code injection so is not very intuitive to use. --- nimble/controller/src/ble_ll.c | 19 +++++++++++++++---- nimble/controller/syscfg.yml | 9 +++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 1a8e4622c3..5305e162bc 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -1573,6 +1573,10 @@ ble_ll_init(void) { int rc; uint64_t features; +#if MYNEWT_VAL(BLE_LL_PUBLIC_DEV_ADDR) + uint64_t pub_dev_addr; + int i; +#endif ble_addr_t addr; struct ble_ll_obj *lldata; @@ -1584,10 +1588,17 @@ ble_ll_init(void) /* Set public device address if not already set */ if (ble_ll_is_addr_empty(g_dev_addr)) { - /* Use sycfg address if configured, otherwise try to read from HW */ - if (!ble_ll_is_addr_empty(MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR))) { - memcpy(g_dev_addr, MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), BLE_DEV_ADDR_LEN); - } else { +#if MYNEWT_VAL(BLE_LL_PUBLIC_DEV_ADDR) + pub_dev_addr = MYNEWT_VAL(BLE_LL_PUBLIC_DEV_ADDR); + + for (i = 0; i < BLE_DEV_ADDR_LEN; i++) { + g_dev_addr[i] = pub_dev_addr & 0xff; + pub_dev_addr >>= 8; + } +#else + memcpy(g_dev_addr, MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), BLE_DEV_ADDR_LEN); +#endif + if (ble_ll_is_addr_empty(g_dev_addr)) { rc = ble_hw_get_public_addr(&addr); if (!rc) { memcpy(g_dev_addr, &addr.val[0], BLE_DEV_ADDR_LEN); diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index 13b6780c1b..de6e688c6d 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -308,6 +308,13 @@ syscfg.defs: packets for receive on secondary advertising channel. value: 0 + BLE_LL_PUBLIC_DEV_ADDR: + description: > + Set public device address. Address is specified as 48-bit number. + If non-zero, this setting has priority over BLE_PUBLIC_DEV_ADDR. + Note: this setting should only be used for testing purposes, it is + not intended for production builds. + value: 0x000000000000 BLE_PUBLIC_DEV_ADDR: description: > Allows the target or app to override the public device address @@ -316,6 +323,7 @@ syscfg.defs: chip specific location. If non-zero, this address will be used. value: "(uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}" + deprecated: 1 BLE_LL_DTM: description: > @@ -462,3 +470,4 @@ syscfg.vals.!BLE_HOST: syscfg.restrictions: - OS_CPUTIME_FREQ == 32768 + - BLE_LL_PUBLIC_DEV_ADDR <= 0xffffffffffff From 911a257fe3dfd529fa42365fc17d8ec68157b064 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 8 Nov 2021 14:12:47 +0100 Subject: [PATCH 137/306] apps/blestress: Fix rx_stress_13 ble_gattc_notify_custom() will trigger a GAP event so we cannot use it inside GAP event handler as this will create infinite loop. --- apps/blestress/src/rx_stress.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/apps/blestress/src/rx_stress.c b/apps/blestress/src/rx_stress.c index 440966adcc..01149c43a8 100644 --- a/apps/blestress/src/rx_stress.c +++ b/apps/blestress/src/rx_stress.c @@ -1010,12 +1010,24 @@ rx_stress_12_gap_event(struct ble_gap_event *event, void *arg) return 0; } -static int -rx_stress_13_gap_event(struct ble_gap_event *event, void *arg) +static struct ble_npl_event rx_stress_13_notify_ev; + +static void +rx_stress_13_notify_ev_func(struct ble_npl_event *ev) { + struct os_mbuf *om; int rc; - struct os_mbuf *om = NULL; + om = ble_hs_mbuf_from_flat(test_6_pattern, 10); + rc = ble_gattc_notify_custom(rx_stress_ctx->conn_handle, + hrs_hrm_handle, om); + assert(rc == 0); + +} + +static int +rx_stress_13_gap_event(struct ble_gap_event *event, void *arg) +{ switch (event->type) { case BLE_GAP_EVENT_CONNECT: /* A new connection was established or a connection attempt failed */ @@ -1026,6 +1038,9 @@ rx_stress_13_gap_event(struct ble_gap_event *event, void *arg) rx_stress_ctx->conn_handle = event->connect.conn_handle; rx_stress_ctx->begin_us = os_get_uptime_usec(); + + ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(), + &rx_stress_13_notify_ev); break; } else { /* Connection failed; resume advertising */ @@ -1061,6 +1076,9 @@ rx_stress_13_gap_event(struct ble_gap_event *event, void *arg) BLE_ERR_REM_USER_CONN_TERM); return 0; } + + ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(), + &rx_stress_13_notify_ev); break; default: @@ -1068,10 +1086,6 @@ rx_stress_13_gap_event(struct ble_gap_event *event, void *arg) return 0; } - om = ble_hs_mbuf_from_flat(test_6_pattern, 10); - rc = ble_gattc_notify_custom(rx_stress_ctx->conn_handle, - hrs_hrm_handle, om); - assert(rc == 0); return 0; } @@ -1377,6 +1391,8 @@ rx_stress_start(int test_num) break; case 13: console_printf("Stress GATT notification\033[0m\n"); + ble_npl_event_init(&rx_stress_13_notify_ev, + rx_stress_13_notify_ev_func, NULL); rx_stress_simple_adv(&rx_stress_adv_sets[13]); break; case 14: From b67d3c186689112717a95bbd24b5e7fd6ba7e959 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 8 Nov 2021 14:14:10 +0100 Subject: [PATCH 138/306] apps/blestress: Fix printout in rx_stress_13 --- apps/blestress/src/rx_stress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/blestress/src/rx_stress.c b/apps/blestress/src/rx_stress.c index 01149c43a8..50415ea4e6 100644 --- a/apps/blestress/src/rx_stress.c +++ b/apps/blestress/src/rx_stress.c @@ -1060,7 +1060,7 @@ rx_stress_13_gap_event(struct ble_gap_event *event, void *arg) rx_stress_ctx->s13_notif_time = rx_stress_ctx->time_sum / rx_stress_ctx->send_num; - MODLOG_DFLT(INFO, "Average time: %lld us\n", + MODLOG_DFLT(INFO, "Average time: %d us\n", rx_stress_ctx->s13_notif_time); rx_stress_on_test_finish(13); return 0; From ec0819fac61049b0fd0c50219f7ff0f5de46dc24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 1 Oct 2021 08:20:20 +0200 Subject: [PATCH 139/306] host/mesh: Fixes Friend Queue store message If the SRC field of the received message is a unicast address of an element of the Low Power node, then the message shall not be stored in the Friend Queue. Otherwise, lpn will discard this message, eventually it breaks friendship. this is port of 5b11c053efcb6eec351bb275020fdac9ed6592d9 --- nimble/host/mesh/src/friend.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 4742e89d36..ff34eda9c6 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -1663,6 +1663,11 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, continue; } + if (friend_lpn_matches(frnd, rx->sub->net_idx, + rx->ctx.addr)) { + continue; + } + if (!friend_queue_prepare_space(frnd, rx->ctx.addr, seq_auth, seg_count)) { continue; From 41ee1e2108e1e0d19ee69cb9eb4df2c94c5eaa20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 07:23:32 +0200 Subject: [PATCH 140/306] host/mesh: Break up mesh settings The mesh settings.c module is a giant piece of code responsible for storing the mesh stack configuration. Such approach makes it difficult to control the data to be stored, breaks the stack modules' encapsulation by forcing them to reveal the internal kitchen, which leads to unpleasant issues such as #19799. This commit moves the responsibility of storing the configuration to corresponding modules while keeping control of the moment of storing the configuration and of starting the stack after the settingss loading is completed. This doesn't introduce any abstraction between the mesh settings.c and other modules as it will add more complexity and overhead than necessary for the actual task. This is a port of 561a8e4f0e9ff43d878f382de4d1052e025febec --- apps/bttester/src/mesh.c | 2 +- nimble/host/mesh/include/mesh/glue.h | 1 + nimble/host/mesh/src/access.c | 451 +++++ nimble/host/mesh/src/access.h | 15 +- nimble/host/mesh/src/app_keys.c | 276 ++- nimble/host/mesh/src/app_keys.h | 24 +- nimble/host/mesh/src/cdb.c | 761 +++++++- nimble/host/mesh/src/cdb_priv.h | 12 + nimble/host/mesh/src/cfg.c | 131 +- nimble/host/mesh/src/cfg.h | 1 + nimble/host/mesh/src/cfg_srv.c | 24 +- nimble/host/mesh/src/heartbeat.c | 104 +- nimble/host/mesh/src/heartbeat.h | 2 + nimble/host/mesh/src/mesh.c | 15 +- nimble/host/mesh/src/net.c | 352 +++- nimble/host/mesh/src/net.h | 17 +- nimble/host/mesh/src/provisioner.c | 2 +- nimble/host/mesh/src/rpl.c | 190 +- nimble/host/mesh/src/rpl.h | 7 +- nimble/host/mesh/src/settings.c | 2410 +------------------------- nimble/host/mesh/src/settings.h | 41 +- nimble/host/mesh/src/shell.c | 6 +- nimble/host/mesh/src/subnet.c | 211 ++- nimble/host/mesh/src/subnet.h | 9 + nimble/host/mesh/src/transport.c | 183 +- nimble/host/mesh/src/transport.h | 17 +- nimble/host/mesh/syscfg.yml | 7 + 27 files changed, 2721 insertions(+), 2550 deletions(-) create mode 100644 nimble/host/mesh/src/cdb_priv.h diff --git a/apps/bttester/src/mesh.c b/apps/bttester/src/mesh.c index 87bdbea430..46bf7699c3 100644 --- a/apps/bttester/src/mesh.c +++ b/apps/bttester/src/mesh.c @@ -599,7 +599,7 @@ static void net_send(uint8_t *data, uint16_t len) SYS_LOG_DBG("ttl 0x%02x dst 0x%04x payload_len %d", ctx.send_ttl, ctx.addr, cmd->payload_len); - if (!bt_mesh_app_key_get(vnd_app_key_idx)) { + if (!bt_mesh_app_key_exists(vnd_app_key_idx)) { (void)bt_mesh_app_key_add(vnd_app_key_idx, net.net_idx, vnd_app_key); vnd_models[0].keys[0] = vnd_app_key_idx; diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 9a4bd9a524..eedaaac92d 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -405,6 +405,7 @@ static inline unsigned int find_msb_set(uint32_t op) #define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER #define CONFIG_BT_MESH_PROV_DEVICE BLE_MESH_PROV_DEVICE #define CONFIG_BT_MESH_CDB BLE_MESH_CDB +#define CONFIG_BT_MESH_DEBUG_CFG BLE_MESH_DEBUG_CFG /* Above flags are used with IS_ENABLED macro */ #define IS_ENABLED(config) MYNEWT_VAL(config) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index d23a656551..c6436e85e8 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -10,6 +10,7 @@ #define MESH_LOG_MODULE BLE_MESH_ACCESS_LOG #include +#include #include #include "mesh/mesh.h" @@ -21,10 +22,30 @@ #include "transport.h" #include "access.h" #include "foundation.h" +#include "settings.h" #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS) #include "mesh/model_cli.h" #endif +/* bt_mesh_model.flags */ +enum { + BT_MESH_MOD_BIND_PENDING = BIT(0), + BT_MESH_MOD_SUB_PENDING = BIT(1), + BT_MESH_MOD_PUB_PENDING = BIT(2), + BT_MESH_MOD_NEXT_IS_PARENT = BIT(3), +}; + +/* Model publication information for persistent storage. */ +struct mod_pub_val { + uint16_t addr; + uint16_t key; + uint8_t ttl; + uint8_t retransmit; + uint8_t period; + uint8_t period_div:4, + cred:1; +}; + static const struct bt_mesh_comp *dev_comp; static uint16_t dev_primary_addr; @@ -847,3 +868,433 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod, return 0; } #endif + +static int mod_set_bind(struct bt_mesh_model *mod, char *val) +{ + int len, err, i; + + /* Start with empty array regardless of cleared or set value */ + for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { + mod->keys[i] = BT_MESH_KEY_UNUSED; + } + + if (!val) { + BT_DBG("Cleared bindings for model"); + return 0; + } + + len = sizeof(mod->keys); + err = settings_bytes_from_str(val, mod->keys, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return -EINVAL; + } + + BT_DBG("Decoded %u bound keys for model", len / sizeof(mod->keys[0])); + return 0; +} + +static int mod_set_sub(struct bt_mesh_model *mod, char *val) +{ + int len, err; + + /* Start with empty array regardless of cleared or set value */ + memset(mod->groups, 0, sizeof(mod->groups)); + + if (!val) { + BT_DBG("Cleared subscriptions for model"); + return 0; + } + + len = sizeof(mod->groups); + err = settings_bytes_from_str(val, mod->groups, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return -EINVAL; + } + + BT_DBG("Decoded %u subscribed group addresses for model", + len / sizeof(mod->groups[0])); + return 0; +} + +static int mod_set_pub(struct bt_mesh_model *mod, char *val) +{ + struct mod_pub_val pub; + int len, err; + + if (!mod->pub) { + BT_WARN("Model has no publication context!"); + return -EINVAL; + } + + if (!val) { + mod->pub->addr = BT_MESH_ADDR_UNASSIGNED; + mod->pub->key = 0; + mod->pub->cred = 0; + mod->pub->ttl = 0; + mod->pub->period = 0; + mod->pub->retransmit = 0; + mod->pub->period_div = pub.period_div; + mod->pub->count = 0; + + BT_DBG("Cleared publication for model"); + return 0; + } + + len = sizeof(pub); + err = settings_bytes_from_str(val, &pub, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return -EINVAL; + } + + if (len != sizeof(pub)) { + BT_ERR("Invalid length for model publication"); + return -EINVAL; + } + + mod->pub->addr = pub.addr; + mod->pub->key = pub.key; + mod->pub->cred = pub.cred; + mod->pub->ttl = pub.ttl; + mod->pub->period = pub.period; + mod->pub->retransmit = pub.retransmit; + mod->pub->count = 0; + + BT_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x", + pub.addr, pub.key); + + return 0; +} + +static int mod_data_set(struct bt_mesh_model *mod, + char *name, char *len_rd) +{ + char *next; + + settings_name_next(name, &next); + + if (mod->cb && mod->cb->settings_set) { + return mod->cb->settings_set(mod, next, len_rd); + } + + return 0; +} + +static int mod_set(bool vnd, int argc, char **argv, char *val) +{ + struct bt_mesh_model *mod; + uint8_t elem_idx, mod_idx; + uint16_t mod_key; + + if (argc < 2) { + BT_ERR("Too small argc (%d)", argc); + return -ENOENT; + } + + mod_key = strtol(argv[0], NULL, 16); + elem_idx = mod_key >> 8; + mod_idx = mod_key; + + BT_DBG("Decoded mod_key 0x%04x as elem_idx %u mod_idx %u", + mod_key, elem_idx, mod_idx); + + mod = bt_mesh_model_get(vnd, elem_idx, mod_idx); + if (!mod) { + BT_ERR("Failed to get model for elem_idx %u mod_idx %u", + elem_idx, mod_idx); + return -ENOENT; + } + + if (!strcmp(argv[1], "bind")) { + return mod_set_bind(mod, val); + } + + if (!strcmp(argv[1], "sub")) { + return mod_set_sub(mod, val); + } + + if (!strcmp(argv[1], "pub")) { + return mod_set_pub(mod, val); + } + + if (!strcmp(argv[1], "data")) { + return mod_data_set(mod, argv[1], val); + } + + BT_WARN("Unknown module key %s", argv[1]); + return -ENOENT; +} + +static int sig_mod_set(int argc, char **argv, char *val) +{ + return mod_set(false, argc, argv, val); +} + +static int vnd_mod_set(int argc, char **argv, char *val) +{ + return mod_set(true, argc, argv, val); +} + +static void encode_mod_path(struct bt_mesh_model *mod, bool vnd, + const char *key, char *path, size_t path_len) +{ + uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx); + + if (vnd) { + snprintk(path, path_len, "bt_mesh/v/%x/%s", mod_key, key); + } else { + snprintk(path, path_len, "bt_mesh/s/%x/%s", mod_key, key); + } +} + +static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd) +{ + uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT]; + char buf[BT_SETTINGS_SIZE(sizeof(keys))]; + char path[20]; + int i, count, err; + char *val; + + for (i = 0, count = 0; i < ARRAY_SIZE(mod->keys); i++) { + if (mod->keys[i] != BT_MESH_KEY_UNUSED) { + keys[count++] = mod->keys[i]; + BT_DBG("model key 0x%04x", mod->keys[i]); + } + } + + if (count) { + val = settings_str_from_bytes(keys, count * sizeof(keys[0]), + buf, sizeof(buf)); + if (!val) { + BT_ERR("Unable to encode model bindings as value"); + return; + } + } else { + val = NULL; + } + + encode_mod_path(mod, vnd, "bind", path, sizeof(path)); + + BT_DBG("Saving %s as %s", path, val ? val : "(null)"); + err = settings_save_one(path, val); + if (err) { + BT_ERR("Failed to store bind"); + } else { + BT_DBG("Stored bind"); + } +} + +static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd) +{ + uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT]; + char buf[BT_SETTINGS_SIZE(sizeof(groups))]; + char path[20]; + int i, count, err; + char *val; + + for (i = 0, count = 0; i < CONFIG_BT_MESH_MODEL_GROUP_COUNT; i++) { + if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { + groups[count++] = mod->groups[i]; + } + } + + if (count) { + val = settings_str_from_bytes(groups, count * sizeof(groups[0]), + buf, sizeof(buf)); + if (!val) { + BT_ERR("Unable to encode model subscription as value"); + return; + } + } else { + val = NULL; + } + + encode_mod_path(mod, vnd, "sub", path, sizeof(path)); + + BT_DBG("Saving %s as %s", path, val ? val : "(null)"); + err = settings_save_one(path, val); + if (err) { + BT_ERR("Failed to store sub"); + } else { + BT_DBG("Stored sub"); + } +} + +static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))]; + struct mod_pub_val pub; + char path[20]; + char *val; + int err; + + if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) { + val = NULL; + } else { + pub.addr = mod->pub->addr; + pub.key = mod->pub->key; + pub.ttl = mod->pub->ttl; + pub.retransmit = mod->pub->retransmit; + pub.period = mod->pub->period; + pub.period_div = mod->pub->period_div; + pub.cred = mod->pub->cred; + + val = settings_str_from_bytes(&pub, sizeof(pub), buf, sizeof(buf)); + if (!val) { + BT_ERR("Unable to encode model publication as value"); + return; + } + } + + encode_mod_path(mod, vnd, "pub", path, sizeof(path)); + + BT_DBG("Saving %s as %s", path, val ? val : "(null)"); + err = settings_save_one(path, val); + if (err) { + BT_ERR("Failed to store pub"); + } else { + BT_DBG("Stored pub"); + } +} + +static void store_pending_mod(struct bt_mesh_model *mod, + struct bt_mesh_elem *elem, bool vnd, + bool primary, void *user_data) +{ + if (!mod->flags) { + return; + } + + if (mod->flags & BT_MESH_MOD_BIND_PENDING) { + mod->flags &= ~BT_MESH_MOD_BIND_PENDING; + store_pending_mod_bind(mod, vnd); + } + + if (mod->flags & BT_MESH_MOD_SUB_PENDING) { + mod->flags &= ~BT_MESH_MOD_SUB_PENDING; + store_pending_mod_sub(mod, vnd); + } + + if (mod->flags & BT_MESH_MOD_PUB_PENDING) { + mod->flags &= ~BT_MESH_MOD_PUB_PENDING; + store_pending_mod_pub(mod, vnd); + } +} + +void bt_mesh_model_pending_store(void) +{ + bt_mesh_model_foreach(store_pending_mod, NULL); +} + +void bt_mesh_model_bind_store(struct bt_mesh_model *mod) +{ + mod->flags |= BT_MESH_MOD_BIND_PENDING; + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); +} + +void bt_mesh_model_sub_store(struct bt_mesh_model *mod) +{ + mod->flags |= BT_MESH_MOD_SUB_PENDING; + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); +} + +void bt_mesh_model_pub_store(struct bt_mesh_model *mod) +{ + mod->flags |= BT_MESH_MOD_PUB_PENDING; + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); +} + +int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, + const char *name, const void *data, + size_t data_len) +{ + char path[30]; + char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))]; + char *val; + int err; + + encode_mod_path(mod, vnd, "data", path, sizeof(path)); + if (name) { + strcat(path, "/"); + strncat(path, name, 8); + } + + if (data_len) { + val = settings_str_from_bytes(data, data_len, buf, sizeof(buf)); + if (!val) { + BT_ERR("Unable to encode model publication as value"); + return -EINVAL; + } + err = settings_save_one(path, val); + } else { + err = settings_save_one(path, NULL); + } + + if (err) { + BT_ERR("Failed to store %s value", path); + } else { + BT_DBG("Stored %s value", path); + } + return err; +} + +static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, + bool vnd, bool primary, void *user_data) +{ + if (mod->pub && mod->pub->update && + mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) { + int32_t ms = bt_mesh_model_pub_period_get(mod); + + if (ms > 0) { + BT_DBG("Starting publish timer (period %u ms)", ms); + k_delayed_work_submit(&mod->pub->timer, K_MSEC(ms)); + } + } + + if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { + return; + } + + for (int i = 0; i < ARRAY_SIZE(mod->groups); i++) { + if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { + bt_mesh_lpn_group_add(mod->groups[i]); + } + } +} + +void bt_mesh_model_settings_commit(void) +{ + bt_mesh_model_foreach(commit_mod, NULL); +} + +static struct conf_handler bt_mesh_sig_mod_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = sig_mod_set, + .ch_commit = NULL, + .ch_export = NULL, +}; + +static struct conf_handler bt_mesh_vnd_mod_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = vnd_mod_set, + .ch_commit = NULL, + .ch_export = NULL, +}; + +void bt_mesh_access_init(void) +{ + int rc; + + rc = conf_register(&bt_mesh_sig_mod_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_access conf"); + rc = conf_register(&bt_mesh_vnd_mod_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_access conf"); +} \ No newline at end of file diff --git a/nimble/host/mesh/src/access.h b/nimble/host/mesh/src/access.h index affba538f2..0bb183c172 100644 --- a/nimble/host/mesh/src/access.h +++ b/nimble/host/mesh/src/access.h @@ -11,14 +11,6 @@ #include "mesh/mesh.h" -/* bt_mesh_model.flags */ -enum { - BT_MESH_MOD_BIND_PENDING = BIT(0), - BT_MESH_MOD_SUB_PENDING = BIT(1), - BT_MESH_MOD_PUB_PENDING = BIT(2), - BT_MESH_MOD_NEXT_IS_PARENT = BIT(3), -}; - /* Tree walk return codes */ enum bt_mesh_walk { BT_MESH_WALK_STOP, @@ -61,4 +53,11 @@ struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); int bt_mesh_comp_register(const struct bt_mesh_comp *comp); + +void bt_mesh_model_pending_store(void); +void bt_mesh_model_bind_store(struct bt_mesh_model *mod); +void bt_mesh_model_sub_store(struct bt_mesh_model *mod); +void bt_mesh_model_pub_store(struct bt_mesh_model *mod); +void bt_mesh_model_settings_commit(void); +void bt_mesh_access_init(void); #endif diff --git a/nimble/host/mesh/src/app_keys.c b/nimble/host/mesh/src/app_keys.c index 9582bbd045..16236009d3 100644 --- a/nimble/host/mesh/src/app_keys.c +++ b/nimble/host/mesh/src/app_keys.c @@ -22,41 +22,176 @@ #include "subnet.h" #define MESH_LOG_MODULE BLE_MESH_LOG + #include "log/log.h" -static struct bt_mesh_app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = { +/* Tracking of what storage changes are pending for App Keys. We track this in + * a separate array here instead of within the respective bt_mesh_app_key + * struct itselve, since once a key gets deleted its struct becomes invalid + * and may be reused for other keys. + */ +struct app_key_update { + uint16_t key_idx:12, /* AppKey Index */ + valid:1, /* 1 if this entry is valid, 0 if not */ + clear:1; /* 1 if key needs clearing, 0 if storing */ +}; + +/* AppKey information for persistent storage. */ +struct app_key_val { + uint16_t net_idx; + bool updated; + uint8_t val[2][16]; +} __packed; + +/** Mesh Application Key. */ +struct app_key { + uint16_t net_idx; + uint16_t app_idx; + bool updated; + struct bt_mesh_app_cred { + uint8_t id; + uint8_t val[16]; + } keys[2]; +}; + +static struct app_key_update app_key_updates[CONFIG_BT_MESH_APP_KEY_COUNT]; + +static struct app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = { [0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = { .app_idx = BT_MESH_KEY_UNUSED, .net_idx = BT_MESH_KEY_UNUSED, } }; -static void app_key_evt(struct bt_mesh_app_key *app, enum bt_mesh_key_evt evt) +static struct app_key *app_get(uint16_t app_idx) { + for (int i = 0; i < ARRAY_SIZE(apps); i++) { + if (apps[i].app_idx == app_idx) { + return &apps[i]; + } + } + + return NULL; +} + +static void clear_app_key(uint16_t app_idx) +{ + char path[20]; + int err; + + BT_DBG("AppKeyIndex 0x%03x", app_idx); + + snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx); + } else { + BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx); + } +} + +static void store_app_key(uint16_t app_idx) +{ + const struct app_key *app; + struct app_key_val key; + char path[20]; + char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; + int err; + char *str; + + snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx); + + app = app_get(app_idx); + if (!app) { + BT_WARN("ApKeyIndex 0x%03x not found", app_idx); + return; + } + + key.net_idx = app->net_idx, + key.updated = app->updated, + + memcpy(key.val[0], app->keys[0].val, 16); + memcpy(key.val[1], app->keys[1].val, 16); + str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); + + err = settings_save_one(path, str); + if (err) { + BT_ERR("Failed to store AppKey"); + } else { + BT_DBG("Stored AppKey %s value"); + } +} + +static struct app_key_update *app_key_update_find(uint16_t key_idx, + struct app_key_update **free_slot) + { + struct app_key_update *match; int i; - for (i = 0; i < (sizeof(bt_mesh_app_key_cb_list)/sizeof(void *)); i++) { - if (bt_mesh_app_key_cb_list[i]) { - BT_DBG("app_key_evt %d", i); - bt_mesh_app_key_cb_list[i] (app->app_idx, app->net_idx, evt); + match = NULL; + *free_slot = NULL; + + for (i = 0; i < ARRAY_SIZE(app_key_updates); i++) { + struct app_key_update *update = &app_key_updates[i]; + + if (!update->valid) { + *free_slot = update; + continue; + } + + if (update->key_idx == key_idx) { + match = update; } } + + return match; } -struct bt_mesh_app_key *app_get(uint16_t app_idx) +static void update_app_key_settings(uint16_t app_idx, bool store) { - for (int i = 0; i < ARRAY_SIZE(apps); i++) { - if (apps[i].app_idx == app_idx) { - return &apps[i]; + struct app_key_update *update, *free_slot; + uint8_t clear = store ? 0U : 1U; + + BT_DBG("AppKeyIndex 0x%03x", app_idx); + + update = app_key_update_find(app_idx, &free_slot); + if (update) { + update->clear = clear; + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_APP_KEYS_PENDING); + return; + } + + if (!free_slot) { + if (store) { + store_app_key(app_idx); + } else { + clear_app_key(app_idx); } + return; } - return NULL; + free_slot->valid = 1U; + free_slot->key_idx = app_idx; + free_slot->clear = clear; + + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_APP_KEYS_PENDING); +} + +static void app_key_evt(struct app_key *app, enum bt_mesh_key_evt evt) +{ + int i; + + for (i = 0; i < (sizeof(bt_mesh_app_key_cb_list)/sizeof(void *)); i++) { + if (bt_mesh_app_key_cb_list[i]) { + BT_DBG("app_key_evt %d", i); + bt_mesh_app_key_cb_list[i] (app->app_idx, app->net_idx, evt); + } + } } -static struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx) +static struct app_key *app_key_alloc(uint16_t app_idx) { - struct bt_mesh_app_key *app = NULL; + struct app_key *app = NULL; for (int i = 0; i < ARRAY_SIZE(apps); i++) { /* Check for already existing app_key */ @@ -72,12 +207,12 @@ static struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx) return app; } -static void app_key_del(struct bt_mesh_app_key *app) +static void app_key_del(struct app_key *app) { BT_DBG("AppIdx 0x%03x", app->app_idx); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_clear_app_key(app->app_idx); + update_app_key_settings(app->app_idx, false); } app_key_evt(app, BT_MESH_KEY_DELETED); @@ -87,7 +222,7 @@ static void app_key_del(struct bt_mesh_app_key *app) (void)memset(app->keys, 0, sizeof(app->keys)); } -static void app_key_revoke(struct bt_mesh_app_key *app) +static void app_key_revoke(struct app_key *app) { if (!app->updated) { return; @@ -98,7 +233,7 @@ static void app_key_revoke(struct bt_mesh_app_key *app) app->updated = false; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_app_key(app->app_idx); + update_app_key_settings(app->app_idx, true); } app_key_evt(app, BT_MESH_KEY_REVOKED); @@ -112,7 +247,7 @@ static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) } for (int i = 0; i < ARRAY_SIZE(apps); i++) { - struct bt_mesh_app_key *app = &apps[i]; + struct app_key *app = &apps[i]; if (app->app_idx == BT_MESH_KEY_UNUSED) { continue; @@ -140,7 +275,7 @@ uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx, bt_mesh_subnet_cb_list[0] = subnet_evt; } - struct bt_mesh_app_key *app; + struct app_key *app; BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx, bt_hex(key, 16)); @@ -179,7 +314,7 @@ uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx, if (IS_ENABLED(CONFIG_BT_SETTINGS)) { BT_DBG("Storing AppKey persistently"); - bt_mesh_store_app_key(app->app_idx); + update_app_key_settings(app->app_idx, true); } app_key_evt(app, BT_MESH_KEY_ADDED); @@ -187,22 +322,10 @@ uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx, return STATUS_SUCCESS; } -struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx) -{ - struct bt_mesh_app_key *app; - - app = app_get(app_idx); - if (app) { - return app; - } - - return NULL; -} - uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx, const uint8_t key[16]) { - struct bt_mesh_app_key *app; + struct app_key *app; struct bt_mesh_subnet *sub; BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx, @@ -250,7 +373,7 @@ uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx, if (IS_ENABLED(CONFIG_BT_SETTINGS)) { BT_DBG("Storing AppKey persistently"); - bt_mesh_store_app_key(app->app_idx); + update_app_key_settings(app->app_idx, true); } app_key_evt(app, BT_MESH_KEY_UPDATED); @@ -260,7 +383,7 @@ uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx, uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx) { - struct bt_mesh_app_key *app; + struct app_key *app; BT_DBG("AppIdx 0x%03x", app_idx); @@ -288,7 +411,7 @@ uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx) int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx, const uint8_t old_key[16], const uint8_t new_key[16]) { - struct bt_mesh_app_key *app; + struct app_key *app; app = app_key_alloc(app_idx); if (!app) { @@ -337,7 +460,7 @@ ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max, size_t count = 0; for (int i = 0; i < ARRAY_SIZE(apps); i++) { - struct bt_mesh_app_key *app = &apps[i]; + struct app_key *app = &apps[i]; if (app->app_idx == BT_MESH_KEY_UNUSED) { continue; @@ -366,7 +489,7 @@ int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx, struct bt_mesh_subnet **sub, const uint8_t *app_key[16], uint8_t *aid) { - struct bt_mesh_app_key *app = NULL; + struct app_key *app = NULL; if (BT_MESH_IS_DEV_KEY(ctx->app_idx)) { /* With device keys, the application has to decide which subnet @@ -462,7 +585,7 @@ uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid, } for (i = 0; i < ARRAY_SIZE(apps); i++) { - const struct bt_mesh_app_key *app = &apps[i]; + const struct app_key *app = &apps[i]; const struct bt_mesh_app_cred *cred; if (app->app_idx == BT_MESH_KEY_UNUSED) { @@ -498,10 +621,83 @@ uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid, void bt_mesh_app_keys_reset(void) { for (int i = 0; i < ARRAY_SIZE(apps); i++) { - struct bt_mesh_app_key *app = &apps[i]; + struct app_key *app = &apps[i]; if (app->app_idx != BT_MESH_KEY_UNUSED) { app_key_del(app); } } } + +static int app_key_set(int argc, char **argv, char *val) +{ + struct app_key_val key; + uint16_t app_idx; + int len_rd, err; + + BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); + + app_idx = strtol(argv[0], NULL, 16); + len_rd = strtol(argv[1], NULL, 16); + + + if (!len_rd) { + return 0; + } + + err = settings_bytes_from_str(val, &key, &len_rd); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return err; + } + + err = bt_mesh_app_key_set(app_idx, key.net_idx, key.val[0], + key.updated ? key.val[1] : NULL); + if (err) { + BT_ERR("Failed to set \'app-key\'"); + return err; + } + + BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx); + + return 0; +} + +void bt_mesh_app_key_pending_store(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(app_key_updates); i++) { + struct app_key_update *update = &app_key_updates[i]; + + if (!update->valid) { + continue; + } + + if (update->clear) { + clear_app_key(update->key_idx); + } else { + store_app_key(update->key_idx); + } + + update->valid = 0U; + } +} + +static struct conf_handler bt_mesh_app_key_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = app_key_set, + .ch_commit = NULL, + .ch_export = NULL, +}; + +void bt_mesh_app_key_init(void) +{ + int rc; + + rc = conf_register(&bt_mesh_app_key_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_app_key conf"); +} \ No newline at end of file diff --git a/nimble/host/mesh/src/app_keys.h b/nimble/host/mesh/src/app_keys.h index d007b785f6..1c560560de 100644 --- a/nimble/host/mesh/src/app_keys.h +++ b/nimble/host/mesh/src/app_keys.h @@ -10,28 +10,9 @@ #include "mesh/mesh.h" #include "subnet.h" -/** Mesh Application. */ -struct bt_mesh_app_key { - uint16_t net_idx; - uint16_t app_idx; - bool updated; - struct bt_mesh_app_cred { - uint8_t id; - uint8_t val[16]; - } keys[2]; -}; - /** @brief Reset the app keys module. */ void bt_mesh_app_keys_reset(void); -/** @brief Get the application key with the given AppIdx. - * - * @param app_idx App index. - * - * @return The matching application, or NULL if the application isn't known. - */ -struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx); - /** @brief Initialize a new application key with the given parameters. * * @param app_idx AppIndex. @@ -78,9 +59,10 @@ uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid, const uint8_t key[16], void *cb_data), void *cb_data); -struct bt_mesh_app_key *app_get(uint16_t app_idx); - extern void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx, enum bt_mesh_key_evt evt); +/** @brief Store pending application keys in persistent storage. */ +void bt_mesh_app_key_pending_store(void); +void bt_mesh_app_key_init(void); #endif /* _BT_MESH_APP_KEYS_H_ */ \ No newline at end of file diff --git a/nimble/host/mesh/src/cdb.c b/nimble/host/mesh/src/cdb.c index 60d47dee26..5c7f88d470 100644 --- a/nimble/host/mesh/src/cdb.c +++ b/nimble/host/mesh/src/cdb.c @@ -7,8 +7,9 @@ #define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_CDB) #define LOG_MODULE_NAME bt_mesh_cdb #include "log/log.h" +#include -#include "mesh/mesh.h" +#include "cdb_priv.h" #include "net.h" #include "rpl.h" #include "settings.h" @@ -16,6 +17,58 @@ #include "mesh/glue.h" #if MYNEWT_VAL(BLE_MESH_CDB) +/* Tracking of what storage changes are pending for App and Net Keys. We + * track this in a separate array here instead of within the respective + * bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key + * gets deleted its struct becomes invalid and may be reused for other keys. + */ +struct key_update { + uint16_t key_idx:12, /* AppKey or NetKey Index */ + valid:1, /* 1 if this entry is valid, 0 if not */ + app_key:1, /* 1 if this is an AppKey, 0 if a NetKey */ + clear:1; /* 1 if key needs clearing, 0 if storing */ +}; + +/* Tracking of what storage changes are pending for node settings. */ +struct node_update { + uint16_t addr; + bool clear; +}; + +/* Node information for persistent storage. */ +struct node_val { + uint16_t net_idx; + uint8_t num_elem; + uint8_t flags; +#define F_NODE_CONFIGURED 0x01 + uint8_t uuid[16]; + uint8_t dev_key[16]; +} __packed; + +/* NetKey storage information */ +struct net_key_val { + uint8_t kr_flag:1, + kr_phase:7; + uint8_t val[2][16]; +} __packed; + +/* AppKey information for persistent storage. */ +struct app_key_val { + uint16_t net_idx; + bool updated; + uint8_t val[2][16]; +} __packed; + +/* IV Index & IV Update information for persistent storage. */ +struct net_val { + uint32_t iv_index; + bool iv_update; +} __packed; + +static struct node_update cdb_node_updates[MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)]; +static struct key_update cdb_key_updates[MYNEWT_VAL(BLE_MESH_CDB_SUBNET_COUNT) + + MYNEWT_VAL(BLE_MESH_CDB_APP_KEY_COUNT)]; + struct bt_mesh_cdb bt_mesh_cdb = { .nodes = { [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = { @@ -107,6 +160,530 @@ static uint16_t find_lowest_free_addr(uint8_t num_elem) return addr; } +static int cdb_net_set(int argc, char *val) +{ + struct net_val net; + int len, err; + + len = sizeof(net); + err = settings_bytes_from_str(val, &net, &len); + if (err) { + BT_ERR("Failed to set \'cdb_net\'"); + return err; + } + + bt_mesh_cdb.iv_index = net.iv_index; + + if (net.iv_update) { + atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS); + } + + atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID); + + return 0; +} + +static int cdb_node_set(int argc, char *str) +{ + struct bt_mesh_cdb_node *node; + struct node_val val; + uint16_t addr; + int len, err; + + if (argc < 1) { + BT_ERR("Insufficient number of arguments"); + return -ENOENT; + } + + addr = strtol(str, NULL, 16); + len = sizeof(str); + + if (argc < 1) { + BT_DBG("val (null)"); + BT_DBG("Deleting node 0x%04x", addr); + + node = bt_mesh_cdb_node_get(addr); + if (node) { + bt_mesh_cdb_node_del(node, false); + } + + return 0; + } + + err = settings_bytes_from_str(str, &val, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return -EINVAL; + } + + if (len != sizeof(struct node_val)) { + BT_ERR("Invalid length for node_val"); + return -EINVAL; + } + + node = bt_mesh_cdb_node_get(addr); + if (!node) { + node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem, + val.net_idx); + } + + if (!node) { + BT_ERR("No space for a new node"); + return -ENOMEM; + } + + if (val.flags & F_NODE_CONFIGURED) { + atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED); + } + + memcpy(node->uuid, val.uuid, 16); + memcpy(node->dev_key, val.dev_key, 16); + + BT_DBG("Node 0x%04x recovered from storage", addr); + + return 0; +} + +static int cdb_subnet_set(int argc, char *name) +{ + struct bt_mesh_cdb_subnet *sub; + struct net_key_val key; + uint16_t net_idx; + int len, len_rd, err; + + if (!name) { + BT_ERR("Insufficient number of arguments"); + return -ENOENT; + } + + len_rd = sizeof(sub); + net_idx = strtol(name, NULL, 16); + sub = bt_mesh_cdb_subnet_get(net_idx); + + if (len_rd == 0) { + BT_DBG("val (null)"); + if (!sub) { + BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx); + return -ENOENT; + } + + BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx); + bt_mesh_cdb_subnet_del(sub, false); + return 0; + } + + len = sizeof(key); + err = settings_bytes_from_str(name, &key, &len); + if (err) { + BT_ERR("Failed to set \'net-key\'"); + return err; + } + + if (sub) { + BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx); + + sub->kr_phase = key.kr_phase; + memcpy(sub->keys[0].net_key, &key.val[0], 16); + memcpy(sub->keys[1].net_key, &key.val[1], 16); + + return 0; + } + + sub = bt_mesh_cdb_subnet_alloc(net_idx); + if (!sub) { + BT_ERR("No space to allocate a new subnet"); + return -ENOMEM; + } + + sub->kr_phase = key.kr_phase; + memcpy(sub->keys[0].net_key, &key.val[0], 16); + memcpy(sub->keys[1].net_key, &key.val[1], 16); + + BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx); + + return 0; +} + +static int cdb_app_key_set(int argc, char *name) +{ + struct bt_mesh_cdb_app_key *app; + struct app_key_val key; + uint16_t app_idx; + int len_rd, err; + + app_idx = strtol(name, NULL, 16); + len_rd = sizeof(key); + + if (len_rd == 0) { + BT_DBG("val (null)"); + BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx); + + app = bt_mesh_cdb_app_key_get(app_idx); + if (app) { + bt_mesh_cdb_app_key_del(app, false); + } + + return 0; + } + + err = settings_bytes_from_str(name, &key, &len_rd); + if (err) { + BT_ERR("Failed to set \'app-key\'"); + return err; + } + + app = bt_mesh_cdb_app_key_get(app_idx); + if (!app) { + app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx); + } + + if (!app) { + BT_ERR("No space for a new app key"); + return -ENOMEM; + } + + memcpy(app->keys[0].app_key, key.val[0], 16); + memcpy(app->keys[1].app_key, key.val[1], 16); + + BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx); + + return 0; +} + +static int cdb_set(int argc, char **argv, char *name) +{ + int len; + char *next; + + if (argc < 1) { + BT_ERR("Insufficient number of arguments"); + return -ENOENT; + } + + if (!strcmp(name, "Net")) { + return cdb_net_set(1, name); + } + + len = settings_name_next(name, &next); + + if (!next) { + BT_ERR("Insufficient number of arguments"); + return -ENOENT; + } + + if (!strncmp(name, "Node", len)) { + return cdb_node_set(1, next); + } + + if (!strncmp(name, "Subnet", len)) { + return cdb_subnet_set(1, next); + } + + if (!strncmp(name, "AppKey", len)) { + return cdb_app_key_set(1, next); + } + + BT_WARN("Unknown module key %s", name); + return -ENOENT; +} + +static void store_cdb_node(const struct bt_mesh_cdb_node *node) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct node_val))]; + struct node_val val; + char path[30]; + char *str; + int err; + + val.net_idx = node->net_idx; + val.num_elem = node->num_elem; + val.flags = 0; + + if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) { + val.flags |= F_NODE_CONFIGURED; + } + + memcpy(val.uuid, node->uuid, 16); + memcpy(val.dev_key, node->dev_key, 16); + + snprintk(path, sizeof(path), "bt_mesh/cdb/Node/%x", node->addr); + + str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode Node as value"); + return; + } + + + err = settings_save_one(path, str); + if (err) { + BT_ERR("Failed to store Node %s value", path); + } else { + BT_DBG("Stored Node %s value", path); + } +} + +static void clear_cdb_node(uint16_t addr) +{ + char path[30]; + int err; + + BT_DBG("Node 0x%04x", addr); + + snprintk(path, sizeof(path), "bt_mesh/cdb/Node/%x", addr); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear Node 0x%04x", addr); + } else { + BT_DBG("Cleared Node 0x%04x", addr); + } +} + +static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))]; + struct net_key_val key; + char path[30]; + int err; + char *str; + + BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx, + bt_hex(sub->keys[0].net_key, 16)); + + memcpy(&key.val[0], sub->keys[0].net_key, 16); + memcpy(&key.val[1], sub->keys[1].net_key, 16); + key.kr_flag = 0U; /* Deprecated */ + key.kr_phase = sub->kr_phase; + + snprintk(path, sizeof(path), "bt_mesh/cdb/Subnet/%x", sub->net_idx); + + + str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode Subnet as value"); + return; + } + err = settings_save_one(path, str); + if (err) { + BT_ERR("Failed to store Subnet value"); + } else { + BT_DBG("Stored Subnet value"); + } +} + +static void clear_cdb_subnet(uint16_t net_idx) +{ + char path[30]; + int err; + + BT_DBG("NetKeyIndex 0x%03x", net_idx); + + snprintk(path, sizeof(path), "bt_mesh/cdb/Subnet/%x", net_idx); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx); + } else { + BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx); + } +} + +static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; + struct app_key_val key; + char path[30]; + int err; + char *str; + + key.net_idx = app->net_idx; + key.updated = false; + memcpy(key.val[0], app->keys[0].app_key, 16); + memcpy(key.val[1], app->keys[1].app_key, 16); + + snprintk(path, sizeof(path), "bt_mesh/cdb/AppKey/%x", app->app_idx); + + str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); + err = settings_save_one(path, str); + if (err) { + BT_ERR("Failed to store AppKey"); + } else { + BT_DBG("Stored AppKey"); + } +} + +static void clear_cdb_app_key(uint16_t app_idx) +{ + char path[30]; + int err; + + snprintk(path, sizeof(path), "bt_mesh/cdb/AppKey/%x", app_idx); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx); + } else { + BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx); + } +} + +static void schedule_cdb_store(int flag) +{ + atomic_set_bit(bt_mesh_cdb.flags, flag); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CDB_PENDING); +} + +static void update_cdb_net_settings(void) +{ + schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING); +} + +static struct node_update *cdb_node_update_find(uint16_t addr, + struct node_update **free_slot) +{ + struct node_update *match; + int i; + + match = NULL; + *free_slot = NULL; + + for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) { + struct node_update *update = &cdb_node_updates[i]; + + if (update->addr == BT_MESH_ADDR_UNASSIGNED) { + *free_slot = update; + continue; + } + + if (update->addr == addr) { + match = update; + } + } + + return match; +} + +static void update_cdb_node_settings(const struct bt_mesh_cdb_node *node, + bool store) +{ + struct node_update *update, *free_slot; + + BT_DBG("Node 0x%04x", node->addr); + + update = cdb_node_update_find(node->addr, &free_slot); + if (update) { + update->clear = !store; + schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); + return; + } + + if (!free_slot) { + if (store) { + store_cdb_node(node); + } else { + clear_cdb_node(node->addr); + } + return; + } + + free_slot->addr = node->addr; + free_slot->clear = !store; + + schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); +} + +static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx, + struct key_update **free_slot) +{ + struct key_update *match; + int i; + + match = NULL; + *free_slot = NULL; + + for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) { + struct key_update *update = &cdb_key_updates[i]; + + if (!update->valid) { + *free_slot = update; + continue; + } + + if (update->app_key != app_key) { + continue; + } + + if (update->key_idx == key_idx) { + match = update; + } + } + + return match; +} + +static void update_cdb_subnet_settings(const struct bt_mesh_cdb_subnet *sub, + bool store) +{ + struct key_update *update, *free_slot; + uint8_t clear = store ? 0U : 1U; + + BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); + + update = cdb_key_update_find(false, sub->net_idx, &free_slot); + if (update) { + update->clear = clear; + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); + return; + } + + if (!free_slot) { + if (store) { + store_cdb_subnet(sub); + } else { + clear_cdb_subnet(sub->net_idx); + } + return; + } + + free_slot->valid = 1U; + free_slot->key_idx = sub->net_idx; + free_slot->app_key = 0U; + free_slot->clear = clear; + + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); +} + +static void update_cdb_app_key_settings(const struct bt_mesh_cdb_app_key *key, + bool store) +{ + struct key_update *update, *free_slot; + uint8_t clear = store ? 0U : 1U; + + BT_DBG("AppKeyIndex 0x%03x", key->app_idx); + + update = cdb_key_update_find(true, key->app_idx, &free_slot); + if (update) { + update->clear = clear; + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); + return; + } + + if (!free_slot) { + if (store) { + store_cdb_app_key(key); + } else { + clear_cdb_app_key(key->app_idx); + } + + return; + } + + free_slot->valid = 1U; + free_slot->key_idx = key->app_idx; + free_slot->app_key = 1U; + free_slot->clear = clear; + + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); +} + int bt_mesh_cdb_create(const uint8_t key[16]) { struct bt_mesh_cdb_subnet *sub; @@ -125,8 +702,8 @@ int bt_mesh_cdb_create(const uint8_t key[16]) bt_mesh_cdb.iv_index = 0; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cdb(); - bt_mesh_store_cdb_subnet(sub); + update_cdb_net_settings(); + update_cdb_subnet_settings(sub, true); } return 0; @@ -157,7 +734,7 @@ void bt_mesh_cdb_clear(void) } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cdb(); + update_cdb_net_settings(); } } @@ -171,7 +748,7 @@ void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update) iv_update); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cdb(); + update_cdb_net_settings(); } } @@ -204,7 +781,7 @@ void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store) BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store); if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_clear_cdb_subnet(sub); + update_cdb_subnet_settings(sub, false); } sub->net_idx = BT_MESH_KEY_UNUSED; @@ -226,8 +803,8 @@ struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx) void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub) { - if (MYNEWT_VAL(BLE_MESH_SETTINGS)) { - bt_mesh_store_cdb_subnet(sub); + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + update_cdb_subnet_settings(sub, true); } } @@ -283,7 +860,7 @@ void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store) BT_DBG("Node addr 0x%04x store %u", node->addr, store); if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_clear_cdb_node(node); + update_cdb_node_settings(node, false); } node->addr = BT_MESH_ADDR_UNASSIGNED; @@ -308,8 +885,8 @@ struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr) void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node) { - if (MYNEWT_VAL(BLE_MESH_SETTINGS)) { - bt_mesh_store_cdb_node(node); + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + update_cdb_node_settings(node, true); } } @@ -356,7 +933,7 @@ void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store) BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store); if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_clear_cdb_app_key(key); + update_cdb_app_key_settings(key, false); } key->net_idx = BT_MESH_KEY_UNUSED; @@ -381,8 +958,164 @@ struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx) void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key) { - if (MYNEWT_VAL(BLE_MESH_SETTINGS)) { - bt_mesh_store_cdb_app_key(key); + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + update_cdb_app_key_settings(key, true); + } +} + +static void clear_cdb_net(void) +{ + char path[30]; + int err; + + snprintk(path, sizeof(path), "bt_mesh/cdb/Net"); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear Net"); + } else { + BT_DBG("Cleared NetKeyIndex 0x%03x"); + } +} + +static void store_cdb_pending_net(void) +{ + struct net_val net; + int err; + char buf[BT_SETTINGS_SIZE(sizeof(struct net_val))]; + char *str; + + BT_DBG(""); + + net.iv_index = bt_mesh_cdb.iv_index; + net.iv_update = atomic_test_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_IVU_IN_PROGRESS); + + str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode Network as value"); + return; + } + err = settings_save_one("bt_mesh/cdb/Net", str); + if (err) { + BT_ERR("Failed to store Network value"); + } else { + BT_DBG("Stored Network value"); + } +} + +static void store_cdb_pending_nodes(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) { + struct node_update *update = &cdb_node_updates[i]; + + if (update->addr == BT_MESH_ADDR_UNASSIGNED) { + continue; + } + + BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear); + + if (update->clear) { + clear_cdb_node(update->addr); + } else { + struct bt_mesh_cdb_node *node; + + node = bt_mesh_cdb_node_get(update->addr); + if (node) { + store_cdb_node(node); + } else { + BT_WARN("Node 0x%04x not found", update->addr); + } + } + + update->addr = BT_MESH_ADDR_UNASSIGNED; + } +} + +static void store_cdb_pending_keys(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) { + struct key_update *update = &cdb_key_updates[i]; + + if (!update->valid) { + continue; + } + + if (update->clear) { + if (update->app_key) { + clear_cdb_app_key(update->key_idx); + } else { + clear_cdb_subnet(update->key_idx); + } + } else { + if (update->app_key) { + struct bt_mesh_cdb_app_key *key; + + key = bt_mesh_cdb_app_key_get(update->key_idx); + if (key) { + store_cdb_app_key(key); + } else { + BT_WARN("AppKeyIndex 0x%03x not found", + update->key_idx); + } + } else { + struct bt_mesh_cdb_subnet *sub; + + sub = bt_mesh_cdb_subnet_get(update->key_idx); + if (sub) { + store_cdb_subnet(sub); + } else { + BT_WARN("NetKeyIndex 0x%03x not found", + update->key_idx); + } + } + } + + update->valid = 0U; + } +} + +void bt_mesh_cdb_pending_store(void) +{ + if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_SUBNET_PENDING)) { + if (atomic_test_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_VALID)) { + store_cdb_pending_net(); + } else { + clear_cdb_net(); + } + } + + if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_NODES_PENDING)) { + store_cdb_pending_nodes(); } + + if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_KEYS_PENDING)) { + store_cdb_pending_keys(); + } +} + +static struct conf_handler bt_mesh_cdb_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = cdb_set, + .ch_commit = NULL, + .ch_export = NULL, +}; + +void bt_mesh_cdb_init(void) +{ + int rc; + + rc = conf_register(&bt_mesh_cdb_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_net conf"); } #endif diff --git a/nimble/host/mesh/src/cdb_priv.h b/nimble/host/mesh/src/cdb_priv.h new file mode 100644 index 0000000000..ff865a56fd --- /dev/null +++ b/nimble/host/mesh/src/cdb_priv.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ommitted `bt_mesh_cdb_node_store` declaration - every header + * includes mesh/mesh.h, which already has it + * void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node); + */ +void bt_mesh_cdb_pending_store(void); +void bt_mesh_cdb_init(void); diff --git a/nimble/host/mesh/src/cfg.c b/nimble/host/mesh/src/cfg.c index 4e14925506..b9daa8fda2 100644 --- a/nimble/host/mesh/src/cfg.c +++ b/nimble/host/mesh/src/cfg.c @@ -15,6 +15,21 @@ #include "cfg.h" #include "mesh/glue.h" +#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_CFG) +#define LOG_MODULE_NAME bt_mesh_cfg +#include "log/log.h" + +/* Miscellaneous configuration server model states */ +struct cfg_val { + uint8_t net_transmit; + uint8_t relay; + uint8_t relay_retransmit; + uint8_t beacon; + uint8_t gatt_proxy; + uint8_t frnd; + uint8_t default_ttl; +}; + void bt_mesh_beacon_set(bool beacon) { if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) { @@ -31,7 +46,7 @@ void bt_mesh_beacon_set(bool beacon) if (IS_ENABLED(CONFIG_BT_SETTINGS) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_store_cfg(); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); } } @@ -82,7 +97,7 @@ int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy) if (IS_ENABLED(CONFIG_BT_SETTINGS) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_store_cfg(); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); } return 0; @@ -111,7 +126,7 @@ int bt_mesh_default_ttl_set(uint8_t default_ttl) if (IS_ENABLED(CONFIG_BT_SETTINGS) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_store_cfg(); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); } return 0; @@ -139,7 +154,7 @@ int bt_mesh_friend_set(enum bt_mesh_feat_state friendship) if (IS_ENABLED(CONFIG_BT_SETTINGS) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_store_cfg(); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); } if (friendship == BT_MESH_FEATURE_DISABLED) { @@ -168,7 +183,7 @@ void bt_mesh_net_transmit_set(uint8_t xmit) if (IS_ENABLED(CONFIG_BT_SETTINGS) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_store_cfg(); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); } } @@ -199,7 +214,7 @@ int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit) if (IS_ENABLED(CONFIG_BT_SETTINGS) && atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_store_cfg(); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); } return 0; @@ -236,8 +251,112 @@ bool bt_mesh_fixed_group_match(uint16_t addr) } } +static int cfg_set(int argc, char **argv, char *val) +{ + struct cfg_val cfg; + int len, err; + + BT_DBG("val %s", val ? val : "(null)"); + + if (!val) { + BT_DBG("Cleared configuration state"); + return 0; + } + + len = sizeof(cfg); + err = settings_bytes_from_str(val, &cfg, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return err; + } + + if (len != sizeof(cfg)) { + BT_ERR("Unexpected value length (%d != %zu)", len, + sizeof(cfg)); + return -EINVAL; + } + + bt_mesh_net_transmit_set(cfg.net_transmit); + bt_mesh_relay_set(cfg.relay, cfg.relay_retransmit); + bt_mesh_beacon_set(cfg.beacon); + bt_mesh_gatt_proxy_set(cfg.gatt_proxy); + bt_mesh_friend_set(cfg.frnd); + bt_mesh_default_ttl_set(cfg.default_ttl); + + BT_DBG("Restored configuration state"); + + return 0; +} + +static void clear_cfg(void) +{ + int err; + + err = settings_save_one("bt_mesh/Cfg", NULL); + if (err) { + BT_ERR("Failed to clear configuration"); + } else { + BT_DBG("Cleared configuration"); + } +} + +static void store_pending_cfg(void) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct cfg_val))]; + struct cfg_val val; + char *str; + int err; + + val.net_transmit = bt_mesh_net_transmit_get(); + val.relay = bt_mesh_relay_get(); + val.relay_retransmit = bt_mesh_relay_retransmit_get(); + val.beacon = bt_mesh_beacon_enabled(); + val.gatt_proxy = bt_mesh_gatt_proxy_get(); + val.frnd = bt_mesh_friend_get(); + val.default_ttl = bt_mesh_default_ttl_get(); + + str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode configuration as value"); + return; + } + + BT_DBG("Saving configuration as value %s", str); + err = settings_save_one("bt_mesh/Cfg", str); + if (err) { + BT_ERR("Failed to store configuration"); + } else { + BT_DBG("Stored configuration"); + } +} + + +void bt_mesh_cfg_pending_store(void) +{ + if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + store_pending_cfg(); + } else { + clear_cfg(); + } +} + +static struct conf_handler bt_mesh_cfg_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = cfg_set, + .ch_commit = NULL, + .ch_export = NULL, +}; + void bt_mesh_cfg_init(void) { + int rc; + + rc = conf_register(&bt_mesh_cfg_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_settings conf"); + bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL; bt_mesh.net_xmit = BT_MESH_TRANSMIT(CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT, diff --git a/nimble/host/mesh/src/cfg.h b/nimble/host/mesh/src/cfg.h index 6f58acf8b0..40f7ed92bc 100644 --- a/nimble/host/mesh/src/cfg.h +++ b/nimble/host/mesh/src/cfg.h @@ -5,5 +5,6 @@ */ void bt_mesh_cfg_init(void); +void bt_mesh_cfg_pending_store(void); bool bt_mesh_fixed_group_match(uint16_t addr); \ No newline at end of file diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 404f7318d4..4c0da372ba 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -204,7 +204,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, } if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_store_mod_pub(model); + bt_mesh_model_pub_store(model); } return STATUS_SUCCESS; @@ -245,7 +245,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, } if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_store_mod_pub(model); + bt_mesh_model_pub_store(model); } return STATUS_SUCCESS; @@ -273,7 +273,7 @@ uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx) model->keys[i] = key_idx; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_mod_bind(model); + bt_mesh_model_bind_store(model); } return STATUS_SUCCESS; @@ -301,7 +301,7 @@ uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store) model->keys[i] = BT_MESH_KEY_UNUSED; if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_store_mod_bind(model); + bt_mesh_model_bind_store(model); } if (model->pub && model->pub->key == key_idx) { @@ -1040,7 +1040,7 @@ static void mod_sub_add(struct bt_mesh_model *model, status = STATUS_SUCCESS; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_mod_sub(mod); + bt_mesh_model_sub_store(mod); } if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { @@ -1110,7 +1110,7 @@ static void mod_sub_del(struct bt_mesh_model *model, *match = BT_MESH_ADDR_UNASSIGNED; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_mod_sub(mod); + bt_mesh_model_sub_store(mod); } } @@ -1181,7 +1181,7 @@ static void mod_sub_overwrite(struct bt_mesh_model *model, status = STATUS_SUCCESS; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_mod_sub(mod); + bt_mesh_model_sub_store(mod); } if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { @@ -1236,7 +1236,7 @@ static void mod_sub_del_all(struct bt_mesh_model *model, NULL); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_mod_sub(mod); + bt_mesh_model_sub_store(mod); } status = STATUS_SUCCESS; @@ -1470,7 +1470,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_mod_sub(mod); + bt_mesh_model_sub_store(mod); } status = STATUS_SUCCESS; @@ -1535,7 +1535,7 @@ static void mod_sub_va_del(struct bt_mesh_model *model, *match = BT_MESH_ADDR_UNASSIGNED; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_mod_sub(mod); + bt_mesh_model_sub_store(mod); } status = STATUS_SUCCESS; @@ -1594,7 +1594,7 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, mod->groups[0] = sub_addr; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_mod_sub(mod); + bt_mesh_model_sub_store(mod); } if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { @@ -2492,7 +2492,7 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, if (IS_ENABLED(CONFIG_BT_SETTINGS)) { if (clear_count) { - bt_mesh_store_mod_sub(mod); + bt_mesh_model_sub_store(mod); } } diff --git a/nimble/host/mesh/src/heartbeat.c b/nimble/host/mesh/src/heartbeat.c index 09d64594de..656942b426 100644 --- a/nimble/host/mesh/src/heartbeat.c +++ b/nimble/host/mesh/src/heartbeat.c @@ -17,6 +17,16 @@ #include "foundation.h" #include "mesh/glue.h" +/* Heartbeat Publication information for persistent storage. */ +struct hb_pub_val { + uint16_t dst; + uint8_t period; + uint8_t ttl; + uint16_t feat; + uint16_t net_idx:12, + indefinite:1; +}; + struct bt_mesh_hb_cb hb_cb; static struct bt_mesh_hb_pub pub; @@ -215,7 +225,8 @@ uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub) if (IS_ENABLED(CONFIG_BT_SETTINGS) && bt_mesh_is_provisioned()) { - bt_mesh_store_hb_pub(); + bt_mesh_settings_store_schedule( + BT_MESH_SETTINGS_HB_PUB_PENDING); } return STATUS_SUCCESS; @@ -244,7 +255,8 @@ uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub) } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_hb_pub(); + bt_mesh_settings_store_schedule( + BT_MESH_SETTINGS_HB_PUB_PENDING); } return STATUS_SUCCESS; @@ -356,3 +368,91 @@ void bt_mesh_hb_resume(void) k_delayed_work_submit(&pub_timer, K_NO_WAIT); } } + +static int hb_pub_set(int argc, char **argv, char *val) +{ + struct bt_mesh_hb_pub pub; + struct hb_pub_val hb_val; + int len, err; + BT_DBG("val %s", val ? val : "(null)"); + len = sizeof(hb_val); + err = settings_bytes_from_str(val, &hb_val, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return err; + } + if (len != sizeof(hb_val)) { + BT_ERR("Unexpected value length (%d != %zu)", len, + sizeof(hb_val)); + return -EINVAL; + } + pub.dst = hb_val.dst; + pub.period = bt_mesh_hb_pwr2(hb_val.period); + pub.ttl = hb_val.ttl; + pub.feat = hb_val.feat; + pub.net_idx = hb_val.net_idx; + if (hb_val.indefinite) { + pub.count = 0xffff; + } else { + pub.count = 0; + } + (void) bt_mesh_hb_pub_set(&pub); + + BT_DBG("Restored heartbeat publication"); + + return 0; +} + +void bt_mesh_hb_pub_pending_store(void) +{ + struct bt_mesh_hb_pub pub; + char buf[BT_SETTINGS_SIZE(sizeof(struct hb_pub_val))]; + struct hb_pub_val val; + int err; + char *str; + + bt_mesh_hb_pub_get(&pub); + if (pub.dst == BT_MESH_ADDR_UNASSIGNED) { + err = settings_save_one("bt_mesh/HBPub", NULL); + } else { + val.indefinite = (pub.count == 0xffff); + val.dst = pub.dst; + val.period = bt_mesh_hb_log(pub.period); + val.ttl = pub.ttl; + val.feat = pub.feat; + val.net_idx = pub.net_idx; + + str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode configuration as value"); + return; + } + + BT_DBG("Saving configuration as value %s", str); + err = settings_save_one("bt_mesh/HBPub", str); + } + + if (err) { + BT_ERR("Failed to store Heartbeat Publication"); + } else { + BT_DBG("Stored Heartbeat Publication"); + } +} + +static struct conf_handler bt_mesh_hb_pub_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = hb_pub_set, + .ch_commit = NULL, + .ch_export = NULL, + }; + +void bt_mesh_hb_pub_init(void) +{ + int rc; + + rc = conf_register(&bt_mesh_hb_pub_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_hb_pub conf"); +} \ No newline at end of file diff --git a/nimble/host/mesh/src/heartbeat.h b/nimble/host/mesh/src/heartbeat.h index 92b0cae9e4..7fcfacf197 100644 --- a/nimble/host/mesh/src/heartbeat.h +++ b/nimble/host/mesh/src/heartbeat.h @@ -39,3 +39,5 @@ void bt_mesh_hb_feature_changed(uint16_t features); uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *hb_pub); uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period); void bt_mesh_hb_sub_reset_count(void); +void bt_mesh_hb_pub_pending_store(void); +void bt_mesh_hb_pub_init(void); \ No newline at end of file diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index 10c6fff991..b22dc1363f 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -108,7 +108,7 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, memcpy(node->dev_key, dev_key, 16); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cdb_node(node); + bt_mesh_cdb_node_store(node); } } @@ -199,7 +199,7 @@ void bt_mesh_reset(void) } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_clear_net(); + bt_mesh_net_clear(); } memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key)); @@ -338,6 +338,17 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, } #endif + bt_mesh_app_key_init(); + bt_mesh_access_init(); + bt_mesh_hb_pub_init(); + bt_mesh_rpl_init(); + bt_mesh_net_key_init(); +#if CONFIG_BT_MESH_LABEL_COUNT > 0 + bt_mesh_va_init(); +#endif +#if CONFIG_BT_MESH_CDB + bt_mesh_cdb_init(); +#endif bt_mesh_cfg_init(); bt_mesh_net_init(); bt_mesh_trans_init(); diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index bbe186ec8d..76ef9eaef8 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -49,6 +49,31 @@ #define SRC(pdu) (sys_get_be16(&(pdu)[5])) #define DST(pdu) (sys_get_be16(&(pdu)[7])) +/** Define CONFIG_BT_MESH_SEQ_STORE_RATE even if settings are disabled to + * compile the code. + */ +#ifndef CONFIG_BT_SETTINGS +#define CONFIG_BT_MESH_SEQ_STORE_RATE 1 +#endif + +/* Mesh network information for persistent storage. */ +struct net_val { + uint16_t primary_addr; + uint8_t dev_key[16]; +} __packed; + +/* Sequence number information for persistent storage. */ +struct seq_val { + uint8_t val[3]; +} __packed; + +/* IV Index & IV Update information for persistent storage. */ +struct iv_val { + uint32_t iv_index; + uint8_t iv_update:1, + iv_duration:7; +} __packed; + static struct { uint32_t src : 15, /* MSb of source is always 0 */ seq : 17; @@ -112,6 +137,31 @@ static void msg_cache_add(struct bt_mesh_net_rx *rx) msg_cache_next %= ARRAY_SIZE(msg_cache); } +static void store_net(void) +{ + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_NET_PENDING); +} + +static void store_iv(bool only_duration) +{ + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_IV_PENDING); + + if (!only_duration) { + /* Always update Seq whenever IV changes */ + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); + } +} + +static void store_seq(void) +{ + if (CONFIG_BT_MESH_SEQ_STORE_RATE && + (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)) { + return; + } + + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); +} + int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], uint32_t iv_index) { @@ -147,9 +197,9 @@ int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], if (IS_ENABLED(CONFIG_BT_SETTINGS)) { BT_DBG("Storing network information persistently"); - bt_mesh_store_net(); - bt_mesh_store_subnet(idx); - bt_mesh_store_iv(false); + store_net(); + bt_mesh_subnet_store(idx); + store_iv(false); } return 0; @@ -282,7 +332,7 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_iv(false); + store_iv(false); } return true; @@ -293,7 +343,7 @@ uint32_t bt_mesh_next_seq(void) uint32_t seq = bt_mesh.seq++; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_seq(); + store_seq(); } if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) && @@ -822,7 +872,7 @@ static void ivu_refresh(struct ble_npl_event *work) if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) { if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_iv(true); + store_iv(true); } k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); @@ -833,14 +883,164 @@ static void ivu_refresh(struct ble_npl_event *work) bt_mesh_beacon_ivu_initiator(true); bt_mesh_net_iv_update(bt_mesh.iv_index, false); } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_iv(true); + store_iv(true); + } +} + +static int net_set(int argc, char **argv, char *val) +{ + struct net_val net; + int len, err; + + BT_DBG("val %s", val ? val : "(null)"); + + if (!val) { + bt_mesh_comp_unprovision(); + memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key)); + return 0; + } + + len = sizeof(net); + err = settings_bytes_from_str(val, &net, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return err; + } + + if (len != sizeof(net)) { + BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(net)); + return -EINVAL; + } + + memcpy(bt_mesh.dev_key, net.dev_key, sizeof(bt_mesh.dev_key)); + bt_mesh_comp_provision(net.primary_addr); + + BT_DBG("Provisioned with primary address 0x%04x", net.primary_addr); + BT_DBG("Recovered DevKey %s", bt_hex(bt_mesh.dev_key, 16)); + + return 0; +} + +static int iv_set(int argc, char **argv, char *val) +{ + struct iv_val iv; + int len, err; + + BT_DBG("val %s", val ? val : "(null)"); + + if (!val) { + bt_mesh.iv_index = 0U; + atomic_clear_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); + return 0; + } + + len = sizeof(iv); + err = settings_bytes_from_str(val, &iv, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return err; + } + + if (len != sizeof(iv)) { + BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(iv)); + return -EINVAL; + } + + bt_mesh.iv_index = iv.iv_index; + atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv.iv_update); + bt_mesh.ivu_duration = iv.iv_duration; + + BT_DBG("IV Index 0x%04x (IV Update Flag %u) duration %u hours", + (unsigned) iv.iv_index, iv.iv_update, iv.iv_duration); + + return 0; +} + +static int seq_set(int argc, char **argv, char *val) +{ + struct seq_val seq; + int len, err; + + BT_DBG("val %s", val ? val : "(null)"); + + if (!val) { + bt_mesh.seq = 0; + return 0; + } + + len = sizeof(seq); + err = settings_bytes_from_str(val, &seq, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return err; + } + + if (len != sizeof(seq)) { + BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(seq)); + return -EINVAL; + } + + bt_mesh.seq = sys_get_le24(seq.val); + + if (CONFIG_BT_MESH_SEQ_STORE_RATE > 0) { + /* Make sure we have a large enough sequence number. We + * subtract 1 so that the first transmission causes a write + * to the settings storage. + */ + bt_mesh.seq += (CONFIG_BT_MESH_SEQ_STORE_RATE - + (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)); + bt_mesh.seq--; } + + BT_DBG("Sequence Number 0x%06x", bt_mesh.seq); + + return 0; } +static struct conf_handler bt_mesh_net_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = net_set, + .ch_commit = NULL, + .ch_export = NULL, +}; + +static struct conf_handler bt_mesh_iv_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = iv_set, + .ch_commit = NULL, + .ch_export = NULL, +}; + +static struct conf_handler bt_mesh_seq_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = seq_set, + .ch_commit = NULL, + .ch_export = NULL, +}; + void bt_mesh_net_init(void) { int rc; + rc = conf_register(&bt_mesh_net_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_net conf"); + + + rc = conf_register(&bt_mesh_iv_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_iv conf"); + + rc = conf_register(&bt_mesh_seq_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_seq conf"); + k_delayed_work_init(&bt_mesh.ivu_timer, ivu_refresh); k_work_init(&bt_mesh.local_work, bt_mesh_net_local); @@ -852,7 +1052,141 @@ void bt_mesh_net_init(void) assert(rc == 0); rc = os_mbuf_pool_init(&loopback_os_mbuf_pool, &loopback_buf_mempool, - LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE, - MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS)); + LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE, + MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS)); assert(rc == 0); } + +static void clear_iv(void) +{ + int err; + + err = settings_save_one("bt_mesh/IV", NULL); + if (err) { + BT_ERR("Failed to clear IV"); + } else { + BT_DBG("Cleared IV"); + } +} + +static void store_pending_iv(void) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct iv_val))]; + struct iv_val iv; + char *str; + int err; + + iv.iv_index = bt_mesh.iv_index; + iv.iv_update = atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); + iv.iv_duration = bt_mesh.ivu_duration; + + str = settings_str_from_bytes(&iv, sizeof(iv), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode IV as value"); + return; + } + + BT_DBG("Saving IV as value %s", str); + err = settings_save_one("bt_mesh/IV", str); + if (err) { + BT_ERR("Failed to store IV"); + } else { + BT_DBG("Stored IV"); + } +} + +void bt_mesh_net_pending_iv_store(void) +{ + if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + store_pending_iv(); + } else { + clear_iv(); + } +} + +static void clear_net(void) +{ + int err; + + err = settings_save_one("bt_mesh/Net", NULL); + if (err) { + BT_ERR("Failed to clear Network"); + } else { + BT_DBG("Cleared Network"); + } +} + +static void store_pending_net(void) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct net_val))]; + struct net_val net; + char *str; + int err; + + BT_DBG("addr 0x%04x DevKey %s", bt_mesh_primary_addr(), + bt_hex(bt_mesh.dev_key, 16)); + + net.primary_addr = bt_mesh_primary_addr(); + memcpy(net.dev_key, bt_mesh.dev_key, 16); + + str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode Network as value"); + return; + } + + BT_DBG("Saving Network as value %s", str); + err = settings_save_one("bt_mesh/Net", str); + if (err) { + BT_ERR("Failed to store Network"); + } else { + BT_DBG("Stored Network"); + } +} + +void bt_mesh_net_pending_net_store(void) +{ + if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + store_pending_net(); + } else { + clear_net(); + } +} + +void bt_mesh_net_pending_seq_store(void) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct seq_val))]; + char *str; + struct seq_val seq; + int err; + + sys_put_le24(bt_mesh.seq, seq.val); + + str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode Network as value"); + return; + } + + BT_DBG("Saving Network as value %s", str); + err = settings_save_one("bt_mesh/Seq", str); + if (err) { + BT_ERR("Failed to stor Seq value"); + } else { + BT_DBG("Stored Seq value"); + } +} + +void bt_mesh_net_clear(void) +{ + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_NET_PENDING); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_IV_PENDING); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); +} + +void bt_mesh_net_settings_commit(void) +{ + if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) { + k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); + } +} diff --git a/nimble/host/mesh/src/net.h b/nimble/host/mesh/src/net.h index 8c501540df..33b491e4b5 100644 --- a/nimble/host/mesh/src/net.h +++ b/nimble/host/mesh/src/net.h @@ -184,17 +184,6 @@ enum { BT_MESH_IVU_TEST, /* IV Update test mode */ BT_MESH_IVU_PENDING, /* Update blocked by SDU in progress */ - /* pending storage actions, must reside within first 32 flags */ - BT_MESH_RPL_PENDING, - BT_MESH_KEYS_PENDING, - BT_MESH_NET_PENDING, - BT_MESH_IV_PENDING, - BT_MESH_SEQ_PENDING, - BT_MESH_HB_PUB_PENDING, - BT_MESH_CFG_PENDING, - BT_MESH_MOD_PENDING, - BT_MESH_VA_PENDING, - /* Feature flags */ BT_MESH_RELAY, BT_MESH_BEACON, @@ -309,7 +298,11 @@ uint32_t bt_mesh_next_seq(void); void bt_mesh_net_init(void); void bt_mesh_net_header_parse(struct os_mbuf *buf, struct bt_mesh_net_rx *rx); - +void bt_mesh_net_pending_net_store(void); +void bt_mesh_net_pending_iv_store(void); +void bt_mesh_net_pending_seq_store(void); +void bt_mesh_net_clear(void); +void bt_mesh_net_settings_commit(void); static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb, void *cb_data) diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index 2e592096e1..3b4b76598d 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -541,7 +541,7 @@ static void prov_complete(const uint8_t *data) #if MYNEWT_VAL(BLE_MESH_CDB) if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cdb_node(node); + bt_mesh_cdb_node_store(node); } #endif diff --git a/nimble/host/mesh/src/rpl.c b/nimble/host/mesh/src/rpl.c index 93c2e1a885..830ab1b01e 100644 --- a/nimble/host/mesh/src/rpl.c +++ b/nimble/host/mesh/src/rpl.c @@ -10,6 +10,7 @@ #define MESH_LOG_MODULE BLE_MESH_RPL_LOG #include "log/log.h" +#include #include "mesh_priv.h" #include "adv.h" @@ -17,8 +18,27 @@ #include "rpl.h" #include "settings.h" +/* Replay Protection List information for persistent storage. */ +struct rpl_val { + uint32_t seq:24, + old_iv:1; +}; + static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)]; +static void schedule_rpl_store(struct bt_mesh_rpl *entry) +{ +#ifdef CONFIG_BT_SETTINGS + entry->store = true; +#endif + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); +} + +static void schedule_rpl_clear(void) +{ + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); +} + void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx) { @@ -27,7 +47,7 @@ void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, rpl->old_iv = rx->old_iv; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_rpl(rpl); + schedule_rpl_store(rpl); } } @@ -95,13 +115,13 @@ void bt_mesh_rpl_clear(void) BT_DBG(""); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_clear_rpl(); + schedule_rpl_clear(); } else { (void)memset(replay_list, 0, sizeof(replay_list)); } } -struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src) +static struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src) { int i; @@ -114,7 +134,7 @@ struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src) return NULL; } -struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src) +static struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src) { int i; @@ -128,15 +148,6 @@ struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src) return NULL; } -void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(replay_list); i++) { - func(&replay_list[i], user_data); - } -} - void bt_mesh_rpl_reset(void) { int i; @@ -155,8 +166,159 @@ void bt_mesh_rpl_reset(void) } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_rpl(rpl); + schedule_rpl_store(rpl); } } } +} + +static int rpl_set(int argc, char **argv, char *val) +{ + struct bt_mesh_rpl *entry; + struct rpl_val rpl; + int len, err; + uint16_t src; + + if (argc < 1) { + BT_ERR("Invalid argc (%d)", argc); + return -ENOENT; + } + + BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); + + src = strtol(argv[0], NULL, 16); + entry = bt_mesh_rpl_find(src); + + if (!val) { + if (entry) { + memset(entry, 0, sizeof(*entry)); + } else { + BT_WARN("Unable to find RPL entry for 0x%04x", src); + } + + return 0; + } + + if (!entry) { + entry = bt_mesh_rpl_alloc(src); + if (!entry) { + BT_ERR("Unable to allocate RPL entry for 0x%04x", src); + return -ENOMEM; + } + } + + len = sizeof(rpl); + err = settings_bytes_from_str(val, &rpl, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return err; + } + + if (len != sizeof(rpl)) { + BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(rpl)); + return -EINVAL; + } + + entry->seq = rpl.seq; + entry->old_iv = rpl.old_iv; + + BT_DBG("RPL entry for 0x%04x: Seq 0x%06x old_iv %u", entry->src, + (unsigned) entry->seq, entry->old_iv); + return 0; +} + +static void store_rpl(struct bt_mesh_rpl *entry) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct rpl_val))]; + struct rpl_val rpl; + char path[18]; + char *str; + int err; + + BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src, + (unsigned) entry->seq, entry->old_iv); + + rpl.seq = entry->seq; + rpl.old_iv = entry->old_iv; + + str = settings_str_from_bytes(&rpl, sizeof(rpl), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode RPL as value"); + return; + } + + snprintk(path, sizeof(path), "bt_mesh/RPL/%x", entry->src); + + BT_DBG("Saving RPL %s as value %s", path, str); + err = settings_save_one(path, str); + if (err) { + BT_ERR("Failed to store RPL"); + } else { + BT_DBG("Stored RPL"); + } +} + +static void clear_rpl(struct bt_mesh_rpl *rpl) +{ + int err; + char path[18]; + + if (!rpl->src) { + return; + } + + snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear RPL"); + } else { + BT_DBG("Cleared RPL"); + } + + (void)memset(rpl, 0, sizeof(*rpl)); +} + +static void store_pending_rpl(struct bt_mesh_rpl *rpl) +{ + BT_DBG(""); + +#ifdef CONFIG_BT_SETTINGS + if (!rpl->store) { + return; + } + + rpl->store = false; +#endif + store_rpl(rpl); +} + +void bt_mesh_rpl_pending_store(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + store_pending_rpl(&replay_list[i]); + } else { + clear_rpl(&replay_list[i]); + } + } +} + +static struct conf_handler bt_mesh_rpl_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = rpl_set, + .ch_commit = NULL, + .ch_export = NULL, + }; + +void bt_mesh_rpl_init(void) +{ + int rc; + + rc = conf_register(&bt_mesh_rpl_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_rpl conf"); } \ No newline at end of file diff --git a/nimble/host/mesh/src/rpl.h b/nimble/host/mesh/src/rpl.h index 0592712f87..d47484a329 100644 --- a/nimble/host/mesh/src/rpl.h +++ b/nimble/host/mesh/src/rpl.h @@ -23,8 +23,7 @@ void bt_mesh_rpl_reset(void); bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match); void bt_mesh_rpl_clear(void); -struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src); -struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src); -void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data); void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, - struct bt_mesh_net_rx *rx); \ No newline at end of file + struct bt_mesh_net_rx *rx); +void bt_mesh_rpl_pending_store(void); +void bt_mesh_rpl_init(void); \ No newline at end of file diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index 903230d1b5..3d28ac94da 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -10,144 +10,25 @@ #if MYNEWT_VAL(BLE_MESH_SETTINGS) #include "mesh_priv.h" -#include "mesh/mesh.h" #include "mesh/glue.h" #include "subnet.h" #include "app_keys.h" #include "net.h" +#include "cdb_priv.h" #include "rpl.h" #include "crypto.h" #include "transport.h" #include "heartbeat.h" #include "access.h" -#include "foundation.h" #include "proxy.h" #include "settings.h" -#include "lpn.h" #include "cfg.h" #include "config/config.h" -/* Tracking of what storage changes are pending for App and Net Keys. We - * track this in a separate array here instead of within the respective - * bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key - * gets deleted its struct becomes invalid and may be reused for other keys. - */ -struct key_update { - uint16_t key_idx:12, /* AppKey or NetKey Index */ - valid:1, /* 1 if this entry is valid, 0 if not */ - app_key:1, /* 1 if this is an AppKey, 0 if a NetKey */ - clear:1; /* 1 if key needs clearing, 0 if storing */ -}; - -static struct key_update key_updates[CONFIG_BT_MESH_APP_KEY_COUNT + - CONFIG_BT_MESH_SUBNET_COUNT]; - static struct k_delayed_work pending_store; - -/* Mesh network storage information */ -struct net_val { - uint16_t primary_addr; - uint8_t dev_key[16]; -} __packed; - -/* Sequence number storage */ -struct seq_val { - uint8_t val[3]; -} __packed; - -/* Heartbeat Publication storage */ -struct hb_pub_val { - uint16_t dst; - uint8_t period; - uint8_t ttl; - uint16_t feat; - uint16_t net_idx:12, - indefinite:1; -}; - -/* Miscelaneous configuration server model states */ -struct cfg_val { - uint8_t net_transmit; - uint8_t relay; - uint8_t relay_retransmit; - uint8_t beacon; - uint8_t gatt_proxy; - uint8_t frnd; - uint8_t default_ttl; -}; - -/* IV Index & IV Update storage */ -struct iv_val { - uint32_t iv_index; - uint8_t iv_update:1, - iv_duration:7; -} __packed; - -/* Replay Protection List storage */ -struct rpl_val { - uint32_t seq:24, - old_iv:1; -}; - -/* NetKey storage information */ -struct net_key_val { - uint8_t kr_flag:1, - kr_phase:7; - uint8_t val[2][16]; -} __packed; - -/* AppKey storage information */ -struct app_key_val { - uint16_t net_idx; - bool updated; - uint8_t val[2][16]; -} __packed; - -struct mod_pub_val { - uint16_t addr; - uint16_t key; - uint8_t ttl; - uint8_t retransmit; - uint8_t period; - uint8_t period_div:4, - cred:1; -}; - -/* Virtual Address information */ -struct va_val { - uint16_t ref; - uint16_t addr; - uint8_t uuid[16]; -} __packed; - -struct cdb_net_val { - uint32_t iv_index; - bool iv_update; -} __packed; - -/* Node storage information */ -struct node_val { - uint16_t net_idx; - uint8_t num_elem; - uint8_t flags; -#define F_NODE_CONFIGURED 0x01 - uint8_t uuid[16]; - uint8_t dev_key[16]; -} __packed; - -struct node_update { - uint16_t addr; - bool clear; -}; - -#if MYNEWT_VAL(BLE_MESH_CDB) -static struct node_update cdb_node_updates[MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)]; -static struct key_update cdb_key_updates[ - MYNEWT_VAL(BLE_MESH_CDB_SUBNET_COUNT) + - MYNEWT_VAL(BLE_MESH_CDB_APP_KEY_COUNT)]; -#endif +static ATOMIC_DEFINE(pending_flags, BT_MESH_SETTINGS_FLAG_COUNT); int settings_name_next(char *name, char **next) { @@ -181,2269 +62,132 @@ int settings_name_next(char *name, char **next) return rc; } -static int net_set(int argc, char **argv, char *val) -{ - struct net_val net; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - if (!val) { - bt_mesh_comp_unprovision(); - memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key)); - return 0; - } - - len = sizeof(net); - err = settings_bytes_from_str(val, &net, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(net)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(net)); - return -EINVAL; - } - - memcpy(bt_mesh.dev_key, net.dev_key, sizeof(bt_mesh.dev_key)); - bt_mesh_comp_provision(net.primary_addr); - - BT_DBG("Provisioned with primary address 0x%04x", net.primary_addr); - BT_DBG("Recovered DevKey %s", bt_hex(bt_mesh.dev_key, 16)); - - return 0; -} - -static int iv_set(int argc, char **argv, char *val) -{ - struct iv_val iv; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - if (!val) { - bt_mesh.iv_index = 0U; - atomic_clear_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); - return 0; - } - - len = sizeof(iv); - err = settings_bytes_from_str(val, &iv, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(iv)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(iv)); - return -EINVAL; - } - - bt_mesh.iv_index = iv.iv_index; - atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv.iv_update); - bt_mesh.ivu_duration = iv.iv_duration; - - BT_DBG("IV Index 0x%04x (IV Update Flag %u) duration %u hours", - (unsigned) iv.iv_index, iv.iv_update, iv.iv_duration); - - return 0; -} - -static int seq_set(int argc, char **argv, char *val) -{ - struct seq_val seq; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - if (!val) { - bt_mesh.seq = 0; - return 0; - } - - len = sizeof(seq); - err = settings_bytes_from_str(val, &seq, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(seq)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(seq)); - return -EINVAL; - } - - bt_mesh.seq = sys_get_le24(seq.val); - - if (CONFIG_BT_MESH_SEQ_STORE_RATE > 0) { - /* Make sure we have a large enough sequence number. We - * subtract 1 so that the first transmission causes a write - * to the settings storage. - */ - bt_mesh.seq += (CONFIG_BT_MESH_SEQ_STORE_RATE - - (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)); - bt_mesh.seq--; - } - - BT_DBG("Sequence Number 0x%06x", bt_mesh.seq); - - return 0; -} - -static int rpl_set(int argc, char **argv, char *val) +static int mesh_commit(void) { - struct bt_mesh_rpl *entry; - struct rpl_val rpl; - int len, err; - uint16_t src; - - if (argc < 1) { - BT_ERR("Invalid argc (%d)", argc); - return -ENOENT; - } - - BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); - - src = strtol(argv[0], NULL, 16); - entry = bt_mesh_rpl_find(src); - - if (!val) { - if (entry) { - memset(entry, 0, sizeof(*entry)); - } else { - BT_WARN("Unable to find RPL entry for 0x%04x", src); - } - + if (!bt_mesh_subnet_next(NULL)) { + /* Nothing to do since we're not yet provisioned */ return 0; } - if (!entry) { - entry = bt_mesh_rpl_alloc(src); - if (!entry) { - BT_ERR("Unable to allocate RPL entry for 0x%04x", src); - return -ENOMEM; - } - } - - len = sizeof(rpl); - err = settings_bytes_from_str(val, &rpl, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(rpl)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(rpl)); - return -EINVAL; + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { + bt_mesh_proxy_prov_disable(true); } - entry->seq = rpl.seq; - entry->old_iv = rpl.old_iv; + bt_mesh_net_settings_commit(); + bt_mesh_model_settings_commit(); - BT_DBG("RPL entry for 0x%04x: Seq 0x%06x old_iv %u", entry->src, - (unsigned) entry->seq, entry->old_iv); + atomic_set_bit(bt_mesh.flags, BT_MESH_VALID); + bt_mesh_start(); return 0; } -static int net_key_set(int argc, char **argv, char *val) -{ - struct net_key_val key; - int len, err; - uint16_t net_idx; - - BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); - - net_idx = strtol(argv[0], NULL, 16); - - len = sizeof(key); - err = settings_bytes_from_str(val, &key, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(key)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(key)); - return -EINVAL; - } - - BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx); - - return bt_mesh_subnet_set( - net_idx, key.kr_phase, key.val[0], - (key.kr_phase != BT_MESH_KR_NORMAL) ? key.val[1] : NULL); -} - -static int app_key_set(int argc, char **argv, char *val) -{ - struct app_key_val key; - uint16_t app_idx; - int len_rd, err; - - BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); - - app_idx = strtol(argv[0], NULL, 16); - len_rd = strtol(argv[1], NULL, 16); - - if (!len_rd) { - return 0; - } - - err = settings_bytes_from_str(val, &key, &len_rd); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - err = bt_mesh_app_key_set(app_idx, key.net_idx, key.val[0], - key.updated ? key.val[1] : NULL); - if (err) { - BT_ERR("Failed to set \'app-key\'"); - return err; - } - - BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx); +/* Pending flags that use K_NO_WAIT as the storage timeout */ +#define NO_WAIT_PENDING_BITS (BIT(BT_MESH_SETTINGS_NET_PENDING) | \ + BIT(BT_MESH_SETTINGS_IV_PENDING) | \ + BIT(BT_MESH_SETTINGS_SEQ_PENDING) | \ + BIT(BT_MESH_SETTINGS_CDB_PENDING)) - return 0; -} +/* Pending flags that use CONFIG_BT_MESH_STORE_TIMEOUT */ +#define GENERIC_PENDING_BITS (BIT(BT_MESH_SETTINGS_NET_KEYS_PENDING) | \ + BIT(BT_MESH_SETTINGS_APP_KEYS_PENDING) | \ + BIT(BT_MESH_SETTINGS_HB_PUB_PENDING) | \ + BIT(BT_MESH_SETTINGS_CFG_PENDING) | \ + BIT(BT_MESH_SETTINGS_MOD_PENDING)) -static int hb_pub_set(int argc, char **argv, char *val) +void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag) { - struct bt_mesh_hb_pub pub; - struct hb_pub_val hb_val; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - len = sizeof(hb_val); - err = settings_bytes_from_str(val, &hb_val, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(hb_val)) { - BT_ERR("Unexpected value length (%d != %zu)", len, - sizeof(hb_val)); - return -EINVAL; - } + int32_t timeout_ms, remaining; - pub.dst = hb_val.dst; - pub.period = bt_mesh_hb_pwr2(hb_val.period); - pub.ttl = hb_val.ttl; - pub.feat = hb_val.feat; - pub.net_idx = hb_val.net_idx; + atomic_set_bit(pending_flags, flag); - if (hb_val.indefinite) { - pub.count = 0xffff; + if (atomic_get(pending_flags) & NO_WAIT_PENDING_BITS) { + timeout_ms = 0; + } else if (atomic_test_bit(pending_flags, + BT_MESH_SETTINGS_RPL_PENDING) && + (!(atomic_get(bt_mesh.flags) & GENERIC_PENDING_BITS) || + (CONFIG_BT_MESH_RPL_STORE_TIMEOUT < + CONFIG_BT_MESH_STORE_TIMEOUT))) { + timeout_ms = CONFIG_BT_MESH_RPL_STORE_TIMEOUT * MSEC_PER_SEC; } else { - pub.count = 0; - } - - (void)bt_mesh_hb_pub_set(&pub); - - BT_DBG("Restored heartbeat publication"); - - return 0; -} - -static int cfg_set(int argc, char **argv, char *val) -{ - struct cfg_val cfg; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - if (!val) { - BT_DBG("Cleared configuration state"); - return 0; - } - - len = sizeof(cfg); - err = settings_bytes_from_str(val, &cfg, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(cfg)) { - BT_ERR("Unexpected value length (%d != %zu)", len, - sizeof(cfg)); - return -EINVAL; - } - - bt_mesh_net_transmit_set(cfg.net_transmit); - bt_mesh_relay_set(cfg.relay, cfg.relay_retransmit); - bt_mesh_beacon_set(cfg.beacon); - bt_mesh_gatt_proxy_set(cfg.gatt_proxy); - bt_mesh_friend_set(cfg.frnd); - bt_mesh_default_ttl_set(cfg.default_ttl); - - BT_DBG("Restored configuration state"); - - return 0; -} - -static int mod_set_bind(struct bt_mesh_model *mod, char *val) -{ - int len, err, i; - - /* Start with empty array regardless of cleared or set value */ - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { - mod->keys[i] = BT_MESH_KEY_UNUSED; - } - - if (!val) { - BT_DBG("Cleared bindings for model"); - return 0; - } - - len = sizeof(mod->keys); - err = settings_bytes_from_str(val, mod->keys, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; - } - - BT_DBG("Decoded %u bound keys for model", len / sizeof(mod->keys[0])); - return 0; -} - -static int mod_set_sub(struct bt_mesh_model *mod, char *val) -{ - int len, err; - - /* Start with empty array regardless of cleared or set value */ - memset(mod->groups, 0, sizeof(mod->groups)); - - if (!val) { - BT_DBG("Cleared subscriptions for model"); - return 0; - } - - len = sizeof(mod->groups); - err = settings_bytes_from_str(val, mod->groups, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; - } - - BT_DBG("Decoded %u subscribed group addresses for model", - len / sizeof(mod->groups[0])); - return 0; -} - -static int mod_set_pub(struct bt_mesh_model *mod, char *val) -{ - struct mod_pub_val pub; - int len, err; - - if (!mod->pub) { - BT_WARN("Model has no publication context!"); - return -EINVAL; + timeout_ms = CONFIG_BT_MESH_STORE_TIMEOUT * MSEC_PER_SEC; } - if (!val) { - mod->pub->addr = BT_MESH_ADDR_UNASSIGNED; - mod->pub->key = 0; - mod->pub->cred = 0; - mod->pub->ttl = 0; - mod->pub->period = 0; - mod->pub->retransmit = 0; - mod->pub->period_div = pub.period_div; - mod->pub->count = 0; - - BT_DBG("Cleared publication for model"); - return 0; - } - - len = sizeof(pub); - err = settings_bytes_from_str(val, &pub, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; - } - - if (len != sizeof(pub)) { - BT_ERR("Invalid length for model publication"); - return -EINVAL; + remaining = k_delayed_work_remaining_get(&pending_store); + if ((remaining > 0) && remaining < timeout_ms) { + BT_DBG("Not rescheduling due to existing earlier deadline"); + return; } - mod->pub->addr = pub.addr; - mod->pub->key = pub.key; - mod->pub->cred = pub.cred; - mod->pub->ttl = pub.ttl; - mod->pub->period = pub.period; - mod->pub->retransmit = pub.retransmit; - mod->pub->count = 0; - - BT_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x", - pub.addr, pub.key); - - return 0; -} - -static int mod_data_set(struct bt_mesh_model *mod, - char *name, char *len_rd) -{ - char *next; - - settings_name_next(name, &next); + BT_DBG("Waiting %d seconds", timeout_ms / MSEC_PER_SEC); - if (mod->cb && mod->cb->settings_set) { - return mod->cb->settings_set(mod, next, len_rd); - } - - return 0; + k_delayed_work_submit(&pending_store, K_MSEC(timeout_ms)); } - -static int mod_set(bool vnd, int argc, char **argv, char *val) +static void store_pending(struct ble_npl_event *work) { - struct bt_mesh_model *mod; - uint8_t elem_idx, mod_idx; - uint16_t mod_key; - - if (argc < 2) { - BT_ERR("Too small argc (%d)", argc); - return -ENOENT; - } - - mod_key = strtol(argv[0], NULL, 16); - elem_idx = mod_key >> 8; - mod_idx = mod_key; - - BT_DBG("Decoded mod_key 0x%04x as elem_idx %u mod_idx %u", - mod_key, elem_idx, mod_idx); - - mod = bt_mesh_model_get(vnd, elem_idx, mod_idx); - if (!mod) { - BT_ERR("Failed to get model for elem_idx %u mod_idx %u", - elem_idx, mod_idx); - return -ENOENT; + BT_DBG(""); + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_RPL_PENDING)) { + bt_mesh_rpl_pending_store(); } - if (!strcmp(argv[1], "bind")) { - return mod_set_bind(mod, val); + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_NET_KEYS_PENDING)) { + bt_mesh_subnet_pending_store(); } - if (!strcmp(argv[1], "sub")) { - return mod_set_sub(mod, val); + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_APP_KEYS_PENDING)) { + bt_mesh_app_key_pending_store(); } - if (!strcmp(argv[1], "pub")) { - return mod_set_pub(mod, val); + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_NET_PENDING)) { + bt_mesh_net_pending_net_store(); } - if (!strcmp(argv[1], "data")) { - return mod_data_set(mod, argv[1], val); + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_IV_PENDING)) { + bt_mesh_net_pending_iv_store(); } - BT_WARN("Unknown module key %s", argv[1]); - return -ENOENT; -} - -static int sig_mod_set(int argc, char **argv, char *val) -{ - return mod_set(false, argc, argv, val); -} - -static int vnd_mod_set(int argc, char **argv, char *val) -{ - return mod_set(true, argc, argv, val); -} - -#if CONFIG_BT_MESH_LABEL_COUNT > 0 -static int va_set(int argc, char **argv, char *val) -{ - struct va_val va; - struct bt_mesh_va *lab; - uint16_t index; - int len, err; - - if (argc < 1) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_SEQ_PENDING)) { + bt_mesh_net_pending_seq_store(); } - index = strtol(argv[0], NULL, 16); - - if (val == NULL) { - BT_WARN("Mesh Virtual Address length = 0"); - return 0; + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_HB_PUB_PENDING)) { + bt_mesh_hb_pub_pending_store(); } - err = settings_bytes_from_str(val, &va, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_CFG_PENDING)) { + bt_mesh_cfg_pending_store(); } - if (len != sizeof(struct va_val)) { - BT_ERR("Invalid length for virtual address"); - return -EINVAL; + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_MOD_PENDING)) { + bt_mesh_model_pending_store(); } - if (va.ref == 0) { - BT_WARN("Ignore Mesh Virtual Address ref = 0"); - return 0; + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_VA_PENDING)) { + bt_mesh_va_pending_store(); } - lab = bt_mesh_va_get(index); - if (lab == NULL) { - BT_WARN("Out of labels buffers"); - return -ENOBUFS; +#if IS_ENABLED(CONFIG_BT_MESH_CDB) + if (atomic_test_and_clear_bit(pending_flags, + BT_MESH_SETTINGS_CDB_PENDING)) { + bt_mesh_cdb_pending_store(); } - - memcpy(lab->uuid, va.uuid, 16); - lab->addr = va.addr; - lab->ref = va.ref; - - BT_DBG("Restored Virtual Address, addr 0x%04x ref 0x%04x", - lab->addr, lab->ref); - - return 0; -} #endif - -#if MYNEWT_VAL(BLE_MESH_CDB) -static int cdb_net_set(int argc, char *val) -{ - struct cdb_net_val net; - int len, err; - - len = sizeof(net); - err = settings_bytes_from_str(val, &net, &len); - if (err) { - BT_ERR("Failed to set \'cdb_net\'"); - return err; - } - - bt_mesh_cdb.iv_index = net.iv_index; - - if (net.iv_update) { - atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS); - } - - atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID); - - return 0; -} - -static int cdb_node_set(int argc, char *str) -{ - struct bt_mesh_cdb_node *node; - struct node_val val; - uint16_t addr; - int len, err; - - if (argc < 1) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; - } - - addr = strtol(str, NULL, 16); - len = sizeof(str); - - if (argc < 1) { - BT_DBG("val (null)"); - BT_DBG("Deleting node 0x%04x", addr); - - node = bt_mesh_cdb_node_get(addr); - if (node) { - bt_mesh_cdb_node_del(node, false); - } - - return 0; - } - - err = settings_bytes_from_str(str, &val, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; - } - - if (len != sizeof(struct node_val)) { - BT_ERR("Invalid length for node_val"); - return -EINVAL; - } - - node = bt_mesh_cdb_node_get(addr); - if (!node) { - node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem, - val.net_idx); - } - - if (!node) { - BT_ERR("No space for a new node"); - return -ENOMEM; - } - - if (val.flags & F_NODE_CONFIGURED) { - atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED); - } - - memcpy(node->uuid, val.uuid, 16); - memcpy(node->dev_key, val.dev_key, 16); - - BT_DBG("Node 0x%04x recovered from storage", addr); - - return 0; -} - -static int cdb_subnet_set(int argc, char *name) -{ - struct bt_mesh_cdb_subnet *sub; - struct net_key_val key; - uint16_t net_idx; - int len, len_rd, err; - - if (!name) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; - } - - len_rd = sizeof(sub); - net_idx = strtol(name, NULL, 16); - sub = bt_mesh_cdb_subnet_get(net_idx); - - if (len_rd == 0) { - BT_DBG("val (null)"); - if (!sub) { - BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx); - return -ENOENT; - } - - BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx); - bt_mesh_cdb_subnet_del(sub, false); - return 0; - } - - len = sizeof(key); - err = settings_bytes_from_str(name, &key, &len); - if (err) { - BT_ERR("Failed to set \'net-key\'"); - return err; - } - - if (sub) { - BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx); - - sub->kr_phase = key.kr_phase; - memcpy(sub->keys[0].net_key, &key.val[0], 16); - memcpy(sub->keys[1].net_key, &key.val[1], 16); - - return 0; - } - - sub = bt_mesh_cdb_subnet_alloc(net_idx); - if (!sub) { - BT_ERR("No space to allocate a new subnet"); - return -ENOMEM; - } - - sub->kr_phase = key.kr_phase; - memcpy(sub->keys[0].net_key, &key.val[0], 16); - memcpy(sub->keys[1].net_key, &key.val[1], 16); - - BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx); - - return 0; -} - -static int cdb_app_key_set(int argc, char *name) -{ - struct bt_mesh_cdb_app_key *app; - struct app_key_val key; - uint16_t app_idx; - int len_rd, err; - - app_idx = strtol(name, NULL, 16); - len_rd = sizeof(key); - - if (len_rd == 0) { - BT_DBG("val (null)"); - BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx); - - app = bt_mesh_cdb_app_key_get(app_idx); - if (app) { - bt_mesh_cdb_app_key_del(app, false); - } - - return 0; - } - - err = settings_bytes_from_str(name, &key, &len_rd); - if (err) { - BT_ERR("Failed to set \'app-key\'"); - return err; - } - - app = bt_mesh_cdb_app_key_get(app_idx); - if (!app) { - app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx); - } - - if (!app) { - BT_ERR("No space for a new app key"); - return -ENOMEM; - } - - memcpy(app->keys[0].app_key, key.val[0], 16); - memcpy(app->keys[1].app_key, key.val[1], 16); - - BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx); - - return 0; -} - -static int cdb_set(int argc, char **argv, char *name) -{ - int len; - char *next; - - if (argc < 1) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; - } - - if (!strcmp(name, "Net")) { - return cdb_net_set(1, name); - } - - - len = settings_name_next(name, &next); - - if (!next) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; - } - - if (!strncmp(name, "Node", len)) { - return cdb_node_set(1, next); - } - - if (!strncmp(name, "Subnet", len)) { - return cdb_subnet_set(1, next); - } - - if (!strncmp(name, "AppKey", len)) { - return cdb_app_key_set(1, next); - } - - BT_WARN("Unknown module key %s", name); - return -ENOENT; -} -#endif - -const struct mesh_setting { - const char *name; - int (*func)(int argc, char **argv, char *val); -} settings[] = { - { "Net", net_set }, - { "IV", iv_set }, - { "Seq", seq_set }, - { "RPL", rpl_set }, - { "NetKey", net_key_set }, - { "AppKey", app_key_set }, - { "HBPub", hb_pub_set }, - { "Cfg", cfg_set }, - { "s", sig_mod_set }, - { "v", vnd_mod_set }, -#if CONFIG_BT_MESH_LABEL_COUNT > 0 - { "Va", va_set }, -#endif -#if MYNEWT_VAL(BLE_MESH_CDB) - { "cdb", cdb_set }, -#endif -}; - -static int mesh_set(int argc, char **argv, char *val) -{ - int i; - - if (argc < 1) { - BT_ERR("Insufficient number of arguments"); - return -EINVAL; - } - - BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); - - for (i = 0; i < ARRAY_SIZE(settings); i++) { - if (!strcmp(settings[i].name, argv[0])) { - argc--; - argv++; - - return settings[i].func(argc, argv, val); - } - } - - BT_WARN("No matching handler for key %s", argv[0]); - - return -ENOENT; -} - -static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, - bool vnd, bool primary, void *user_data) -{ - if (mod->pub && mod->pub->update && - mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) { - int32_t ms = bt_mesh_model_pub_period_get(mod); - if (ms) { - BT_DBG("Starting publish timer (period %u ms)", - (unsigned) ms); - k_delayed_work_submit(&mod->pub->timer, ms); - } - } - - if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - return; - } - - for (int i = 0; i < ARRAY_SIZE(mod->groups); i++) { - if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { - bt_mesh_lpn_group_add(mod->groups[i]); - } - } -} - -static int mesh_commit(void) -{ - if (!bt_mesh_subnet_next(NULL)) { - /* Nothing to do since we're not yet provisioned */ - return 0; - } - - if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - bt_mesh_proxy_prov_disable(true); - } - - if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) { - k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); - } - - bt_mesh_model_foreach(commit_mod, NULL); - - atomic_set_bit(bt_mesh.flags, BT_MESH_VALID); - - bt_mesh_start(); - - return 0; -} - -/* Pending flags that use K_NO_WAIT as the storage timeout */ -#define NO_WAIT_PENDING_BITS (BIT(BT_MESH_NET_PENDING) | \ - BIT(BT_MESH_IV_PENDING) | \ - BIT(BT_MESH_SEQ_PENDING)) - -/* Pending flags that use CONFIG_BT_MESH_STORE_TIMEOUT */ -#define GENERIC_PENDING_BITS (BIT(BT_MESH_KEYS_PENDING) | \ - BIT(BT_MESH_HB_PUB_PENDING) | \ - BIT(BT_MESH_CFG_PENDING) | \ - BIT(BT_MESH_MOD_PENDING)) - -static void schedule_store(int flag) -{ - int32_t timeout, remaining; - - atomic_set_bit(bt_mesh.flags, flag); - - if (atomic_get(bt_mesh.flags) & NO_WAIT_PENDING_BITS) { - timeout = K_NO_WAIT; - } else if (atomic_test_bit(bt_mesh.flags, BT_MESH_RPL_PENDING) && - (!(atomic_get(bt_mesh.flags) & GENERIC_PENDING_BITS) || - (CONFIG_BT_MESH_RPL_STORE_TIMEOUT < - CONFIG_BT_MESH_STORE_TIMEOUT))) { - timeout = K_SECONDS(CONFIG_BT_MESH_RPL_STORE_TIMEOUT); - } else { - timeout = K_SECONDS(CONFIG_BT_MESH_STORE_TIMEOUT); - } - - remaining = k_delayed_work_remaining_get(&pending_store); - if (remaining && remaining < timeout) { - BT_DBG("Not rescheduling due to existing earlier deadline"); - return; - } - - BT_DBG("Waiting %d seconds", (int) (timeout / MSEC_PER_SEC)); - - k_delayed_work_submit(&pending_store, timeout); -} - -static void clear_iv(void) -{ - int err; - - err = settings_save_one("bt_mesh/IV", NULL); - if (err) { - BT_ERR("Failed to clear IV"); - } else { - BT_DBG("Cleared IV"); - } -} - -static void clear_net(void) -{ - int err; - - err = settings_save_one("bt_mesh/Net", NULL); - if (err) { - BT_ERR("Failed to clear Network"); - } else { - BT_DBG("Cleared Network"); - } -} - -static void store_pending_net(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct net_val))]; - struct net_val net; - char *str; - int err; - - BT_DBG("addr 0x%04x DevKey %s", bt_mesh_primary_addr(), - bt_hex(bt_mesh.dev_key, 16)); - - net.primary_addr = bt_mesh_primary_addr(); - memcpy(net.dev_key, bt_mesh.dev_key, 16); - - str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Network as value"); - return; - } - - BT_DBG("Saving Network as value %s", str); - err = settings_save_one("bt_mesh/Net", str); - if (err) { - BT_ERR("Failed to store Network"); - } else { - BT_DBG("Stored Network"); - } -} - -void bt_mesh_store_net(void) -{ - schedule_store(BT_MESH_NET_PENDING); -} - -static void store_pending_iv(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct iv_val))]; - struct iv_val iv; - char *str; - int err; - - iv.iv_index = bt_mesh.iv_index; - iv.iv_update = atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); - iv.iv_duration = bt_mesh.ivu_duration; - - str = settings_str_from_bytes(&iv, sizeof(iv), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode IV as value"); - return; - } - - BT_DBG("Saving IV as value %s", str); - err = settings_save_one("bt_mesh/IV", str); - if (err) { - BT_ERR("Failed to store IV"); - } else { - BT_DBG("Stored IV"); - } -} - -void bt_mesh_store_iv(bool only_duration) -{ - schedule_store(BT_MESH_IV_PENDING); - - if (!only_duration) { - /* Always update Seq whenever IV changes */ - schedule_store(BT_MESH_SEQ_PENDING); - } -} - -static void store_pending_seq(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct seq_val))]; - struct seq_val seq; - char *str; - int err; - - sys_put_le24(bt_mesh.seq, seq.val); - - str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Seq as value"); - return; - } - - BT_DBG("Saving Seq as value %s", str); - err = settings_save_one("bt_mesh/Seq", str); - if (err) { - BT_ERR("Failed to store Seq"); - } else { - BT_DBG("Stored Seq"); - } -} - -void bt_mesh_store_seq(void) -{ - if (CONFIG_BT_MESH_SEQ_STORE_RATE > 1 && - (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)) { - return; - } - - schedule_store(BT_MESH_SEQ_PENDING); -} - -static void store_rpl(struct bt_mesh_rpl *entry) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct rpl_val))]; - struct rpl_val rpl; - char path[18]; - char *str; - int err; - - BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src, - (unsigned) entry->seq, entry->old_iv); - - rpl.seq = entry->seq; - rpl.old_iv = entry->old_iv; - - str = settings_str_from_bytes(&rpl, sizeof(rpl), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode RPL as value"); - return; - } - - snprintk(path, sizeof(path), "bt_mesh/RPL/%x", entry->src); - - BT_DBG("Saving RPL %s as value %s", path, str); - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store RPL"); - } else { - BT_DBG("Stored RPL"); - } -} - -static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data) -{ - int err; - char path[18]; - - if (!rpl->src) { - return; - } - - snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear RPL"); - } else { - BT_DBG("Cleared RPL"); - } - - (void)memset(rpl, 0, sizeof(*rpl)); -} - -static void store_pending_rpl(struct bt_mesh_rpl *rpl, void *user_data) -{ - BT_DBG(""); - - if (rpl->store) { - rpl->store = false; - store_rpl(rpl); - } -} - -static void store_pending_hb_pub(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct hb_pub_val))]; - struct bt_mesh_hb_pub pub; - struct hb_pub_val val; - char *str; - int err; - - bt_mesh_hb_pub_get(&pub); - if (pub.dst == BT_MESH_ADDR_UNASSIGNED) { - str = NULL; - } else { - val.indefinite = (pub.count == 0xffff); - val.dst = pub.dst; - val.period = bt_mesh_hb_log(pub.period); - val.ttl = pub.ttl; - val.feat = pub.feat; - val.net_idx = pub.net_idx; - - str = settings_str_from_bytes(&val, sizeof(val), - buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode hb pub as value"); - return; - } - } - - BT_DBG("Saving Heartbeat Publication as value %s", - str ? str : "(null)"); - err = settings_save_one("bt_mesh/HBPub", str); - if (err) { - BT_ERR("Failed to store Heartbeat Publication"); - } else { - BT_DBG("Stored Heartbeat Publication"); - } -} - -static void store_pending_cfg(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct cfg_val))]; - struct cfg_val val; - char *str; - int err; - - val.net_transmit = bt_mesh_net_transmit_get(); - val.relay = bt_mesh_relay_get(); - val.relay_retransmit = bt_mesh_relay_retransmit_get(); - val.beacon = bt_mesh_beacon_enabled(); - val.gatt_proxy = bt_mesh_gatt_proxy_get(); - val.frnd = bt_mesh_friend_get(); - val.default_ttl = bt_mesh_default_ttl_get(); - - str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode configuration as value"); - return; - } - - BT_DBG("Saving configuration as value %s", str); - err = settings_save_one("bt_mesh/Cfg", str); - if (err) { - BT_ERR("Failed to store configuration"); - } else { - BT_DBG("Stored configuration"); - } -} - -static void clear_cfg(void) -{ - int err; - - err = settings_save_one("bt_mesh/Cfg", NULL); - if (err) { - BT_ERR("Failed to clear configuration"); - } else { - BT_DBG("Cleared configuration"); - } -} - -static void clear_app_key(uint16_t app_idx) -{ - char path[20]; - int err; - - BT_DBG("AppKeyIndex 0x%03x", app_idx); - - snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx); - } else { - BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx); - } -} - -static void clear_net_key(uint16_t net_idx) -{ - char path[20]; - int err; - - BT_DBG("NetKeyIndex 0x%03x", net_idx); - - snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", net_idx); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx); - } else { - BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx); - } -} - -static void store_subnet(uint16_t net_idx) -{ - const struct bt_mesh_subnet *sub; - struct net_key_val key; - char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; - char path[20]; - char *str; - int err; - - sub = bt_mesh_subnet_get(net_idx); - if (!sub) { - BT_WARN("NetKeyIndex 0x%03x not found", net_idx); - return; - } - - BT_DBG("NetKeyIndex 0x%03x", net_idx); - - snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", net_idx); - - memcpy(&key.val[0], sub->keys[0].net, 16); - memcpy(&key.val[1], sub->keys[1].net, 16); - key.kr_flag = 0U; /* Deprecated */ - key.kr_phase = sub->kr_phase; - - str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode AppKey as value"); - return; - } - - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store NetKey"); - } else { - BT_DBG("Stored NetKey"); - } -} - -static void store_app(uint16_t app_idx) -{ - const struct bt_mesh_app_key *app; - char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; - struct app_key_val key; - char path[20]; - char *str; - int err; - - snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx); - - app = bt_mesh_app_key_get(app_idx); - if (!app) { - BT_WARN("ApKeyIndex 0x%03x not found", app_idx); - return; - } - - key.net_idx = app->net_idx, - key.updated = app->updated, - - memcpy(key.val[0], app->keys[0].val, 16); - memcpy(key.val[1], app->keys[1].val, 16); - - str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode AppKey as value"); - return; - } - - snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app->app_idx); - - BT_DBG("Saving AppKey %s as value %s", path, str); - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store AppKey"); - } else { - BT_DBG("Stored AppKey"); - } -} - -static void store_pending_keys(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(key_updates); i++) { - struct key_update *update = &key_updates[i]; - - if (!update->valid) { - continue; - } - - if (update->clear) { - if (update->app_key) { - clear_app_key(update->key_idx); - } else { - clear_net_key(update->key_idx); - } - } else { - store_subnet(update->key_idx); - } - - update->valid = 0; - } -} - -#if MYNEWT_VAL(BLE_MESH_CDB) -static void clear_cdb(void) -{ - int err; - - err = settings_save_one("bt/mesh/cdb/Net", NULL); - if (err) { - BT_ERR("Failed to clear Network"); - } else { - BT_DBG("Cleared Network"); - } -} - -static void store_pending_cdb(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct cdb_net_val))]; - struct cdb_net_val net; - int err; - char *str; - - BT_DBG(""); - - net.iv_index = bt_mesh_cdb.iv_index; - net.iv_update = atomic_test_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_IVU_IN_PROGRESS); - - str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Network as value"); - return; - } - err = settings_save_one("bt/mesh/cdb/Net", str); - if (err) { - BT_ERR("Failed to store Network value"); - } else { - BT_DBG("Stored Network value"); - } -} - -static void store_cdb_node(const struct bt_mesh_cdb_node *node) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct node_val))]; - struct node_val val; - char path[30]; - char *str; - int err; - - val.net_idx = node->net_idx; - val.num_elem = node->num_elem; - val.flags = 0; - - if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) { - val.flags |= F_NODE_CONFIGURED; - } - - memcpy(val.uuid, node->uuid, 16); - memcpy(val.dev_key, node->dev_key, 16); - - snprintk(path, sizeof(path), "bt_mesh/cdb/Node/%x", node->addr); - - str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Node as value"); - return; - } - - - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store Node %s value", path); - } else { - BT_DBG("Stored Node %s value", path); - } -} - -static void clear_cdb_node(uint16_t addr) -{ - char path[30]; - int err; - - BT_DBG("Node 0x%04x", addr); - - snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", addr); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear Node 0x%04x", addr); - } else { - BT_DBG("Cleared Node 0x%04x", addr); - } -} - -static void store_pending_cdb_nodes(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) { - struct node_update *update = &cdb_node_updates[i]; - - if (update->addr == BT_MESH_ADDR_UNASSIGNED) { - continue; - } - - BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear); - - if (update->clear) { - clear_cdb_node(update->addr); - } else { - struct bt_mesh_cdb_node *node; - - node = bt_mesh_cdb_node_get(update->addr); - if (node) { - store_cdb_node(node); - } else { - BT_WARN("Node 0x%04x not found", update->addr); - } - } - - update->addr = BT_MESH_ADDR_UNASSIGNED; - } -} - -static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))]; - struct net_key_val key; - char path[30]; - int err; - char *str; - - BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx, - bt_hex(sub->keys[0].net_key, 16)); - - memcpy(&key.val[0], sub->keys[0].net_key, 16); - memcpy(&key.val[1], sub->keys[1].net_key, 16); - key.kr_flag = 0U; /* Deprecated */ - key.kr_phase = sub->kr_phase; - - snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx); - - - str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Subnet as value"); - return; - } - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store Subnet value"); - } else { - BT_DBG("Stored Subnet value"); - } -} - -static void clear_cdb_subnet(uint16_t net_idx) -{ - char path[30]; - int err; - - BT_DBG("NetKeyIndex 0x%03x", net_idx); - - snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", net_idx); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx); - } else { - BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx); - } -} - -static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; - struct app_key_val key; - char path[30]; - int err; - char *str; - - key.net_idx = app->net_idx; - key.updated = false; - memcpy(key.val[0], app->keys[0].app_key, 16); - memcpy(key.val[1], app->keys[1].app_key, 16); - - snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app->app_idx); - - str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store AppKey"); - } else { - BT_DBG("Stored AppKey"); - } -} - -static void clear_cdb_app_key(uint16_t app_idx) -{ - char path[30]; - int err; - - snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app_idx); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx); - } else { - BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx); - } -} - -static void store_pending_cdb_keys(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) { - struct key_update *update = &cdb_key_updates[i]; - - if (!update->valid) { - continue; - } - - if (update->clear) { - if (update->app_key) { - clear_cdb_app_key(update->key_idx); - } else { - clear_cdb_subnet(update->key_idx); - } - } else { - if (update->app_key) { - struct bt_mesh_cdb_app_key *key; - - key = bt_mesh_cdb_app_key_get(update->key_idx); - if (key) { - store_cdb_app_key(key); - } else { - BT_WARN("AppKeyIndex 0x%03x not found", - update->key_idx); - } - } else { - struct bt_mesh_cdb_subnet *sub; - - sub = bt_mesh_cdb_subnet_get(update->key_idx); - if (sub) { - store_cdb_subnet(sub); - } else { - BT_WARN("NetKeyIndex 0x%03x not found", - update->key_idx); - } - } - } - - update->valid = 0U; - } -} - -static struct node_update *cdb_node_update_find(uint16_t addr, - struct node_update **free_slot) -{ - struct node_update *match; - int i; - - match = NULL; - *free_slot = NULL; - - for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) { - struct node_update *update = &cdb_node_updates[i]; - - if (update->addr == BT_MESH_ADDR_UNASSIGNED) { - *free_slot = update; - continue; - } - - if (update->addr == addr) { - match = update; - } - } - - return match; -} -#endif - -static void encode_mod_path(struct bt_mesh_model *mod, bool vnd, - const char *key, char *path, size_t path_len) -{ - uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx); - - if (vnd) { - snprintk(path, path_len, "bt_mesh/v/%x/%s", mod_key, key); - } else { - snprintk(path, path_len, "bt_mesh/s/%x/%s", mod_key, key); - } -} - -static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd) -{ - uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT]; - char buf[BT_SETTINGS_SIZE(sizeof(keys))]; - char path[20]; - int i, count, err; - char *val; - - for (i = 0, count = 0; i < ARRAY_SIZE(mod->keys); i++) { - if (mod->keys[i] != BT_MESH_KEY_UNUSED) { - keys[count++] = mod->keys[i]; - } - } - - if (count) { - val = settings_str_from_bytes(keys, count * sizeof(keys[0]), - buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model bindings as value"); - return; - } - } else { - val = NULL; - } - - encode_mod_path(mod, vnd, "bind", path, sizeof(path)); - - BT_DBG("Saving %s as %s", path, val ? val : "(null)"); - err = settings_save_one(path, val); - if (err) { - BT_ERR("Failed to store bind"); - } else { - BT_DBG("Stored bind"); - } -} - -static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd) -{ - uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT]; - char buf[BT_SETTINGS_SIZE(sizeof(groups))]; - char path[20]; - int i, count, err; - char *val; - - for (i = 0, count = 0; i < CONFIG_BT_MESH_MODEL_GROUP_COUNT; i++) { - if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { - groups[count++] = mod->groups[i]; - } - } - - if (count) { - val = settings_str_from_bytes(groups, count * sizeof(groups[0]), - buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model subscription as value"); - return; - } - } else { - val = NULL; - } - - encode_mod_path(mod, vnd, "sub", path, sizeof(path)); - - BT_DBG("Saving %s as %s", path, val ? val : "(null)"); - err = settings_save_one(path, val); - if (err) { - BT_ERR("Failed to store sub"); - } else { - BT_DBG("Stored sub"); - } -} - -static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))]; - struct mod_pub_val pub; - char path[20]; - char *val; - int err; - - if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - val = NULL; - } else { - pub.addr = mod->pub->addr; - pub.key = mod->pub->key; - pub.ttl = mod->pub->ttl; - pub.retransmit = mod->pub->retransmit; - pub.period = mod->pub->period; - pub.period_div = mod->pub->period_div; - pub.cred = mod->pub->cred; - - val = settings_str_from_bytes(&pub, sizeof(pub), - buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model publication as value"); - return; - } - } - - encode_mod_path(mod, vnd, "pub", path, sizeof(path)); - - BT_DBG("Saving %s as %s", path, val ? val : "(null)"); - err = settings_save_one(path, val); - if (err) { - BT_ERR("Failed to store pub"); - } else { - BT_DBG("Stored pub"); - } -} - -static void store_pending_mod(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, bool vnd, - bool primary, void *user_data) -{ - if (!mod->flags) { - return; - } - - if (mod->flags & BT_MESH_MOD_BIND_PENDING) { - mod->flags &= ~BT_MESH_MOD_BIND_PENDING; - store_pending_mod_bind(mod, vnd); - } - - if (mod->flags & BT_MESH_MOD_SUB_PENDING) { - mod->flags &= ~BT_MESH_MOD_SUB_PENDING; - store_pending_mod_sub(mod, vnd); - } - - if (mod->flags & BT_MESH_MOD_PUB_PENDING) { - mod->flags &= ~BT_MESH_MOD_PUB_PENDING; - store_pending_mod_pub(mod, vnd); - } -} - -#define IS_VA_DEL(_label) ((_label)->ref == 0) -static void store_pending_va(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct va_val))]; - struct bt_mesh_va *lab; - struct va_val va; - char path[18]; - char *val; - uint16_t i; - int err = 0; - - for (i = 0; (lab = bt_mesh_va_get(i)) != NULL; i++) { - if (!lab->changed) { - continue; - } - - lab->changed = 0U; - - snprintk(path, sizeof(path), "bt_mesh/Va/%x", i); - - if (IS_VA_DEL(lab)) { - val = NULL; - } else { - va.ref = lab->ref; - va.addr = lab->addr; - memcpy(va.uuid, lab->uuid, 16); - - val = settings_str_from_bytes(&va, sizeof(va), - buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model publication as value"); - return; - } - - err = settings_save_one(path, val); - } - - if (err) { - BT_ERR("Failed to %s %s value (err %d)", - IS_VA_DEL(lab) ? "delete" : "store", path, err); - } else { - BT_DBG("%s %s value", - IS_VA_DEL(lab) ? "Deleted" : "Stored", path); - } - } -} - -static void store_pending(struct ble_npl_event *work) -{ - BT_DBG(""); - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) { - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - bt_mesh_rpl_foreach(store_pending_rpl, NULL); - } else { - bt_mesh_rpl_foreach(clear_rpl, NULL); - } - } - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_KEYS_PENDING)) { - store_pending_keys(); - } - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NET_PENDING)) { - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - store_pending_net(); - } else { - clear_net(); - } - } - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_IV_PENDING)) { - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - store_pending_iv(); - } else { - clear_iv(); - } - } - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_SEQ_PENDING)) { - store_pending_seq(); - } - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_HB_PUB_PENDING)) { - store_pending_hb_pub(); - } - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_CFG_PENDING)) { - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - store_pending_cfg(); - } else { - clear_cfg(); - } - } - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_MOD_PENDING)) { - bt_mesh_model_foreach(store_pending_mod, NULL); - } - - if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_VA_PENDING)) { - store_pending_va(); - } - -#if MYNEWT_VAL(BLE_MESH_CDB) - if (IS_ENABLED(CONFIG_BT_MESH_CDB)) { - if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_SUBNET_PENDING)) { - if (atomic_test_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_VALID)) { - store_pending_cdb(); - } else { - clear_cdb(); - } - } - - if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_NODES_PENDING)) { - store_pending_cdb_nodes(); - } - - if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_KEYS_PENDING)) { - store_pending_cdb_keys(); - } - } -#endif -} - -void bt_mesh_store_rpl(struct bt_mesh_rpl *entry) -{ - entry->store = true; - schedule_store(BT_MESH_RPL_PENDING); -} - -static struct key_update *key_update_find(bool app_key, uint16_t key_idx, - struct key_update **free_slot) -{ - struct key_update *match; - int i; - - match = NULL; - *free_slot = NULL; - - for (i = 0; i < ARRAY_SIZE(key_updates); i++) { - struct key_update *update = &key_updates[i]; - - if (!update->valid) { - *free_slot = update; - continue; - } - - if (update->app_key != app_key) { - continue; - } - - if (update->key_idx == key_idx) { - match = update; - } - } - - return match; -} - -void bt_mesh_store_subnet(uint16_t net_idx) -{ - struct key_update *update, *free_slot; - - BT_DBG("NetKeyIndex 0x%03x", net_idx); - - update = key_update_find(false, net_idx, &free_slot); - if (update) { - update->clear = 0; - schedule_store(BT_MESH_KEYS_PENDING); - return; - } - - if (!free_slot) { - store_subnet(net_idx); - return; - } - - free_slot->valid = 1; - free_slot->key_idx = net_idx; - free_slot->app_key = 0; - free_slot->clear = 0; - - schedule_store(BT_MESH_KEYS_PENDING); -} - -void bt_mesh_store_app_key(uint16_t app_idx) -{ - struct key_update *update, *free_slot; - - BT_DBG("AppKeyIndex 0x%03x", app_idx); - - update = key_update_find(true, app_idx, &free_slot); - if (update) { - update->clear = 0; - schedule_store(BT_MESH_KEYS_PENDING); - return; - } - - if (!free_slot) { - store_app(app_idx); - return; - } - - free_slot->valid = 1; - free_slot->key_idx = app_idx; - free_slot->app_key = 1; - free_slot->clear = 0; - - schedule_store(BT_MESH_KEYS_PENDING); -} - -void bt_mesh_store_hb_pub(void) -{ - schedule_store(BT_MESH_HB_PUB_PENDING); -} - -void bt_mesh_store_cfg(void) -{ - schedule_store(BT_MESH_CFG_PENDING); -} - -void bt_mesh_clear_net(void) -{ - schedule_store(BT_MESH_NET_PENDING); - schedule_store(BT_MESH_IV_PENDING); - schedule_store(BT_MESH_CFG_PENDING); -} - -void bt_mesh_clear_subnet(uint16_t net_idx) -{ - struct key_update *update, *free_slot; - - BT_DBG("NetKeyIndex 0x%03x", net_idx); - - update = key_update_find(false, net_idx, &free_slot); - if (update) { - update->clear = 1; - schedule_store(BT_MESH_KEYS_PENDING); - return; - } - - if (!free_slot) { - clear_net_key(net_idx); - return; - } - - free_slot->valid = 1; - free_slot->key_idx = net_idx; - free_slot->app_key = 0; - free_slot->clear = 1; - - schedule_store(BT_MESH_KEYS_PENDING); -} - -void bt_mesh_clear_app_key(uint16_t app_idx) -{ - struct key_update *update, *free_slot; - - BT_DBG("AppKeyIndex 0x%03x", app_idx); - - update = key_update_find(true, app_idx, &free_slot); - if (update) { - update->clear = 1; - schedule_store(BT_MESH_KEYS_PENDING); - return; - } - - if (!free_slot) { - clear_app_key(app_idx); - return; - } - - free_slot->valid = 1; - free_slot->key_idx = app_idx; - free_slot->app_key = 1; - free_slot->clear = 1; - - schedule_store(BT_MESH_KEYS_PENDING); -} - -void bt_mesh_clear_rpl(void) -{ - schedule_store(BT_MESH_RPL_PENDING); -} - -void bt_mesh_store_mod_bind(struct bt_mesh_model *mod) -{ - mod->flags |= BT_MESH_MOD_BIND_PENDING; - schedule_store(BT_MESH_MOD_PENDING); -} - -void bt_mesh_store_mod_sub(struct bt_mesh_model *mod) -{ - mod->flags |= BT_MESH_MOD_SUB_PENDING; - schedule_store(BT_MESH_MOD_PENDING); -} - -void bt_mesh_store_mod_pub(struct bt_mesh_model *mod) -{ - mod->flags |= BT_MESH_MOD_PUB_PENDING; - schedule_store(BT_MESH_MOD_PENDING); -} - - -void bt_mesh_store_label(void) -{ - schedule_store(BT_MESH_VA_PENDING); -} - -#if MYNEWT_VAL(BLE_MESH_CDB) -static void schedule_cdb_store(int flag) -{ - atomic_set_bit(bt_mesh_cdb.flags, flag); - k_delayed_work_submit(&pending_store, K_NO_WAIT); -} - -void bt_mesh_store_cdb(void) -{ - schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING); -} - -void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node) -{ - struct node_update *update, *free_slot; - - BT_DBG("Node 0x%04x", node->addr); - - update = cdb_node_update_find(node->addr, &free_slot); - if (update) { - update->clear = false; - schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); - return; - } - - if (!free_slot) { - store_cdb_node(node); - return; - } - - free_slot->addr = node->addr; - free_slot->clear = false; - - schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); -} - -void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node) -{ - struct node_update *update, *free_slot; - - BT_DBG("Node 0x%04x", node->addr); - - update = cdb_node_update_find(node->addr, &free_slot); - if (update) { - update->clear = true; - schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); - return; - } - - if (!free_slot) { - clear_cdb_node(node->addr); - return; - } - - free_slot->addr = node->addr; - free_slot->clear = true; - - schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); -} - -/* TODO: Could be shared with key_update_find? */ -static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx, - struct key_update **free_slot) -{ - struct key_update *match; - int i; - - match = NULL; - *free_slot = NULL; - - for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) { - struct key_update *update = &cdb_key_updates[i]; - - if (!update->valid) { - *free_slot = update; - continue; - } - - if (update->app_key != app_key) { - continue; - } - - if (update->key_idx == key_idx) { - match = update; - } - } - - return match; -} - -void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) -{ - struct key_update *update, *free_slot; - - BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); - - update = cdb_key_update_find(false, sub->net_idx, &free_slot); - if (update) { - update->clear = 0U; - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); - return; - } - - if (!free_slot) { - store_cdb_subnet(sub); - return; - } - - free_slot->valid = 1U; - free_slot->key_idx = sub->net_idx; - free_slot->app_key = 0U; - free_slot->clear = 0U; - - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); -} - -void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub) -{ - struct key_update *update, *free_slot; - - BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); - - update = cdb_key_update_find(false, sub->net_idx, &free_slot); - if (update) { - update->clear = 1U; - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); - return; - } - - if (!free_slot) { - clear_cdb_subnet(sub->net_idx); - return; - } - - free_slot->valid = 1U; - free_slot->key_idx = sub->net_idx; - free_slot->app_key = 0U; - free_slot->clear = 1U; - - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); -} - -void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *key) -{ - struct key_update *update, *free_slot; - - BT_DBG("AppKeyIndex 0x%03x", key->app_idx); - - update = cdb_key_update_find(true, key->app_idx, &free_slot); - if (update) { - update->clear = 0U; - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); - return; - } - - if (!free_slot) { - store_cdb_app_key(key); - return; - } - - free_slot->valid = 1U; - free_slot->key_idx = key->app_idx; - free_slot->app_key = 1U; - free_slot->clear = 0U; - - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); -} - -void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *key) -{ - struct key_update *update, *free_slot; - - BT_DBG("AppKeyIndex 0x%03x", key->app_idx); - - update = cdb_key_update_find(true, key->app_idx, &free_slot); - if (update) { - update->clear = 1U; - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); - return; - } - - if (!free_slot) { - clear_cdb_app_key(key->app_idx); - return; - } - - free_slot->valid = 1U; - free_slot->key_idx = key->app_idx; - free_slot->app_key = 1U; - free_slot->clear = 1U; - - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); -} -#endif - -int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, - const char *name, const void *data, - size_t data_len) -{ - char path[30]; - char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))]; - char *val; - int err; - - encode_mod_path(mod, vnd, "data", path, sizeof(path)); - if (name) { - strcat(path, "/"); - strncat(path, name, 8); - } - - if (data_len) { - val = settings_str_from_bytes(data, data_len, - buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model publication as value"); - return -EINVAL; - } - err = settings_save_one(path, val); - } else { - err = settings_save_one(path, NULL); - } - - if (err) { - BT_ERR("Failed to store %s value", path); - } else { - BT_DBG("Stored %s value", path); - } - return err; } static struct conf_handler bt_mesh_settings_conf_handler = { .ch_name = "bt_mesh", .ch_get = NULL, - .ch_set = mesh_set, + .ch_set = NULL, .ch_commit = mesh_commit, .ch_export = NULL, }; diff --git a/nimble/host/mesh/src/settings.h b/nimble/host/mesh/src/settings.h index 9060a14a72..95f78f50ff 100644 --- a/nimble/host/mesh/src/settings.h +++ b/nimble/host/mesh/src/settings.h @@ -3,30 +3,23 @@ * * SPDX-License-Identifier: Apache-2.0 */ +/* Pending storage actions. */ +enum bt_mesh_settings_flag { + BT_MESH_SETTINGS_RPL_PENDING, + BT_MESH_SETTINGS_NET_KEYS_PENDING, + BT_MESH_SETTINGS_APP_KEYS_PENDING, + BT_MESH_SETTINGS_NET_PENDING, + BT_MESH_SETTINGS_IV_PENDING, + BT_MESH_SETTINGS_SEQ_PENDING, + BT_MESH_SETTINGS_HB_PUB_PENDING, + BT_MESH_SETTINGS_CFG_PENDING, + BT_MESH_SETTINGS_MOD_PENDING, + BT_MESH_SETTINGS_VA_PENDING, + BT_MESH_SETTINGS_CDB_PENDING, -void bt_mesh_store_net(void); -void bt_mesh_store_iv(bool only_duration); -void bt_mesh_store_seq(void); -void bt_mesh_store_rpl(struct bt_mesh_rpl *rpl); -void bt_mesh_store_subnet(uint16_t net_idx); -void bt_mesh_store_app_key(uint16_t app_idx); -void bt_mesh_store_hb_pub(void); -void bt_mesh_store_cfg(void); -void bt_mesh_store_mod_bind(struct bt_mesh_model *mod); -void bt_mesh_store_mod_sub(struct bt_mesh_model *mod); -void bt_mesh_store_mod_pub(struct bt_mesh_model *mod); -void bt_mesh_store_label(void); -void bt_mesh_store_cdb(void); -void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node); -void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub); -void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *app); - -void bt_mesh_clear_net(void); -void bt_mesh_clear_subnet(uint16_t net_idx); -void bt_mesh_clear_app_key(uint16_t app_idx); -void bt_mesh_clear_rpl(void); -void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node); -void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub); -void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *app); + BT_MESH_SETTINGS_FLAG_COUNT, +}; void bt_mesh_settings_init(void); +int settings_name_next(char *name, char **next); +void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag); diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index 0a27e274e7..99c4f95b2c 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -2906,7 +2906,7 @@ static int cmd_cdb_node_add(int argc, char *argv[]) memcpy(node->dev_key, dev_key, 16); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cdb_node(node); + bt_mesh_cdb_node_store(node); } printk("Added node 0x%04x", addr); @@ -2960,7 +2960,7 @@ static int cmd_cdb_subnet_add(int argc, memcpy(sub->keys[0].net_key, net_key, 16); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cdb_subnet(sub); + bt_mesh_cdb_subnet_store(sub); } printk("Added Subnet 0x%03x", net_idx); @@ -3016,7 +3016,7 @@ static int cmd_cdb_app_key_add(int argc, memcpy(key->keys[0].app_key, app_key, 16); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cdb_app_key(key); + bt_mesh_cdb_app_key_store(key); } printk("Added AppKey 0x%03x", app_idx); diff --git a/nimble/host/mesh/src/subnet.c b/nimble/host/mesh/src/subnet.c index d6fcfbeee7..71d7b3d1ab 100644 --- a/nimble/host/mesh/src/subnet.c +++ b/nimble/host/mesh/src/subnet.c @@ -4,7 +4,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ - +#include #include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_NET_KEYS_LOG @@ -26,6 +26,26 @@ #include "settings.h" #include "prov.h" +/* Tracking of what storage changes are pending for Net Keys. We track this in + * a separate array here instead of within the respective bt_mesh_subnet + * struct itselve, since once a key gets deleted its struct becomes invalid + * and may be reused for other keys. + */ +struct net_key_update { + uint16_t key_idx:12, /* NetKey Index */ + valid:1, /* 1 if this entry is valid, 0 if not */ + clear:1; /* 1 if key needs clearing, 0 if storing */ +}; + +/* NetKey storage information */ +struct net_key_val { + uint8_t kr_flag:1, + kr_phase:7; + uint8_t val[2][16]; +} __packed; + +static struct net_key_update net_key_updates[CONFIG_BT_MESH_SUBNET_COUNT]; + #ifdef CONFIG_BT_MESH_GATT_PROXY void (*bt_mesh_subnet_cb_list[5]) (struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt); @@ -51,6 +71,85 @@ static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) } } +static void clear_net_key(uint16_t net_idx) +{ + char path[20]; + int err; + + BT_DBG("NetKeyIndex 0x%03x", net_idx); + + snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", net_idx); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx); + } else { + BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx); + } +} + +static void store_subnet(uint16_t net_idx) +{ + const struct bt_mesh_subnet *sub; + struct net_key_val key; + char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))]; + char path[20]; + char *str; + int err; + + sub = bt_mesh_subnet_get(net_idx); + if (!sub) { + BT_WARN("NetKeyIndex 0x%03x not found", net_idx); + return; + } + + BT_DBG("NetKeyIndex 0x%03x", net_idx); + + snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", net_idx); + + memcpy(&key.val[0], sub->keys[0].net, 16); + memcpy(&key.val[1], sub->keys[1].net, 16); + key.kr_flag = 0U; /* Deprecated */ + key.kr_phase = sub->kr_phase; + + str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode AppKey as value"); + return; + } + + err = settings_save_one(path, str); + if (err) { + BT_ERR("Failed to store NetKey"); + } else { + BT_DBG("Stored NetKey"); + } +} + +static struct net_key_update *net_key_update_find(uint16_t key_idx, + struct net_key_update **free_slot) +{ + struct net_key_update *match; + int i; + + match = NULL; + *free_slot = NULL; + + for (i = 0; i < ARRAY_SIZE(net_key_updates); i++) { + struct net_key_update *update = &net_key_updates[i]; + + if (!update->valid) { + *free_slot = update; + continue; + } + + if (update->key_idx == key_idx) { + match = update; + } + } + + return match; +} + uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub) { uint8_t flags = 0x00; @@ -66,6 +165,42 @@ uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub) return flags; } +static void update_subnet_settings(uint16_t net_idx, bool store) +{ + struct net_key_update *update, *free_slot; + uint8_t clear = store ? 0U : 1U; + + BT_DBG("NetKeyIndex 0x%03x", net_idx); + + update = net_key_update_find(net_idx, &free_slot); + if (update) { + update->clear = clear; + bt_mesh_settings_store_schedule( + BT_MESH_SETTINGS_NET_KEYS_PENDING); + return; + } + + if (!free_slot) { + if (store) { + store_subnet(net_idx); + } else { + clear_net_key(net_idx); + } + return; + } + + free_slot->valid = 1U; + free_slot->key_idx = net_idx; + free_slot->clear = clear; + + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_NET_KEYS_PENDING); +} + +void bt_mesh_subnet_store(uint16_t net_idx) +{ + update_subnet_settings(net_idx, true); +} + static void key_refresh(struct bt_mesh_subnet *sub, uint8_t new_phase) { BT_DBG("Phase 0x%02x -> 0x%02x", sub->kr_phase, new_phase); @@ -97,7 +232,7 @@ static void key_refresh(struct bt_mesh_subnet *sub, uint8_t new_phase) if (IS_ENABLED(CONFIG_BT_SETTINGS)) { BT_DBG("Storing Updated NetKey persistently"); - bt_mesh_store_subnet(sub->net_idx); + bt_mesh_subnet_store(sub->net_idx); } } @@ -139,7 +274,7 @@ static struct bt_mesh_subnet *subnet_alloc(uint16_t net_idx) static void subnet_del(struct bt_mesh_subnet *sub) { if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_clear_subnet(sub->net_idx); + update_subnet_settings(sub->net_idx, false); } bt_mesh_net_loopback_clear(sub->net_idx); @@ -242,7 +377,7 @@ uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16]) if (IS_ENABLED(CONFIG_BT_SETTINGS)) { BT_DBG("Storing NetKey persistently"); - bt_mesh_store_subnet(sub->net_idx); + bt_mesh_subnet_store(sub->net_idx); } return STATUS_SUCCESS; @@ -664,3 +799,71 @@ bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct os_mbuf *in, return false; } + +static int net_key_set(int argc, char **argv, char *val) +{ + struct net_key_val key; + int len, err; + uint16_t net_idx; + + BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); + + net_idx = strtol(argv[0], NULL, 16); + + len = sizeof(key); + err = settings_bytes_from_str(val, &key, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return err; + } + + if (len != sizeof(key)) { + BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(key)); + return -EINVAL; + } + + BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx); + + return bt_mesh_subnet_set( + net_idx, key.kr_phase, key.val[0], + (key.kr_phase != BT_MESH_KR_NORMAL) ? key.val[1] : NULL); +} + +void bt_mesh_subnet_pending_store(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(net_key_updates); i++) { + struct net_key_update *update = &net_key_updates[i]; + + if (!update->valid) { + continue; + } + + if (update->clear) { + clear_net_key(update->key_idx); + } else { + store_subnet(update->key_idx); + } + + update->valid = 0U; + } +} + +static struct conf_handler bt_mesh_net_key_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = net_key_set, + .ch_commit = NULL, + .ch_export = NULL, + }; + +void bt_mesh_net_key_init(void) +{ + int rc; + + rc = conf_register(&bt_mesh_net_key_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_net_key conf"); +} \ No newline at end of file diff --git a/nimble/host/mesh/src/subnet.h b/nimble/host/mesh/src/subnet.h index 7a82999789..b3ac899272 100644 --- a/nimble/host/mesh/src/subnet.h +++ b/nimble/host/mesh/src/subnet.h @@ -194,4 +194,13 @@ bt_mesh_subnet_has_new_key(const struct bt_mesh_subnet *sub) return sub->kr_phase != BT_MESH_KR_NORMAL; } +/** @brief Store the Subnet information in persistent storage. + * + * @param net_idx Network index to store. + */ +void bt_mesh_subnet_store(uint16_t net_idx); + +/** @brief Store the pending Subnets in persistent storage. */ +void bt_mesh_subnet_pending_store(void); +void bt_mesh_net_key_init(void); #endif /* _BLUETOOTH_MESH_SUBNET_H_ */ \ No newline at end of file diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 3582c998bf..721d5005b6 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -11,6 +11,7 @@ #include #include +#include #include "mesh/mesh.h" #include "mesh/glue.h" @@ -69,6 +70,20 @@ /* How long to wait for available buffers before giving up */ #define BUF_TIMEOUT K_NO_WAIT +struct virtual_addr { + uint16_t ref:15, + changed:1; + uint16_t addr; + uint8_t uuid[16]; +}; + +/* Virtual Address information for persistent storage. */ +struct va_val { + uint16_t ref; + uint16_t addr; + uint8_t uuid[16]; +} __packed; + static struct seg_tx { struct bt_mesh_subnet *sub; void *seg[CONFIG_BT_MESH_TX_SEG_MAX]; @@ -124,7 +139,7 @@ struct k_mem_slab segs = { .num_used = 0 }; -static struct bt_mesh_va virtual_addrs[CONFIG_BT_MESH_LABEL_COUNT]; +static struct virtual_addr virtual_addrs[CONFIG_BT_MESH_LABEL_COUNT]; static int send_unseg(struct bt_mesh_net_tx *tx, struct os_mbuf *sdu, const struct bt_mesh_send_cb *cb, void *cb_data, @@ -1584,6 +1599,11 @@ void bt_mesh_rx_reset(void) } } +static void store_va_label(void) +{ + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_VA_PENDING); +} + void bt_mesh_trans_reset(void) { int i; @@ -1606,7 +1626,7 @@ void bt_mesh_trans_reset(void) bt_mesh_rpl_clear(); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_label(); + store_va_label(); } } @@ -1634,26 +1654,17 @@ void bt_mesh_trans_init(void) } } -struct bt_mesh_va *bt_mesh_va_get(uint16_t index) -{ - if (index >= ARRAY_SIZE(virtual_addrs)) { - return NULL; - } - - return &virtual_addrs[index]; -} - -static inline void va_store(struct bt_mesh_va *store) +static inline void va_store(struct virtual_addr *store) { store->changed = 1U; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_label(); + store_va_label(); } } uint8_t bt_mesh_va_add(const uint8_t uuid[16], uint16_t *addr) { - struct bt_mesh_va *va = NULL; + struct virtual_addr *va = NULL; int err; for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) { @@ -1695,7 +1706,7 @@ uint8_t bt_mesh_va_add(const uint8_t uuid[16], uint16_t *addr) uint8_t bt_mesh_va_del(const uint8_t uuid[16], uint16_t *addr) { - struct bt_mesh_va *va = NULL; + struct virtual_addr *va = NULL; for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) { if (virtual_addrs[i].ref && @@ -1719,19 +1730,6 @@ uint8_t bt_mesh_va_del(const uint8_t uuid[16], uint16_t *addr) return STATUS_SUCCESS; } -struct bt_mesh_va *bt_mesh_va_find(uint8_t uuid[16]) -{ - for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) { - if (virtual_addrs[i].ref && - !memcmp(uuid, virtual_addrs[i].uuid, - ARRAY_SIZE(virtual_addrs[i].uuid))) { - return &virtual_addrs[i]; - } - } - - return NULL; -} - uint8_t *bt_mesh_va_label_get(uint16_t addr) { int i; @@ -1750,3 +1748,132 @@ uint8_t *bt_mesh_va_label_get(uint16_t addr) return NULL; } + +static struct virtual_addr *bt_mesh_va_get(uint16_t index) +{ + if (index >= ARRAY_SIZE(virtual_addrs)) { + return NULL; + } + + return &virtual_addrs[index]; +} + +#if CONFIG_BT_MESH_LABEL_COUNT > 0 +static int va_set(int argc, char **argv, char *val) +{ + struct va_val va; + struct virtual_addr *lab; + uint16_t index; + int len, err; + + if (argc < 1) { + BT_ERR("Insufficient number of arguments"); + return -ENOENT; + } + + index = strtol(argv[0], NULL, 16); + + if (val == NULL) { + BT_WARN("Mesh Virtual Address length = 0"); + return 0; + } + + err = settings_bytes_from_str(val, &va, &len); + if (err) { + BT_ERR("Failed to decode value %s (err %d)", val, err); + return -EINVAL; + } + + if (len != sizeof(struct va_val)) { + BT_ERR("Invalid length for virtual address"); + return -EINVAL; + } + + if (va.ref == 0) { + BT_WARN("Ignore Mesh Virtual Address ref = 0"); + return 0; + } + + lab = bt_mesh_va_get(index); + if (lab == NULL) { + BT_WARN("Out of labels buffers"); + return -ENOBUFS; + } + + memcpy(lab->uuid, va.uuid, 16); + lab->addr = va.addr; + lab->ref = va.ref; + + BT_DBG("Restored Virtual Address, addr 0x%04x ref 0x%04x", + lab->addr, lab->ref); + + return 0; +} +#endif + +#define IS_VA_DEL(_label) ((_label)->ref == 0) +void bt_mesh_va_pending_store(void) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct va_val))]; + struct virtual_addr *lab; + struct va_val va; + char path[18]; + char *val; + uint16_t i; + int err = 0; + + for (i = 0; (lab = bt_mesh_va_get(i)) != NULL; i++) { + if (!lab->changed) { + continue; + } + + lab->changed = 0U; + + snprintk(path, sizeof(path), "bt_mesh/Va/%x", i); + + if (IS_VA_DEL(lab)) { + val = NULL; + } else { + va.ref = lab->ref; + va.addr = lab->addr; + memcpy(va.uuid, lab->uuid, 16); + + val = settings_str_from_bytes(&va, sizeof(va), + buf, sizeof(buf)); + if (!val) { + BT_ERR("Unable to encode model publication as value"); + return; + } + + err = settings_save_one(path, val); + } + + if (err) { + BT_ERR("Failed to %s %s value (err %d)", + IS_VA_DEL(lab) ? "delete" : "store", path, err); + } else { + BT_DBG("%s %s value", + IS_VA_DEL(lab) ? "Deleted" : "Stored", path); + } + } +} + +#if CONFIG_BT_MESH_LABEL_COUNT > 0 +static struct conf_handler bt_mesh_va_conf_handler = { + .ch_name = "bt_mesh", + .ch_get = NULL, + .ch_set = va_set, + .ch_commit = NULL, + .ch_export = NULL, + }; + +void bt_mesh_va_init(void) +{ + int rc; + + rc = conf_register(&bt_mesh_va_conf_handler); + + SYSINIT_PANIC_ASSERT_MSG(rc == 0, + "Failed to register bt_mesh_hb_pub conf"); +} +#endif \ No newline at end of file diff --git a/nimble/host/mesh/src/transport.h b/nimble/host/mesh/src/transport.h index bf458e83c8..a1af9a4bd8 100644 --- a/nimble/host/mesh/src/transport.h +++ b/nimble/host/mesh/src/transport.h @@ -79,13 +79,6 @@ struct bt_mesh_ctl_friend_sub_confirm { uint8_t xact; }__attribute__((__packed__)); -struct bt_mesh_va { - uint16_t ref:15, - changed:1; - uint16_t addr; - uint8_t uuid[16]; -}; - bool bt_mesh_tx_in_progress(void); void bt_mesh_rx_reset(void); @@ -102,12 +95,12 @@ void bt_mesh_trans_init(void); void bt_mesh_trans_reset(void); -struct bt_mesh_va *bt_mesh_va_get(uint16_t index); - -struct bt_mesh_va *bt_mesh_va_find(uint8_t uuid[16]); - uint8_t bt_mesh_va_add(const uint8_t uuid[16], uint16_t *addr); uint8_t bt_mesh_va_del(const uint8_t uuid[16], uint16_t *addr); -uint8_t *bt_mesh_va_label_get(uint16_t addr); \ No newline at end of file +uint8_t *bt_mesh_va_label_get(uint16_t addr); + +void bt_mesh_va_pending_store(void); + +void bt_mesh_va_init(void); \ No newline at end of file diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index d110a3888a..99b18c2056 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -58,6 +58,7 @@ syscfg.defs: description: > Mesh Configuration Database [EXPERIMENTAL] value: 0 + restrictions: BLE_MESH_SETTINGS BLE_MESH_CDB_NODE_COUNT: description: > @@ -82,6 +83,12 @@ syscfg.defs: Use this option to enable configuration database debug logs. value: 1 + BLE_MESH_DEBUG_CFG: + description: + Use this option to enable node configuration debug logs for the + Bluetooth Mesh functionality. + value: 1 + BLE_MESH_PROXY: description: > Enable proxy. This is automatically set whenever BLE_MESH_PB_GATT or From 0fa50c3eddf1e7d7523ba996643a5c02fa90411b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 07:49:48 +0200 Subject: [PATCH 141/306] host/mesh: Fix mod app key get vnd pass cid instead of CID_NVAL in parameters of mod_member_list_get This is port of 3ff1eb618fd50ecb4328d0f832471caaec7be3ee --- nimble/host/mesh/src/cfg_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index 2df7d70271..f51e07c20e 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -1557,7 +1557,7 @@ int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_a } return mod_member_list_get(OP_VND_MOD_APP_GET, OP_VND_MOD_APP_LIST, - net_idx, addr, elem_addr, mod_id, CID_NVAL, + net_idx, addr, elem_addr, mod_id, cid, status, apps, app_cnt); } From 0c6d730e7aaf3b70c20ec98e47f22852d159c2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 07:52:58 +0200 Subject: [PATCH 142/306] host/mesh: Fix fix mod_sub_get_vnd pass cid instead of CID_NVAL in parameters of mod_member_list_get This is port of 942979b252a46602213656107d6b5b6a5e98615c --- nimble/host/mesh/src/cfg_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index f51e07c20e..6806818d8a 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -1808,7 +1808,7 @@ int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_a } return mod_member_list_get(OP_MOD_SUB_GET_VND, OP_MOD_SUB_LIST_VND, - net_idx, addr, elem_addr, mod_id, CID_NVAL, + net_idx, addr, elem_addr, mod_id, cid, status, subs, sub_cnt); } From 94b3c4a9d3d3d2f961c21048f8c90696e7823913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 07:59:16 +0200 Subject: [PATCH 143/306] host/mesh: Store network at the end of provisioning After #31176, the network would get stored immediately in bt_mesh_net_create, causing the address and devicekey to get stored as their zero-initialized version, as they're only being set in the bt_mesh_comp_provision call, which fires after. This is port of a281d10cff8d0e626fcc31897649f4312c794a4e --- nimble/host/mesh/src/mesh.c | 4 ++++ nimble/host/mesh/src/net.c | 6 ------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index b22dc1363f..2417872a95 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -134,6 +134,10 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, bt_mesh_lpn_group_add(BT_MESH_ADDR_ALL_NODES); } + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_net_pending_net_store(); + } + bt_mesh_start(); return 0; diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 76ef9eaef8..692989dd23 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -137,11 +137,6 @@ static void msg_cache_add(struct bt_mesh_net_rx *rx) msg_cache_next %= ARRAY_SIZE(msg_cache); } -static void store_net(void) -{ - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_NET_PENDING); -} - static void store_iv(bool only_duration) { bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_IV_PENDING); @@ -197,7 +192,6 @@ int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], if (IS_ENABLED(CONFIG_BT_SETTINGS)) { BT_DBG("Storing network information persistently"); - store_net(); bt_mesh_subnet_store(idx); store_iv(false); } From ea75a5e683da0f69aeeae926fcd4f7491a151d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 08:05:48 +0200 Subject: [PATCH 144/306] host/mesh: Update seqnum when re-encrypting for friend Sets the sequence number when re-encrypting messages from the friend to the lpn. This is port of 512444d863f0e4de69ea600dda37b11f032e9707 --- nimble/host/mesh/src/friend.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index ff34eda9c6..b544a7830a 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -431,6 +431,9 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, return 0; } + BT_DBG("Re-encrypting friend pdu (SeqNum %06x -> %06x)", + meta.crypto.seq_num, bt_mesh.seq); + err = unseg_app_sdu_unpack(frnd, buf, &meta); if (err) { return err; @@ -446,6 +449,8 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, BT_DBG("Re-encrypting friend pdu (SeqNum %06x -> %06x)", meta.crypto.seq_num, bt_mesh.seq); + meta.crypto.seq_num = bt_mesh.seq; + err = unseg_app_sdu_decrypt(frnd, buf, &meta); if (err) { BT_WARN("Decryption failed! %d", err); From 9a7d9f4a7f7f103b13fecb41466dcfbe8cc57cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 08:24:55 +0200 Subject: [PATCH 145/306] host/mesh: Only do label lookup when there are labels Include virtual label's pending_store function in the LABEL_COUNT > 0 compile guard to avoid including dead iteration code in the compilation. This is port of 7039675df13c74e74fb76d4f41cfc7e949c209ad --- nimble/host/mesh/src/transport.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 721d5005b6..0299c98331 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -1749,6 +1749,7 @@ uint8_t *bt_mesh_va_label_get(uint16_t addr) return NULL; } +#if CONFIG_BT_MESH_LABEL_COUNT > 0 static struct virtual_addr *bt_mesh_va_get(uint16_t index) { if (index >= ARRAY_SIZE(virtual_addrs)) { @@ -1758,7 +1759,6 @@ static struct virtual_addr *bt_mesh_va_get(uint16_t index) return &virtual_addrs[index]; } -#if CONFIG_BT_MESH_LABEL_COUNT > 0 static int va_set(int argc, char **argv, char *val) { struct va_val va; @@ -1809,7 +1809,6 @@ static int va_set(int argc, char **argv, char *val) return 0; } -#endif #define IS_VA_DEL(_label) ((_label)->ref == 0) void bt_mesh_va_pending_store(void) @@ -1857,8 +1856,13 @@ void bt_mesh_va_pending_store(void) } } } +#else +void bt_mesh_va_pending_store(void) +{ + /* Do nothing. */ +} +#endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */ -#if CONFIG_BT_MESH_LABEL_COUNT > 0 static struct conf_handler bt_mesh_va_conf_handler = { .ch_name = "bt_mesh", .ch_get = NULL, From 135dd1b42edd7e9cf4d9a4f994889a01868b0539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 08:33:16 +0200 Subject: [PATCH 146/306] Resolve dead code in store_seg If CONFIG_BT_MESH_SEQ_STORE_RATE is 1, the check in store_seq can be reduced to a simple if (false), and the modulo code does not need to be included in the build. This is port of aef354c6bc3264de9f2a38b8c56ff5253b35912a --- nimble/host/mesh/src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 692989dd23..b3e22aad30 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -149,7 +149,7 @@ static void store_iv(bool only_duration) static void store_seq(void) { - if (CONFIG_BT_MESH_SEQ_STORE_RATE && + if (CONFIG_BT_MESH_SEQ_STORE_RATE > 1 && (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)) { return; } From 097aa7f9a164613e63291243441df9955ed22954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 15:18:32 +0200 Subject: [PATCH 147/306] host/mesh: update k_work API Updated k_work API to new behaviour reflected in `glue`. This is port of: 81b9ba3a9b2dd4d5bd3f0966eac9f8f6dad983e6 17831b045f5869b0e57e26caa0441f263d1a5ae6 6a097caa22c769855aba552b50371bafe05ee6b4 5506727bde18bb9afcf4f1b969cd2cc09d7e65f8 --- apps/mesh_badge/src/reel_board.c | 24 ++++----- nimble/host/mesh/include/mesh/access.h | 2 +- nimble/host/mesh/include/mesh/glue.h | 16 +++--- nimble/host/mesh/include/mesh/health_srv.h | 2 +- nimble/host/mesh/src/access.c | 12 ++--- nimble/host/mesh/src/beacon.c | 20 ++++---- nimble/host/mesh/src/cfg_srv.c | 9 ++-- nimble/host/mesh/src/friend.c | 22 ++++---- nimble/host/mesh/src/glue.c | 36 +++++++++++--- nimble/host/mesh/src/health_srv.c | 22 +++----- nimble/host/mesh/src/heartbeat.c | 58 +++++++++++----------- nimble/host/mesh/src/lpn.c | 32 ++++++------ nimble/host/mesh/src/mesh.c | 6 +-- nimble/host/mesh/src/net.c | 8 +-- nimble/host/mesh/src/net.h | 8 +-- nimble/host/mesh/src/pb_adv.c | 20 ++++---- nimble/host/mesh/src/pb_gatt.c | 12 ++--- nimble/host/mesh/src/proxy.c | 14 +++--- nimble/host/mesh/src/settings.c | 25 ++++++---- nimble/host/mesh/src/transport.c | 46 ++++++++--------- 20 files changed, 207 insertions(+), 187 deletions(-) diff --git a/apps/mesh_badge/src/reel_board.c b/apps/mesh_badge/src/reel_board.c index bc8229377f..5e5f6b4088 100644 --- a/apps/mesh_badge/src/reel_board.c +++ b/apps/mesh_badge/src/reel_board.c @@ -49,8 +49,8 @@ struct font_info { static struct os_dev *epd_dev; static bool pressed; static bool stats_view; -static struct k_delayed_work epd_work; -static struct k_delayed_work long_press_work; +static struct k_work_delayable epd_work; +static struct k_work_delayable long_press_work; static struct { int pin; @@ -61,7 +61,7 @@ static struct { { .pin = RGB_LED_BLU, }, }; -struct k_delayed_work led_timer; +struct k_work_delayable led_timer; static size_t print_line(enum font_size font_size, int row, const char *text, size_t len, bool center) @@ -121,7 +121,7 @@ static size_t get_len(enum font_size font, const char *text) void board_blink_leds(void) { - k_delayed_work_submit(&led_timer, K_MSEC(100)); + k_work_reschedule(&led_timer, K_MSEC(100)); } void board_show_text(const char *text, bool center, int32_t duration) @@ -151,7 +151,7 @@ void board_show_text(const char *text, bool center, int32_t duration) cfb_framebuffer_finalize(epd_dev); if (duration != K_FOREVER) { - k_delayed_work_submit(&epd_work, duration); + k_work_reschedule(&epd_work, duration); } } @@ -381,11 +381,11 @@ static void button_interrupt(struct os_event *ev) printk("Button %s\n", pressed ? "pressed" : "released"); if (pressed) { - k_delayed_work_submit(&long_press_work, LONG_PRESS_TIMEOUT); + k_work_reschedule(&long_press_work, LONG_PRESS_TIMEOUT); return; } - k_delayed_work_cancel(&long_press_work); + k_work_cancel_delayable(&long_press_work); if (!mesh_is_initialized()) { return; @@ -441,7 +441,7 @@ static void led_timeout(struct ble_npl_event *work) i = led_cntr++ % ARRAY_SIZE(leds); hal_gpio_write(leds[i].pin, 0); - k_delayed_work_submit(&led_timer, K_MSEC(100)); + k_work_reschedule(&led_timer, K_MSEC(100)); } static int configure_leds(void) @@ -452,7 +452,7 @@ static int configure_leds(void) hal_gpio_init_out(leds[i].pin, 1); } - k_delayed_work_init(&led_timer, led_timeout); + k_work_init_delayable(&led_timer, led_timeout); return 0; } @@ -466,7 +466,7 @@ static int erase_storage(void) void board_refresh_display(void) { - k_delayed_work_submit(&epd_work, K_NO_WAIT); + k_work_reschedule(&epd_work, K_NO_WAIT); } int board_init(void) @@ -494,8 +494,8 @@ int board_init(void) return -EIO; } - k_delayed_work_init(&epd_work, epd_update); - k_delayed_work_init(&long_press_work, long_press); + k_work_init_delayable(&epd_work, epd_update); + k_work_init_delayable(&long_press_work, long_press); pressed = button_is_pressed(); if (pressed) { diff --git a/nimble/host/mesh/include/mesh/access.h b/nimble/host/mesh/include/mesh/access.h index 9f923cb9e4..f12ec85b59 100644 --- a/nimble/host/mesh/include/mesh/access.h +++ b/nimble/host/mesh/include/mesh/access.h @@ -436,7 +436,7 @@ struct bt_mesh_model_pub { int (*update)(struct bt_mesh_model *mod); /** Publish Period Timer. Only for stack-internal use. */ - struct k_delayed_work timer; + struct k_work_delayable timer; }; /** Model callback functions. */ diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index eedaaac92d..34a32aed9c 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -329,22 +329,24 @@ int bt_le_adv_start(const struct ble_gap_adv_params *param, const struct bt_data *sd, size_t sd_len); int bt_le_adv_stop(bool proxy); -struct k_delayed_work { +struct k_work_delayable { struct ble_npl_callout work; }; void k_work_init(struct ble_npl_callout *work, ble_npl_event_fn handler); -void k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f); -void k_delayed_work_cancel(struct k_delayed_work *w); -bool k_delayed_work_pending(struct k_delayed_work *w); -void k_delayed_work_submit(struct k_delayed_work *w, uint32_t ms); +void k_work_init_delayable(struct k_work_delayable *w, ble_npl_event_fn *f); +void k_work_cancel_delayable(struct k_work_delayable *w); +bool k_work_delayable_is_pending(struct k_work_delayable *w); +void k_work_reschedule(struct k_work_delayable *w, uint32_t ms); int64_t k_uptime_get(void); uint32_t k_uptime_get_32(void); void k_sleep(int32_t duration); void k_work_submit(struct ble_npl_callout *w); void k_work_add_arg(struct ble_npl_callout *w, void *arg); -void k_delayed_work_add_arg(struct k_delayed_work *w, void *arg); -uint32_t k_delayed_work_remaining_get(struct k_delayed_work *w); +void k_work_add_arg_delayable(struct k_work_delayable *w, void *arg); +ble_npl_time_t k_work_delayable_remaining_get(struct k_work_delayable *w); +void k_work_schedule(struct k_work_delayable *w, uint32_t ms); +uint32_t k_ticks_to_ms_floor32(ble_npl_time_t ticks); static inline void net_buf_simple_save(struct os_mbuf *buf, struct net_buf_simple_state *state) diff --git a/nimble/host/mesh/include/mesh/health_srv.h b/nimble/host/mesh/include/mesh/health_srv.h index ad79e368da..980e757486 100644 --- a/nimble/host/mesh/include/mesh/health_srv.h +++ b/nimble/host/mesh/include/mesh/health_srv.h @@ -65,7 +65,7 @@ struct bt_mesh_health_srv { const struct bt_mesh_health_srv_cb *cb; /* Attention Timer state */ - struct k_delayed_work attn_timer; + struct k_work_delayable attn_timer; }; int bt_mesh_fault_update(struct bt_mesh_elem *elem); diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index c6436e85e8..5c12792ecb 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -148,7 +148,7 @@ static void publish_sent(int err, void *user_data) if (delay) { BT_DBG("Publishing next time in %dms", (int) delay); - k_delayed_work_submit(&mod->pub->timer, delay); + k_work_reschedule(&mod->pub->timer, delay); } } @@ -228,7 +228,7 @@ static void mod_publish(struct ble_npl_event *work) /* Continue with normal publication */ if (period_ms) { - k_delayed_work_submit(&pub->timer, period_ms); + k_work_reschedule(&pub->timer, period_ms); } } @@ -301,8 +301,8 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, if (mod->pub) { mod->pub->mod = mod; - k_delayed_work_init(&mod->pub->timer, mod_publish); - k_delayed_work_add_arg(&mod->pub->timer, mod->pub); + k_work_init_delayable(&mod->pub->timer, mod_publish); + k_work_add_arg_delayable(&mod->pub->timer, mod->pub); } for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { @@ -738,7 +738,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) if (pub->count) { BT_WARN("Clearing publish retransmit timer"); - k_delayed_work_cancel(&pub->timer); + k_work_cancel_delayable(&pub->timer); } net_buf_simple_init(sdu, 0); @@ -1249,7 +1249,7 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, if (ms > 0) { BT_DBG("Starting publish timer (period %u ms)", ms); - k_delayed_work_submit(&mod->pub->timer, K_MSEC(ms)); + k_work_reschedule(&mod->pub->timer, K_MSEC(ms)); } } diff --git a/nimble/host/mesh/src/beacon.c b/nimble/host/mesh/src/beacon.c index 6a5fc5a1cd..d7be9c5e1c 100644 --- a/nimble/host/mesh/src/beacon.c +++ b/nimble/host/mesh/src/beacon.c @@ -34,7 +34,7 @@ /* 1 transmission, 20ms interval */ #define PROV_XMIT BT_MESH_TRANSMIT(0, 20) -static struct k_delayed_work beacon_timer; +static struct k_work_delayable beacon_timer; static int cache_check(struct bt_mesh_subnet *sub, void *beacon_data) { @@ -230,7 +230,7 @@ static void beacon_send(struct ble_npl_event *work) { /* Don't send anything if we have an active provisioning link */ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && bt_mesh_prov_active()) { - k_delayed_work_submit(&beacon_timer, + k_work_reschedule(&beacon_timer, K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT))); return; } @@ -244,7 +244,7 @@ static void beacon_send(struct ble_npl_event *work) /* Only resubmit if beaconing is still enabled */ if (bt_mesh_beacon_enabled() || atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { - k_delayed_work_submit(&beacon_timer, + k_work_reschedule(&beacon_timer, PROVISIONED_INTERVAL); } @@ -253,7 +253,7 @@ static void beacon_send(struct ble_npl_event *work) if (IS_ENABLED(BLE_MESH_PB_ADV)) { unprovisioned_beacon_send(); - k_delayed_work_submit(&beacon_timer, + k_work_reschedule(&beacon_timer, K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT))); } } @@ -430,7 +430,7 @@ void bt_mesh_beacon_init(void) bt_mesh_subnet_cb_list[1] = subnet_evt; } - k_delayed_work_init(&beacon_timer, beacon_send); + k_work_init_delayable(&beacon_timer, beacon_send); } void bt_mesh_beacon_ivu_initiator(bool enable) @@ -438,9 +438,9 @@ void bt_mesh_beacon_ivu_initiator(bool enable) atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable); if (enable) { - k_delayed_work_submit(&beacon_timer, K_NO_WAIT); + k_work_reschedule(&beacon_timer, K_NO_WAIT); } else if (!bt_mesh_beacon_enabled()) { - k_delayed_work_cancel(&beacon_timer); + k_work_cancel_delayable(&beacon_timer); } } @@ -455,18 +455,18 @@ static void subnet_beacon_enable(struct bt_mesh_subnet *sub) void bt_mesh_beacon_enable(void) { if (!bt_mesh_is_provisioned()) { - k_delayed_work_submit(&beacon_timer, K_NO_WAIT); + k_work_reschedule(&beacon_timer, K_NO_WAIT); return; } bt_mesh_subnet_foreach(subnet_beacon_enable); - k_delayed_work_submit(&beacon_timer, K_NO_WAIT); + k_work_reschedule(&beacon_timer, K_NO_WAIT); } void bt_mesh_beacon_disable(void) { if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { - k_delayed_work_cancel(&beacon_timer); + k_work_cancel_delayable(&beacon_timer); } } diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 4c0da372ba..919c26a94a 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -200,7 +200,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, model->pub->count = 0; if (model->pub->update) { - k_delayed_work_cancel(&model->pub->timer); + k_work_cancel_delayable(&model->pub->timer); } if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { @@ -238,9 +238,9 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, BT_DBG("period %u ms", (unsigned) period_ms); if (period_ms > 0) { - k_delayed_work_submit(&model->pub->timer, period_ms); + k_work_reschedule(&model->pub->timer, period_ms); } else { - k_delayed_work_cancel(&model->pub->timer); + k_work_cancel_delayable(&model->pub->timer); } } @@ -2128,7 +2128,8 @@ static void lpn_timeout_get(struct bt_mesh_model *model, goto send_rsp; } - timeout = k_delayed_work_remaining_get(&frnd->timer) / 100; + timeout = k_ticks_to_ms_floor32( + k_work_delayable_remaining_get(&frnd->timer)) / 100; send_rsp: net_buf_simple_add_le24(msg, timeout); diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index b544a7830a..402930f9f8 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -151,7 +151,7 @@ static void friend_clear(struct bt_mesh_friend *frnd) BT_DBG("LPN 0x%04x", frnd->lpn); - k_delayed_work_cancel(&frnd->timer); + k_work_cancel_delayable(&frnd->timer); memset(frnd->cred, 0, sizeof(frnd->cred)); @@ -605,7 +605,7 @@ static void friend_recv_delay(struct bt_mesh_friend *frnd) int32_t delay = recv_delay(frnd); frnd->pending_req = 1; - k_delayed_work_submit(&frnd->timer, K_MSEC(delay)); + k_work_reschedule(&frnd->timer, K_MSEC(delay)); BT_DBG("Waiting RecvDelay of %d ms", delay); } @@ -772,7 +772,7 @@ static void friend_clear_sent(int err, void *user_data) { struct bt_mesh_friend *frnd = user_data; - k_delayed_work_submit(&frnd->clear.timer, + k_work_reschedule(&frnd->clear.timer, K_SECONDS(frnd->clear.repeat_sec)); frnd->clear.repeat_sec *= 2; } @@ -867,7 +867,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx, return 0; } - k_delayed_work_cancel(&frnd->clear.timer); + k_work_cancel_delayable(&frnd->clear.timer); frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED; return 0; @@ -1037,7 +1037,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) } delay = offer_delay(frnd, rx->ctx.recv_rssi, msg->criteria); - k_delayed_work_submit(&frnd->timer, K_MSEC(delay)); + k_work_reschedule(&frnd->timer, K_MSEC(delay)); enqueue_offer(frnd, rx->ctx.recv_rssi); @@ -1154,12 +1154,12 @@ static void buf_send_end(int err, void *user_data) } if (frnd->established) { - k_delayed_work_submit(&frnd->timer, frnd->poll_to); + k_work_reschedule(&frnd->timer, frnd->poll_to); BT_DBG("Waiting %u ms for next poll", (unsigned) frnd->poll_to); } else { /* Friend offer timeout is 1 second */ - k_delayed_work_submit(&frnd->timer, K_SECONDS(1)); + k_work_reschedule(&frnd->timer, K_SECONDS(1)); BT_DBG("Waiting for first poll"); } } @@ -1322,10 +1322,10 @@ int bt_mesh_friend_init(void) net_buf_slist_init(&frnd->queue); - k_delayed_work_init(&frnd->timer, friend_timeout); - k_delayed_work_add_arg(&frnd->timer, frnd); - k_delayed_work_init(&frnd->clear.timer, clear_timeout); - k_delayed_work_add_arg(&frnd->clear.timer, frnd); + k_work_init_delayable(&frnd->timer, friend_timeout); + k_work_add_arg_delayable(&frnd->timer, frnd); + k_work_init_delayable(&frnd->clear.timer, clear_timeout); + k_work_add_arg_delayable(&frnd->clear.timer, frnd); for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) { net_buf_slist_init(&frnd->seg[j].queue); diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index 8862344dca..2059e2a6f4 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -399,7 +399,7 @@ k_work_init(struct ble_npl_callout *work, ble_npl_event_fn handler) } void -k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f) +k_work_init_delayable(struct k_work_delayable *w, ble_npl_event_fn *f) { #ifndef MYNEWT ble_npl_callout_init(&w->work, nimble_port_get_dflt_eventq(), f, NULL); @@ -409,25 +409,39 @@ k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f) } bool -k_delayed_work_pending(struct k_delayed_work *w) +k_work_delayable_is_pending(struct k_work_delayable *w) { return ble_npl_callout_is_active(&w->work); } void -k_delayed_work_cancel(struct k_delayed_work *w) +k_work_cancel_delayable(struct k_work_delayable *w) { ble_npl_callout_stop(&w->work); } void -k_delayed_work_submit(struct k_delayed_work *w, uint32_t ms) +k_work_schedule(struct k_work_delayable *w, uint32_t ms) + { + uint32_t ticks; + + if (ble_npl_time_ms_to_ticks(ms, &ticks) != 0) { + assert(0); + } + ble_npl_callout_reset(&w->work, ticks); +} + +void +k_work_reschedule(struct k_work_delayable *w, uint32_t ms) { uint32_t ticks; if (ble_npl_time_ms_to_ticks(ms, &ticks) != 0) { assert(0); } + if (ms == 0) { + ble_npl_callout_stop(&w->work); + } ble_npl_callout_reset(&w->work, ticks); } @@ -444,13 +458,13 @@ k_work_add_arg(struct ble_npl_callout *w, void *arg) } void -k_delayed_work_add_arg(struct k_delayed_work *w, void *arg) +k_work_add_arg_delayable(struct k_work_delayable *w, void *arg) { k_work_add_arg(&w->work, arg); } -uint32_t -k_delayed_work_remaining_get (struct k_delayed_work *w) +ble_npl_time_t +k_work_delayable_remaining_get (struct k_work_delayable *w) { int sr; ble_npl_time_t t; @@ -461,7 +475,13 @@ k_delayed_work_remaining_get (struct k_delayed_work *w) OS_EXIT_CRITICAL(sr); - return ble_npl_time_ticks_to_ms32(t); + return t; +} + +uint32_t +k_ticks_to_ms_floor32(ble_npl_time_t ticks) +{ + return ble_npl_time_ticks_to_ms32(ticks); } int64_t k_uptime_get(void) diff --git a/nimble/host/mesh/src/health_srv.c b/nimble/host/mesh/src/health_srv.c index dd90533be8..d7436b30a3 100644 --- a/nimble/host/mesh/src/health_srv.c +++ b/nimble/host/mesh/src/health_srv.c @@ -221,7 +221,8 @@ static void send_attention_status(struct bt_mesh_model *model, struct bt_mesh_health_srv *srv = model->user_data; uint8_t time; - time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000; + time = k_ticks_to_ms_floor32( + k_work_delayable_remaining_get(&srv->attn_timer)) / 1000; BT_DBG("%u second%s", time, (time == 1) ? "" : "s"); bt_mesh_model_msg_init(msg, OP_ATTENTION_STATUS); @@ -400,8 +401,8 @@ static int health_srv_init(struct bt_mesh_model *model) model->pub->update = health_pub_update; - k_delayed_work_init(&srv->attn_timer, attention_off); - k_delayed_work_add_arg(&srv->attn_timer, srv); + k_work_init_delayable(&srv->attn_timer, attention_off); + k_work_add_arg_delayable(&srv->attn_timer, srv); srv->model = model; @@ -433,17 +434,8 @@ void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time) srv = model->user_data; } - if (time) { - if (srv->cb && srv->cb->attn_on) { - srv->cb->attn_on(model); - } - - k_delayed_work_submit(&srv->attn_timer, time * 1000); - } else { - k_delayed_work_cancel(&srv->attn_timer); - - if (srv->cb && srv->cb->attn_off) { - srv->cb->attn_off(model); - } + if ((time > 0) && srv->cb && srv->cb->attn_on) { + srv->cb->attn_on(model); } + k_work_reschedule(&srv->attn_timer, K_SECONDS(time)); } diff --git a/nimble/host/mesh/src/heartbeat.c b/nimble/host/mesh/src/heartbeat.c index 656942b426..1d249b4899 100644 --- a/nimble/host/mesh/src/heartbeat.c +++ b/nimble/host/mesh/src/heartbeat.c @@ -31,8 +31,8 @@ struct bt_mesh_hb_cb hb_cb; static struct bt_mesh_hb_pub pub; static struct bt_mesh_hb_sub sub; -static struct k_delayed_work sub_timer; -static struct k_delayed_work pub_timer; +static struct k_work_delayable sub_timer; +static struct k_work_delayable pub_timer; static int64_t sub_remaining(void) { @@ -40,13 +40,15 @@ static int64_t sub_remaining(void) return 0U; } - return k_delayed_work_remaining_get(&sub_timer) / MSEC_PER_SEC; + uint32_t rem_ms = k_ticks_to_ms_floor32( + k_work_delayable_remaining_get(&sub_timer)); + return rem_ms / MSEC_PER_SEC; } static void hb_publish_end_cb(int err, void *cb_data) { if (pub.period && pub.count > 1) { - k_delayed_work_submit(&pub_timer, K_SECONDS(pub.period)); + k_work_reschedule(&pub_timer, K_SECONDS(pub.period)); } if (pub.count != 0xffff) { @@ -148,6 +150,11 @@ static void hb_publish(struct ble_npl_event *work) BT_DBG("hb_pub.count: %u", pub.count); + /* Fast exit if disabled or expired */ + if (pub.period == 0U || pub.count == 0U) { + return; + } + sub = bt_mesh_subnet_get(pub.net_idx); if (!sub) { BT_ERR("No matching subnet for idx 0x%02x", pub.net_idx); @@ -155,10 +162,6 @@ static void hb_publish(struct ble_npl_event *work) return; } - if (pub.count == 0U) { - return; - } - err = heartbeat_send(&publish_cb, NULL); if (err) { hb_publish_end_cb(err, NULL); @@ -185,8 +188,8 @@ int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) return 0; } - if (!k_delayed_work_pending(&sub_timer)) { - BT_DBG("Heartbeat subscription period expired"); + if (!k_work_delayable_is_pending(&sub_timer)) { + BT_DBG("Heartbeat subscription inactive"); return 0; } @@ -215,7 +218,7 @@ static void pub_disable(void) pub.ttl = 0U; pub.period = 0U; - k_delayed_work_cancel(&pub_timer); + k_work_cancel_delayable(&pub_timer); } uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub) @@ -247,12 +250,11 @@ uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub) /* The first Heartbeat message shall be published as soon as possible * after the Heartbeat Publication Period state has been configured for * periodic publishing. + * + * If the new configuration disables publishing this flushes + * the work item. */ - if (pub.period && pub.count) { - k_delayed_work_submit(&pub_timer, K_NO_WAIT); - } else { - k_delayed_work_cancel(&pub_timer); - } + k_work_reschedule(&pub_timer, K_NO_WAIT); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_settings_store_schedule( @@ -294,9 +296,7 @@ uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period) sub.min_hops = 0U; sub.max_hops = 0U; sub.count = 0U; - sub.period = sub.period - sub_remaining(); - k_delayed_work_cancel(&sub_timer); - notify_sub_end(); + sub.period = 0U; } else if (period) { sub.src = src; sub.dst = dst; @@ -304,16 +304,18 @@ uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period) sub.max_hops = 0U; sub.count = 0U; sub.period = period; - k_delayed_work_submit(&sub_timer, K_SECONDS(period)); } else { /* Clearing the period should stop heartbeat subscription * without clearing the parameters, so we can still read them. */ - sub.period = sub.period - sub_remaining(); - k_delayed_work_cancel(&sub_timer); - notify_sub_end(); + sub.period = 0U; } + /* Start the timer, which notifies immediately if the new + * configuration disables the subscription. + */ + k_work_reschedule(&sub_timer, K_SECONDS(sub.period)); + return STATUS_SUCCESS; } @@ -344,28 +346,28 @@ void bt_mesh_hb_feature_changed(uint16_t features) void bt_mesh_hb_init(void) { pub.net_idx = BT_MESH_KEY_UNUSED; - k_delayed_work_init(&pub_timer, hb_publish); - k_delayed_work_init(&sub_timer, sub_end); + k_work_init_delayable(&pub_timer, hb_publish); + k_work_init_delayable(&sub_timer, sub_end); } void bt_mesh_hb_start(void) { if (pub.count && pub.period) { BT_DBG("Starting heartbeat publication"); - k_delayed_work_submit(&pub_timer, K_NO_WAIT); + k_work_reschedule(&pub_timer, K_NO_WAIT); } } void bt_mesh_hb_suspend(void) { - k_delayed_work_cancel(&pub_timer); + (void)k_work_cancel_delayable(&pub_timer); } void bt_mesh_hb_resume(void) { if (pub.period && pub.count) { BT_DBG("Starting heartbeat publication"); - k_delayed_work_submit(&pub_timer, K_NO_WAIT); + k_work_reschedule(&pub_timer, K_NO_WAIT); } } diff --git a/nimble/host/mesh/src/lpn.c b/nimble/host/mesh/src/lpn.c index 45c9004b63..4c6c708ca2 100644 --- a/nimble/host/mesh/src/lpn.c +++ b/nimble/host/mesh/src/lpn.c @@ -182,7 +182,7 @@ static void friend_clear_sent(int err, void *user_data) } lpn_set_state(BT_MESH_LPN_CLEAR); - k_delayed_work_submit(&lpn->timer, FRIEND_REQ_TIMEOUT); + k_work_reschedule(&lpn->timer, FRIEND_REQ_TIMEOUT); } static const struct bt_mesh_send_cb clear_sent_cb = { @@ -230,7 +230,7 @@ static void clear_friendship(bool force, bool disable) bt_mesh_rx_reset(); lpn_set_state(BT_MESH_LPN_DISABLED); - k_delayed_work_cancel(&lpn->timer); + k_work_cancel_delayable(&lpn->timer); if (lpn->clear_success) { lpn->old_friend = BT_MESH_ADDR_UNASSIGNED; @@ -267,7 +267,7 @@ static void clear_friendship(bool force, bool disable) if (!disable) { lpn_set_state(BT_MESH_LPN_DISABLED); - k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); + k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); return; } @@ -285,10 +285,10 @@ static void friend_req_sent(uint16_t duration, int err, void *user_data) lpn->adv_duration = duration; if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - k_delayed_work_submit(&lpn->timer, FRIEND_REQ_WAIT); + k_work_reschedule(&lpn->timer, FRIEND_REQ_WAIT); lpn_set_state(BT_MESH_LPN_REQ_WAIT); } else { - k_delayed_work_submit(&lpn->timer, + k_work_reschedule(&lpn->timer, duration + FRIEND_REQ_TIMEOUT); lpn_set_state(BT_MESH_LPN_WAIT_OFFER); } @@ -362,11 +362,11 @@ static void req_sent(uint16_t duration, int err, void *user_data) /* We start scanning a bit early to elimitate risk of missing * response data due to HCI and other latencies. */ - k_delayed_work_submit(&lpn->timer, + k_work_reschedule(&lpn->timer, LPN_RECV_DELAY - SCAN_LATENCY); } else { lpn_set_state(BT_MESH_LPN_WAIT_UPDATE); - k_delayed_work_submit(&lpn->timer, + k_work_reschedule(&lpn->timer, LPN_RECV_DELAY + duration + lpn->recv_win); } @@ -459,7 +459,7 @@ int bt_mesh_lpn_set(bool enable) } else { if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO) && lpn->state == BT_MESH_LPN_TIMER) { - k_delayed_work_cancel(&lpn->timer); + k_work_cancel_delayable(&lpn->timer); lpn_set_state(BT_MESH_LPN_DISABLED); } else { bt_mesh_lpn_disable(false); @@ -484,7 +484,7 @@ static void friend_response_received(struct bt_mesh_lpn *lpn) int32_t timeout = poll_timeout(lpn); - k_delayed_work_submit(&lpn->timer, K_MSEC(timeout)); + k_work_reschedule(&lpn->timer, K_MSEC(timeout)); } void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) @@ -493,7 +493,7 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) if (lpn->state == BT_MESH_LPN_TIMER) { BT_DBG("Restarting establishment timer"); - k_delayed_work_submit(&lpn->timer, LPN_AUTO_TIMEOUT); + k_work_reschedule(&lpn->timer, LPN_AUTO_TIMEOUT); return; } @@ -754,7 +754,7 @@ static void update_timeout(struct bt_mesh_lpn *lpn) BT_WARN("No response from Friend during ReceiveWindow"); bt_mesh_scan_disable(); lpn_set_state(BT_MESH_LPN_ESTABLISHED); - k_delayed_work_submit(&lpn->timer, POLL_RETRY_TIMEOUT); + k_work_reschedule(&lpn->timer, POLL_RETRY_TIMEOUT); } else { if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { bt_mesh_scan_disable(); @@ -799,7 +799,7 @@ static void lpn_timeout(struct ble_npl_event *work) break; case BT_MESH_LPN_REQ_WAIT: bt_mesh_scan_enable(); - k_delayed_work_submit(&lpn->timer, + k_work_reschedule(&lpn->timer, lpn->adv_duration + FRIEND_REQ_SCAN); lpn_set_state(BT_MESH_LPN_WAIT_OFFER); break; @@ -811,7 +811,7 @@ static void lpn_timeout(struct ble_npl_event *work) lpn->lpn_counter++; lpn_set_state(BT_MESH_LPN_ENABLED); lpn->sent_req = 0U; - k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); + k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); break; case BT_MESH_LPN_ESTABLISHED: if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { @@ -834,7 +834,7 @@ static void lpn_timeout(struct ble_npl_event *work) clear_friendship(false, false); break; case BT_MESH_LPN_RECV_DELAY: - k_delayed_work_submit(&lpn->timer, + k_work_reschedule(&lpn->timer, lpn->adv_duration + SCAN_LATENCY + lpn->recv_win); bt_mesh_scan_enable(); @@ -1067,7 +1067,7 @@ int bt_mesh_lpn_init(void) BT_DBG(""); - k_delayed_work_init(&lpn->timer, lpn_timeout); + k_work_init_delayable(&lpn->timer, lpn_timeout); if (lpn->state == BT_MESH_LPN_ENABLED) { if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { @@ -1083,7 +1083,7 @@ int bt_mesh_lpn_init(void) if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO)) { BT_DBG("Waiting %u ms for messages", LPN_AUTO_TIMEOUT); lpn_set_state(BT_MESH_LPN_TIMER); - k_delayed_work_submit(&lpn->timer, LPN_AUTO_TIMEOUT); + k_work_reschedule(&lpn->timer, LPN_AUTO_TIMEOUT); } } diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index 2417872a95..a9bdb3154c 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -174,7 +174,7 @@ void bt_mesh_reset(void) memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags)); - k_delayed_work_cancel(&bt_mesh.ivu_timer); + k_work_cancel_delayable(&bt_mesh.ivu_timer); bt_mesh_cfg_reset(); @@ -240,7 +240,7 @@ static void model_suspend(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, { if (mod->pub && mod->pub->update) { mod->pub->count = 0; - k_delayed_work_cancel(&mod->pub->timer); + k_work_cancel_delayable(&mod->pub->timer); } } @@ -281,7 +281,7 @@ static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, int32_t period_ms = bt_mesh_model_pub_period_get(mod); if (period_ms) { - k_delayed_work_submit(&mod->pub->timer, period_ms); + k_work_reschedule(&mod->pub->timer, period_ms); } } } diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index b3e22aad30..4c102f7a8c 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -307,7 +307,7 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) bt_mesh.seq = 0; } - k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); + k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); /* Notify other modules */ if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { @@ -869,7 +869,7 @@ static void ivu_refresh(struct ble_npl_event *work) store_iv(true); } - k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); + k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); return; } @@ -1035,7 +1035,7 @@ void bt_mesh_net_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_seq conf"); - k_delayed_work_init(&bt_mesh.ivu_timer, ivu_refresh); + k_work_init_delayable(&bt_mesh.ivu_timer, ivu_refresh); k_work_init(&bt_mesh.local_work, bt_mesh_net_local); net_buf_slist_init(&bt_mesh.local_queue); @@ -1181,6 +1181,6 @@ void bt_mesh_net_clear(void) void bt_mesh_net_settings_commit(void) { if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) { - k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); + k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); } } diff --git a/nimble/host/mesh/src/net.h b/nimble/host/mesh/src/net.h index 33b491e4b5..9d8f857610 100644 --- a/nimble/host/mesh/src/net.h +++ b/nimble/host/mesh/src/net.h @@ -74,7 +74,7 @@ struct bt_mesh_friend { uint16_t sub_list[FRIEND_SUB_LIST_SIZE]; - struct k_delayed_work timer; + struct k_work_delayable timer; struct bt_mesh_friend_seg { struct net_buf_slist_t queue; @@ -96,7 +96,7 @@ struct bt_mesh_friend { uint32_t start; /* Clear Procedure start */ uint16_t frnd; /* Previous Friend's address */ uint16_t repeat_sec; /* Repeat timeout in seconds */ - struct k_delayed_work timer; /* Repeat timer */ + struct k_work_delayable timer; /* Repeat timer */ } clear; }; @@ -160,7 +160,7 @@ struct bt_mesh_lpn { uint16_t adv_duration; /* Next LPN related action timer */ - struct k_delayed_work timer; + struct k_work_delayable timer; /* Subscribed groups */ uint16_t groups[LPN_GROUPS]; @@ -221,7 +221,7 @@ struct bt_mesh_net { uint8_t default_ttl; /* Timer to track duration in current IV Update state */ - struct k_delayed_work ivu_timer; + struct k_work_delayable ivu_timer; uint8_t dev_key[16]; }; diff --git a/nimble/host/mesh/src/pb_adv.c b/nimble/host/mesh/src/pb_adv.c index 50b8419e10..f4cafab03f 100644 --- a/nimble/host/mesh/src/pb_adv.c +++ b/nimble/host/mesh/src/pb_adv.c @@ -105,11 +105,11 @@ struct pb_adv { void *cb_data; /* Retransmit timer */ - struct k_delayed_work retransmit; + struct k_work_delayable retransmit; } tx; /* Protocol timeout */ - struct k_delayed_work prot_timer; + struct k_work_delayable prot_timer; }; struct prov_rx { @@ -136,7 +136,7 @@ static void buf_sent(int err, void *user_data) } BT_DBG("submit retransmit"); - k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT); + k_work_reschedule(&link.tx.retransmit, RETRANSMIT_TIMEOUT); } static struct bt_mesh_send_cb buf_sent_cb = { @@ -181,7 +181,7 @@ static void prov_clear_tx(void) { BT_DBG(""); - k_delayed_work_cancel(&link.tx.retransmit); + k_work_cancel_delayable(&link.tx.retransmit); free_segments(); } @@ -191,7 +191,7 @@ static void reset_adv_link(void) BT_DBG(""); prov_clear_tx(); - k_delayed_work_cancel(&link.prot_timer); + k_work_cancel_delayable(&link.prot_timer); if (atomic_test_bit(link.flags, ADV_PROVISIONER)) { /* Clear everything except the retransmit and protocol timer @@ -258,7 +258,7 @@ static void prov_failed(uint8_t err) static void prov_msg_recv(void) { - k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) { BT_ERR("Incorrect FCS"); @@ -624,7 +624,7 @@ static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len, BT_DBG("op 0x%02x data_len %u", op, data_len); prov_clear_tx(); - k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); buf = adv_buf_create(reliable ? RETRANSMITS_RELIABLE : RETRANSMITS_UNRELIABLE); @@ -656,7 +656,7 @@ static int prov_send_adv(struct os_mbuf *msg, uint8_t seg_len, seg_id; prov_clear_tx(); - k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); start = adv_buf_create(RETRANSMITS_RELIABLE); if (!start) { @@ -864,8 +864,8 @@ static void prov_link_close(enum prov_bearer_link_status status) void pb_adv_init(void) { - k_delayed_work_init(&link.prot_timer, protocol_timeout); - k_delayed_work_init(&link.tx.retransmit, prov_retransmit); + k_work_init_delayable(&link.prot_timer, protocol_timeout); + k_work_init_delayable(&link.tx.retransmit, prov_retransmit); if (!rx_buf) { rx_buf = NET_BUF_SIMPLE(65); diff --git a/nimble/host/mesh/src/pb_gatt.c b/nimble/host/mesh/src/pb_gatt.c index bce7cf6c09..c358e2e43e 100644 --- a/nimble/host/mesh/src/pb_gatt.c +++ b/nimble/host/mesh/src/pb_gatt.c @@ -27,7 +27,7 @@ struct prov_link { uint8_t fcs; /* Expected FCS value */ struct os_mbuf *buf; } rx; - struct k_delayed_work prot_timer; + struct k_work_delayable prot_timer; }; static struct prov_link link; @@ -36,7 +36,7 @@ static void reset_state(void) { link.conn_handle = BLE_HS_CONN_HANDLE_NONE; - k_delayed_work_cancel(&link.prot_timer); + k_work_cancel_delayable(&link.prot_timer); link.rx.buf = bt_mesh_proxy_get_buf(); } @@ -73,7 +73,7 @@ int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf) return -EINVAL; } - k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); link.cb->recv(&pb_gatt, link.cb_data, buf); @@ -89,7 +89,7 @@ int bt_mesh_pb_gatt_open(uint16_t conn_handle) } link.conn_handle = conn_handle; - k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); link.cb->link_opened(&pb_gatt, link.cb_data); @@ -131,7 +131,7 @@ static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb, return -ENOTCONN; } - k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, buf); } @@ -143,7 +143,7 @@ static void clear_tx(void) void pb_gatt_init(void) { - k_delayed_work_init(&link.prot_timer, protocol_timeout); + k_work_init_delayable(&link.prot_timer, protocol_timeout); } void pb_gatt_reset(void) diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/proxy.c index d013c79894..515d86e8c3 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/proxy.c @@ -125,7 +125,7 @@ static struct bt_mesh_proxy_client { #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) struct ble_npl_callout send_beacons; #endif - struct k_delayed_work sar_timer; + struct k_work_delayable sar_timer; struct os_mbuf *buf; } clients[MYNEWT_VAL(BLE_MAX_CONNECTIONS)] = { [0 ... (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1)] = { 0 }, @@ -568,7 +568,7 @@ static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle, return -EINVAL; } - k_delayed_work_submit(&client->sar_timer, PROXY_SAR_TIMEOUT); + k_work_reschedule(&client->sar_timer, PROXY_SAR_TIMEOUT); client->msg_type = PDU_TYPE(data); net_buf_simple_add_mem(client->buf, data + 1, len - 1); break; @@ -584,7 +584,7 @@ static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle, return -EINVAL; } - k_delayed_work_submit(&client->sar_timer, PROXY_SAR_TIMEOUT); + k_work_reschedule(&client->sar_timer, PROXY_SAR_TIMEOUT); net_buf_simple_add_mem(client->buf, data + 1, len - 1); break; @@ -599,7 +599,7 @@ static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle, return -EINVAL; } - k_delayed_work_cancel(&client->sar_timer); + k_work_cancel_delayable(&client->sar_timer); net_buf_simple_add_mem(client->buf, data + 1, len - 1); proxy_complete_pdu(client); break; @@ -661,7 +661,7 @@ static void proxy_disconnected(uint16_t conn_handle, int reason) bt_mesh_pb_gatt_close(conn_handle); } - k_delayed_work_cancel(&client->sar_timer); + k_work_cancel_delayable(&client->sar_timer); client->conn_handle = BLE_HS_CONN_HANDLE_NONE; break; } @@ -1543,8 +1543,8 @@ int bt_mesh_proxy_init(void) clients[i].buf = NET_BUF_SIMPLE(CLIENT_BUF_SIZE); clients[i].conn_handle = BLE_HS_CONN_HANDLE_NONE; - k_delayed_work_init(&clients[i].sar_timer, proxy_sar_timeout); - k_delayed_work_add_arg(&clients[i].sar_timer, &clients[i]); + k_work_init_delayable(&clients[i].sar_timer, proxy_sar_timeout); + k_work_add_arg_delayable(&clients[i].sar_timer, &clients[i]); } resolve_svc_handles(); diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index 3d28ac94da..19a9c3f87a 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -27,7 +27,7 @@ #include "config/config.h" -static struct k_delayed_work pending_store; +static struct k_work_delayable pending_store; static ATOMIC_DEFINE(pending_flags, BT_MESH_SETTINGS_FLAG_COUNT); int settings_name_next(char *name, char **next) @@ -97,7 +97,7 @@ static int mesh_commit(void) void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag) { - int32_t timeout_ms, remaining; + int32_t timeout_ms, remaining_ms; atomic_set_bit(pending_flags, flag); @@ -113,15 +113,18 @@ void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag) timeout_ms = CONFIG_BT_MESH_STORE_TIMEOUT * MSEC_PER_SEC; } - remaining = k_delayed_work_remaining_get(&pending_store); - if ((remaining > 0) && remaining < timeout_ms) { - BT_DBG("Not rescheduling due to existing earlier deadline"); - return; + remaining_ms = k_ticks_to_ms_floor32( + k_work_delayable_remaining_get(&pending_store)); + BT_DBG("Waiting %u ms vs rem %u ms", timeout_ms, remaining_ms); + /* If the new deadline is sooner, override any existing + * deadline; otherwise schedule without changing any existing + * deadline. + */ + if (timeout_ms < remaining_ms) { + k_work_reschedule(&pending_store, K_MSEC(timeout_ms)); + } else { + k_work_schedule(&pending_store, K_MSEC(timeout_ms)); } - - BT_DBG("Waiting %d seconds", timeout_ms / MSEC_PER_SEC); - - k_delayed_work_submit(&pending_store, K_MSEC(timeout_ms)); } static void store_pending(struct ble_npl_event *work) { @@ -201,7 +204,7 @@ void bt_mesh_settings_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_settings conf"); - k_delayed_work_init(&pending_store, store_pending); + k_work_init_delayable(&pending_store, store_pending); } #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 0299c98331..18e88d7ce5 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -107,7 +107,7 @@ static struct seg_tx { friend_cred:1; /* Using Friend credentials */ const struct bt_mesh_send_cb *cb; void *cb_data; - struct k_delayed_work retransmit; /* Retransmit timer */ + struct k_work_delayable retransmit; /* Retransmit timer */ } seg_tx[MYNEWT_VAL(BLE_MESH_TX_SEG_MSG_COUNT)]; static struct seg_rx { @@ -125,7 +125,7 @@ static struct seg_rx { uint8_t ttl; uint32_t block; uint32_t last; - struct k_delayed_work ack; + struct k_work_delayable ack; } seg_rx[CONFIG_BT_MESH_RX_SEG_MSG_COUNT]; @@ -248,7 +248,7 @@ static void seg_tx_unblock_check(struct seg_tx *tx) BT_DBG("Unblocked 0x%04x", (uint16_t)(blocked->seq_auth & TRANS_SEQ_ZERO_MASK)); blocked->blocked = false; - k_delayed_work_submit(&blocked->retransmit, 0); + k_work_reschedule(&blocked->retransmit, 0); } } @@ -256,7 +256,7 @@ static void seg_tx_reset(struct seg_tx *tx) { int i; - k_delayed_work_cancel(&tx->retransmit); + k_work_cancel_delayable(&tx->retransmit); tx->cb = NULL; tx->cb_data = NULL; @@ -317,7 +317,7 @@ static void schedule_retransmit(struct seg_tx *tx) * called this from inside bt_mesh_net_send), we should continue the * retransmit immediately, as we just freed up a tx buffer. */ - k_delayed_work_submit(&tx->retransmit, + k_work_reschedule(&tx->retransmit, tx->seg_o ? 0 : K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx))); } @@ -439,7 +439,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx) tx->attempts--; end: if (!tx->seg_pending) { - k_delayed_work_submit(&tx->retransmit, + k_work_reschedule(&tx->retransmit, SEG_RETRANSMIT_TIMEOUT(tx)); } @@ -860,7 +860,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, return -EINVAL; } - k_delayed_work_cancel(&tx->retransmit); + k_work_cancel_delayable(&tx->retransmit); while ((bit = find_lsb_set(ack))) { if (tx->seg[bit - 1]) { @@ -1094,7 +1094,7 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset) BT_DBG("rx %p", rx); - k_delayed_work_cancel(&rx->ack); + k_work_cancel_delayable(&rx->ack); if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->obo && rx->block != BLOCK_COMPLETE(rx->seg_n)) { @@ -1148,7 +1148,7 @@ static void seg_ack(struct ble_npl_event *work) rx->block, rx->obo); timeout = ack_timeout(rx); - k_delayed_work_submit(&rx->ack, K_MSEC(timeout)); + k_work_reschedule(&rx->ack, K_MSEC(timeout)); } static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n) @@ -1429,11 +1429,11 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, /* Reset the Incomplete Timer */ rx->last = k_uptime_get_32(); - if (!k_delayed_work_remaining_get(&rx->ack) && + if (!k_work_delayable_remaining_get(&rx->ack) && !bt_mesh_lpn_established()) { int32_t timeout = ack_timeout(rx); - k_delayed_work_submit(&rx->ack, K_MSEC(timeout)); + k_work_reschedule(&rx->ack, K_MSEC(timeout)); } /* Allocated segment here */ @@ -1464,7 +1464,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, *pdu_type = BT_MESH_FRIEND_PDU_COMPLETE; - k_delayed_work_cancel(&rx->ack); + k_work_cancel_delayable(&rx->ack); send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo); @@ -1641,16 +1641,16 @@ void bt_mesh_trans_init(void) } for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { - k_delayed_work_init(&seg_tx[i].retransmit, seg_retransmit); - k_delayed_work_add_arg(&seg_tx[i].retransmit, &seg_tx[i]); + k_work_init_delayable(&seg_tx[i].retransmit, seg_retransmit); + k_work_add_arg_delayable(&seg_tx[i].retransmit, &seg_tx[i]); } /* XXX Probably we need mempool for that. * For now we increase MSYS_1_BLOCK_COUNT */ for (i = 0; i < ARRAY_SIZE(seg_rx); i++) { - k_delayed_work_init(&seg_rx[i].ack, seg_ack); - k_delayed_work_add_arg(&seg_rx[i].ack, &seg_rx[i]); + k_work_init_delayable(&seg_rx[i].ack, seg_ack); + k_work_add_arg_delayable(&seg_rx[i].ack, &seg_rx[i]); } } @@ -1856,12 +1856,6 @@ void bt_mesh_va_pending_store(void) } } } -#else -void bt_mesh_va_pending_store(void) -{ - /* Do nothing. */ -} -#endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */ static struct conf_handler bt_mesh_va_conf_handler = { .ch_name = "bt_mesh", @@ -1880,4 +1874,10 @@ void bt_mesh_va_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_hb_pub conf"); } -#endif \ No newline at end of file + +#else +void bt_mesh_va_pending_store(void) +{ + /* Do nothing. */ +} +#endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */ From 840e92249ad5b0a871a180fe8d325257d7b0f40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 6 Oct 2021 15:40:04 +0200 Subject: [PATCH 148/306] host/mesh: Perform replay check on SeqAuth To prevent the transport layer from accepting duplicate or out of order segmented messages, add an RPL-like check for the SeqAuth of the segmented messages when their context is allocated. This prevents duplicate receives of the same segmented messages in the case where a single source address sends two segmented messages in parallel (to two different addresses): Previously, when receiving two segmented messages, the first message would go through to the access layer, then the second. Then, if the transport layer received any repeated segments for the first message, it would fail to identify the SeqAuth as old, as all its segments were of new sequence numbers, and the "already complete SDU" check would only look at the second message. Thus, the segmented message got processed again and passed to the access layer, even though it was a duplicate. To solve this, we need a mechanism like RPL, but only for the segmented messages' SeqAuth. We cannot re-use the actual RPL mechanism, as it can't support the scenario provoked by the "blocking tx" mechanism in transport. This mechanism allocates the SeqAuth when the message is first passed to the transport layer. The ongoing message that caused the block would keep sending segments with higher sequence numbers than the blocked message got, which will cause the blocked message to fail the RPL check. This patch adds a parallel SeqAuth mechanism to the RPL module, which only deals with the SeqAuth of the segmented messages. This list gets checked when the segmented message is first allocated, in the same manner as the general RPL mechanism. The storage gets hooked into the RPL mechanism, by adding a separate seg field to each RPL entry. This is port of 4fbd0cb0ca6bead0354f54808da3224302d98c28 --- nimble/host/mesh/src/rpl.c | 29 ++++++++++++++++++----------- nimble/host/mesh/src/rpl.h | 16 ++++++++++------ nimble/host/mesh/src/transport.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/nimble/host/mesh/src/rpl.c b/nimble/host/mesh/src/rpl.c index 830ab1b01e..3c4045ca5b 100644 --- a/nimble/host/mesh/src/rpl.c +++ b/nimble/host/mesh/src/rpl.c @@ -25,12 +25,16 @@ struct rpl_val { }; static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)]; +static ATOMIC_DEFINE(store, MYNEWT_VAL(BLE_MESH_CRPL)); + +static inline int rpl_idx(const struct bt_mesh_rpl *rpl) +{ + return rpl - &replay_list[0]; +} static void schedule_rpl_store(struct bt_mesh_rpl *entry) { -#ifdef CONFIG_BT_SETTINGS - entry->store = true; -#endif + atomic_set_bit(store, rpl_idx(entry)); bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); } @@ -42,6 +46,13 @@ static void schedule_rpl_clear(void) void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx) { + /* If this is the first message on the new IV index, we should reset it + * to zero to avoid invalid combinations of IV index and seg. + */ + if (rpl->old_iv && !rx->old_iv) { + rpl->seg = 0; + } + rpl->src = rx->ctx.addr; rpl->seq = rx->seq; rpl->old_iv = rx->old_iv; @@ -276,20 +287,16 @@ static void clear_rpl(struct bt_mesh_rpl *rpl) } (void)memset(rpl, 0, sizeof(*rpl)); + atomic_clear_bit(store, rpl_idx(rpl)); } static void store_pending_rpl(struct bt_mesh_rpl *rpl) { BT_DBG(""); -#ifdef CONFIG_BT_SETTINGS - if (!rpl->store) { - return; + if (atomic_test_and_clear_bit(store, rpl_idx(rpl))) { + store_rpl(rpl); } - - rpl->store = false; -#endif - store_rpl(rpl); } void bt_mesh_rpl_pending_store(void) @@ -311,7 +318,7 @@ static struct conf_handler bt_mesh_rpl_conf_handler = { .ch_set = rpl_set, .ch_commit = NULL, .ch_export = NULL, - }; +}; void bt_mesh_rpl_init(void) { diff --git a/nimble/host/mesh/src/rpl.h b/nimble/host/mesh/src/rpl.h index d47484a329..9a1d49ff07 100644 --- a/nimble/host/mesh/src/rpl.h +++ b/nimble/host/mesh/src/rpl.h @@ -8,12 +8,16 @@ */ struct bt_mesh_rpl { - uint16_t src; - bool old_iv; -#if defined(CONFIG_BT_SETTINGS) - bool store; -#endif - uint32_t seq; + uint64_t src:15, + old_iv:1, + seq:24, + /** Sequence authentication value for the previous segmented + * message received from this address. + * + * This value is used to manage the parallel RPL of the + * SeqAuth values in transport. + */ + seg:24; }; typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl, diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 18e88d7ce5..643606349c 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -1263,6 +1263,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, struct seg_rx *rx; uint8_t *hdr = buf->om_data; uint16_t seq_zero; + uint32_t auth_seqnum; uint8_t seg_n; uint8_t seg_o; int err; @@ -1314,6 +1315,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, ((((net_rx->seq & BIT_MASK(14)) - seq_zero)) & BIT_MASK(13)))); + auth_seqnum = *seq_auth & BIT_MASK(24); *seg_count = seg_n + 1; /* Look for old RX sessions */ @@ -1382,6 +1384,28 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, return -ENOBUFS; } + /* Keep track of the received SeqAuth values received from this address + * and discard segmented messages that are not newer, as described in + * the Bluetooth Mesh specification section 3.5.3.4. + * + * The logic on the first segmented receive is a bit special, since the + * initial value of rpl->seg is 0, which would normally fail the + * comparison check with auth_seqnum: + * - If this is the first time we receive from this source, rpl->src + * will be 0, and we can skip this check. + * - If this is the first time we receive from this source on the new IV + * index, rpl->old_iv will be set, and the check is also skipped. + * - If this is the first segmented message on the new IV index, but we + * have received an unsegmented message already, the unsegmented + * message will have reset rpl->seg to 0, and this message's SeqAuth + * cannot be zero. + */ + if (rpl && rpl->src && auth_seqnum <= rpl->seg && + (!rpl->old_iv || net_rx->old_iv)) { + BT_WARN("Ignoring old SeqAuth 0x%06x", auth_seqnum); + return -EALREADY; + } + /* Look for free slot for a new RX session */ rx = seg_rx_alloc(net_rx, hdr, seq_auth, seg_n); if (!rx) { @@ -1460,6 +1484,12 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, if (rpl) { bt_mesh_rpl_update(rpl, net_rx); + /* Update the seg, unless it has already been surpassed: + * This needs to happen after rpl_update to ensure that the IV + * update reset logic inside rpl_update doesn't overwrite the + * change. + */ + rpl->seg = MAX(rpl->seg, auth_seqnum); } *pdu_type = BT_MESH_FRIEND_PDU_COMPLETE; From ffbd3587c784f189801c5cad7e528b0def1f1a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 07:37:11 +0200 Subject: [PATCH 149/306] host/mesh: Fix restoring fast period divisor from settings The Health Fast Period Divisor is stored within the model publish parameters on the access layer. The opposite part for divisor restoring has been missed. This is port of 73e1c6a77d71f8b51746946f78f0b3525101e1c0 --- nimble/host/mesh/src/access.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 5c12792ecb..9459da63e5 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -960,6 +960,7 @@ static int mod_set_pub(struct bt_mesh_model *mod, char *val) mod->pub->ttl = pub.ttl; mod->pub->period = pub.period; mod->pub->retransmit = pub.retransmit; + mod->pub->period_div = pub.period_div; mod->pub->count = 0; BT_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x", From 21f1b076af4fcdc10b6d6439c91284c01d1d24e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 07:40:27 +0200 Subject: [PATCH 150/306] host/mesh: Send Link Close message when closing link Instead of silently closing the link we should send a Link Close message three times before resetting provisioning state. From Mesh Profile Specification v1.0.1.: ``` 5.3.1.4.3 Link Close message The Link Close message is used to close a link. ``` ``` 5.3.2 Link Establishment procedure The device shall start the link timer, set to 60 seconds, when the link is open. When the link timer expires, then the device shall close the link. ``` ``` 5.3.3 Generic Provisioning behavior If the sender does not receive a Transaction Acknowledgment message within 30 seconds after sending the first message in a transaction, the sender shall cancel the transaction, cancel the provisioning process and close the link. ``` From Mesh Profile Test Specification p6: ``` MESH/PVNR/PBADV/BV-01-C Test Procedure: [...] 6. The IUT is induced to send a Link Close message with the Reason field set to 0x02 to terminate the link. The message is sent at least three times to ensure the message is received by the Lower Tester. ``` This is port of 497d9df96acde1d28f7cd83c786e496e8ea0db67 --- nimble/host/mesh/src/pb_adv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/pb_adv.c b/nimble/host/mesh/src/pb_adv.c index f4cafab03f..1fa4c8e996 100644 --- a/nimble/host/mesh/src/pb_adv.c +++ b/nimble/host/mesh/src/pb_adv.c @@ -589,7 +589,7 @@ static void prov_retransmit(struct ble_npl_event *work) close_link(PROV_BEARER_LINK_STATUS_SUCCESS); } else { BT_WARN("Giving up transaction"); - close_link(PROV_BEARER_LINK_STATUS_TIMEOUT); + prov_link_close(PROV_BEARER_LINK_STATUS_TIMEOUT); } return; From b5e2a3a300da187e1bf3a10a3dbb4cf134a96e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 08:03:10 +0200 Subject: [PATCH 151/306] host/mesh: Rename bt_mesh_cfg_comp_data_get's status param to rsp The first byte of the composition data status message is the returned page index, not the status of the request. This is now reflected in the API. This is port of 9259b199bba0ae982632c36069a472b197627521 --- nimble/host/mesh/include/mesh/cfg_cli.h | 2 +- nimble/host/mesh/src/cfg_cli.c | 10 ++++++---- nimble/host/mesh/src/shell.c | 11 +++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/nimble/host/mesh/include/mesh/cfg_cli.h b/nimble/host/mesh/include/mesh/cfg_cli.h index 368bdfc344..ea1b7e3213 100644 --- a/nimble/host/mesh/include/mesh/cfg_cli.h +++ b/nimble/host/mesh/include/mesh/cfg_cli.h @@ -41,7 +41,7 @@ extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb; int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status); int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, - uint8_t *status, struct os_mbuf *comp); + uint8_t *rsp, struct os_mbuf *comp); int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status); diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index 6806818d8a..ab1f9ec31f 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -25,7 +25,7 @@ #define DUMMY_2_BYTE_OP BT_MESH_MODEL_OP_2(0xff, 0xff) struct comp_data { - uint8_t *status; + uint8_t *page; struct os_mbuf *comp; }; @@ -56,7 +56,9 @@ static void comp_data_status(struct bt_mesh_model *model, param = cli->op_param; - *(param->status) = net_buf_simple_pull_u8(buf); + if (param->page) { + *(param->page) = net_buf_simple_pull_u8(buf); + } to_copy = min(net_buf_simple_tailroom(param->comp), buf->om_len); net_buf_simple_add_mem(param->comp, buf->om_data, to_copy); @@ -807,7 +809,7 @@ static int cli_wait(void) } int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, - uint8_t *status, struct os_mbuf *comp) + uint8_t *rsp, struct os_mbuf *comp) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEV_COMP_DATA_GET, 1); struct bt_mesh_msg_ctx ctx = { @@ -817,7 +819,7 @@ int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, .send_ttl = BT_MESH_TTL_DEFAULT, }; struct comp_data param = { - .status = status, + .page = rsp, .comp = comp, }; int err; diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index 99c4f95b2c..4ff2c7edae 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -998,7 +998,7 @@ struct shell_cmd_help cmd_timeout_help = { static int cmd_get_comp(int argc, char *argv[]) { struct os_mbuf *comp = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); - uint8_t status, page = 0x00; + uint8_t page = 0x00; int err = 0; if (argc > 1) { @@ -1007,16 +1007,15 @@ static int cmd_get_comp(int argc, char *argv[]) net_buf_simple_init(comp, 0); err = bt_mesh_cfg_comp_data_get(net.net_idx, net.dst, page, - &status, comp); + &page, comp); if (err) { printk("Getting composition failed (err %d)\n", err); goto done; } - if (status != 0x00) { - printk("Got non-success status 0x%02x\n", status); - goto done; - } + if (page != 0x00) { + shell_print(shell, "Got page 0x%02x. No parser available.", + page); printk("Got Composition Data for 0x%04x:\n", net.dst); printk("\tCID 0x%04x\n", net_buf_simple_pull_le16(comp)); From 5b4fd3021be60c400b0d233f29c8fcdf8f536b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 08:40:04 +0200 Subject: [PATCH 152/306] host/mesh: Composition data page 0 traversal Adds a parsing mechanism for Composition data page 0 in the Config Client API, and uses it in the shell module to parse the incoming composition data. This is port of b84fee5190cd72e9d31fa820aaa5d8684ad4a11c --- nimble/host/mesh/include/mesh/access.h | 13 +++-- nimble/host/mesh/include/mesh/cfg_cli.h | 36 +++++++++++++ nimble/host/mesh/include/mesh/glue.h | 4 ++ nimble/host/mesh/src/cfg_cli.c | 64 ++++++++++++++++++++++ nimble/host/mesh/src/shell.c | 70 +++++++++++++------------ 5 files changed, 149 insertions(+), 38 deletions(-) diff --git a/nimble/host/mesh/include/mesh/access.h b/nimble/host/mesh/include/mesh/access.h index f12ec85b59..4892e43402 100644 --- a/nimble/host/mesh/include/mesh/access.h +++ b/nimble/host/mesh/include/mesh/access.h @@ -495,14 +495,19 @@ struct bt_mesh_model_cb { void (*const reset)(struct bt_mesh_model *model); }; +/** Vendor model ID */ +struct bt_mesh_mod_id_vnd { + /** Vendor's company ID */ + uint16_t company; + /** Model ID */ + uint16_t id; +}; + /** Abstraction that describes a Mesh Model instance */ struct bt_mesh_model { union { const uint16_t id; - struct { - uint16_t company; - uint16_t id; - } vnd; + const struct bt_mesh_mod_id_vnd vnd; }; /* Internal information, mainly for persistent storage */ diff --git a/nimble/host/mesh/include/mesh/cfg_cli.h b/nimble/host/mesh/include/mesh/cfg_cli.h index ea1b7e3213..745e6b27de 100644 --- a/nimble/host/mesh/include/mesh/cfg_cli.h +++ b/nimble/host/mesh/include/mesh/cfg_cli.h @@ -269,6 +269,42 @@ int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr, int32_t bt_mesh_cfg_cli_timeout_get(void); void bt_mesh_cfg_cli_timeout_set(int32_t timeout); +struct bt_mesh_comp_p0 { + /** Company ID */ + uint16_t cid; + /** Product ID */ + uint16_t pid; + /** Version ID */ + uint16_t vid; + /** Replay protection list size */ + uint16_t crpl; + /** Supported features, see @ref BT_MESH_FEAT_SUPPORTED. */ + uint16_t feat; + + struct os_mbuf *_buf; +}; + +struct bt_mesh_comp_p0_elem { + /** Element location */ + uint16_t loc; + /** The number of SIG models in this element */ + size_t nsig; + /** The number of vendor models in this element */ + size_t nvnd; + + uint8_t *_buf; +}; + +int bt_mesh_comp_p0_get(struct bt_mesh_comp_p0 *comp, + struct os_mbuf *buf); + +struct bt_mesh_comp_p0_elem *bt_mesh_comp_p0_elem_pull(const struct bt_mesh_comp_p0 *comp, + struct bt_mesh_comp_p0_elem *elem); + +uint16_t bt_mesh_comp_p0_elem_mod(struct bt_mesh_comp_p0_elem *elem, int idx); + +struct bt_mesh_mod_id_vnd bt_mesh_comp_p0_elem_mod_vnd(struct bt_mesh_comp_p0_elem *elem, int idx); + #ifdef __cplusplus } #endif diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 34a32aed9c..760088b1c2 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -144,6 +144,10 @@ extern "C" { #define ASSERT_NOT_CHAIN(om) (void)(om) #endif +#define CHECKIF(expr) \ + __ASSERT_NO_MSG(!(expr)); \ + if (0) + #define __packed __attribute__((__packed__)) #define MSEC_PER_SEC (1000) diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index ab1f9ec31f..82e6a82a59 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -2145,4 +2145,68 @@ void bt_mesh_cfg_cli_timeout_set(int32_t timeout) msg_timeout = timeout; } +int bt_mesh_comp_p0_get(struct bt_mesh_comp_p0 *page, + struct os_mbuf *buf) +{ + if (buf->om_len < 10) { + return -EINVAL; + } + + page->cid = net_buf_simple_pull_le16(buf); + page->pid = net_buf_simple_pull_le16(buf); + page->vid = net_buf_simple_pull_le16(buf); + page->crpl = net_buf_simple_pull_le16(buf); + page->feat = net_buf_simple_pull_le16(buf); + page->_buf = buf; + + return 0; +} + +struct bt_mesh_comp_p0_elem *bt_mesh_comp_p0_elem_pull(const struct bt_mesh_comp_p0 *page, + struct bt_mesh_comp_p0_elem *elem) +{ + size_t modlist_size; + + if (page->_buf->om_len < 4) { + return NULL; + } + + elem->loc = net_buf_simple_pull_le16(page->_buf); + elem->nsig = net_buf_simple_pull_u8(page->_buf); + elem->nvnd = net_buf_simple_pull_u8(page->_buf); + + modlist_size = elem->nsig * 2 + elem->nvnd * 4; + + if (page->_buf->om_len < modlist_size) { + return NULL; + } + + elem->_buf = net_buf_simple_pull_mem(page->_buf, modlist_size); + + return elem; +} + +uint16_t bt_mesh_comp_p0_elem_mod(struct bt_mesh_comp_p0_elem *elem, int idx) + { + CHECKIF(idx >= elem->nsig) { + return 0xffff; + } + + return sys_get_le16(&elem->_buf[idx * 2]); +} + +struct bt_mesh_mod_id_vnd bt_mesh_comp_p0_elem_mod_vnd(struct bt_mesh_comp_p0_elem *elem, int idx) + { + CHECKIF(idx >= elem->nvnd) { + return (struct bt_mesh_mod_id_vnd){ 0xffff, 0xffff }; + } + + size_t offset = elem->nsig * 2 + idx * 4; + struct bt_mesh_mod_id_vnd mod = { + .company = sys_get_le16(&elem->_buf[offset]), + .id = sys_get_le16(&elem->_buf[offset + 2]), + }; + + return mod; +} #endif diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index 4ff2c7edae..61f1db69e0 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -997,7 +997,9 @@ struct shell_cmd_help cmd_timeout_help = { static int cmd_get_comp(int argc, char *argv[]) { - struct os_mbuf *comp = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); + struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); + struct bt_mesh_comp_p0_elem elem; + struct bt_mesh_comp_p0 comp; uint8_t page = 0x00; int err = 0; @@ -1005,69 +1007,69 @@ static int cmd_get_comp(int argc, char *argv[]) page = strtol(argv[1], NULL, 0); } - net_buf_simple_init(comp, 0); - err = bt_mesh_cfg_comp_data_get(net.net_idx, net.dst, page, - &page, comp); + net_buf_simple_init(buf, 0); + err = bt_mesh_cfg_comp_data_get(net.net_idx, net.dst, page, &page, + buf); if (err) { printk("Getting composition failed (err %d)\n", err); goto done; } if (page != 0x00) { - shell_print(shell, "Got page 0x%02x. No parser available.", + printk("Got page 0x%02x. No parser available.", page); + goto done; + } - printk("Got Composition Data for 0x%04x:\n", net.dst); - printk("\tCID 0x%04x\n", net_buf_simple_pull_le16(comp)); - printk("\tPID 0x%04x\n", net_buf_simple_pull_le16(comp)); - printk("\tVID 0x%04x\n", net_buf_simple_pull_le16(comp)); - printk("\tCRPL 0x%04x\n", net_buf_simple_pull_le16(comp)); - printk("\tFeatures 0x%04x\n", net_buf_simple_pull_le16(comp)); - - while (comp->om_len > 4) { - uint8_t sig, vnd; - uint16_t loc; - int i; - - loc = net_buf_simple_pull_le16(comp); - sig = net_buf_simple_pull_u8(comp); - vnd = net_buf_simple_pull_u8(comp); + err = bt_mesh_comp_p0_get(&comp, buf); + if (err) { + printk("Getting composition failed (err %d)\n", err); + goto done; + } - printk("\n\tElement @ 0x%04x:\n", loc); + printk("Got Composition Data for 0x%04x:", net.dst); + printk("\tCID 0x%04x", comp.cid); + printk("\tPID 0x%04x", comp.pid); + printk("\tVID 0x%04x", comp.vid); + printk("\tCRPL 0x%04x", comp.crpl); + printk("\tFeatures 0x%04x", comp.feat); - if (comp->om_len < ((sig * 2) + (vnd * 4))) { - printk("\t\t...truncated data!\n"); - break; - } + while (bt_mesh_comp_p0_elem_pull(&comp, &elem)) { + int i; - if (sig) { + printk("\tElement @ 0x%04x:", elem.loc); + if (elem.nsig) { printk("\t\tSIG Models:\n"); } else { printk("\t\tNo SIG Models\n"); } - for (i = 0; i < sig; i++) { - uint16_t mod_id = net_buf_simple_pull_le16(comp); + for (i = 0; i < elem.nsig; i++) { + uint16_t mod_id = bt_mesh_comp_p0_elem_mod(&elem, i); printk("\t\t\t0x%04x\n", mod_id); } - if (vnd) { + if (elem.nvnd) { printk("\t\tVendor Models:\n"); } else { printk("\t\tNo Vendor Models\n"); } - for (i = 0; i < vnd; i++) { - uint16_t cid = net_buf_simple_pull_le16(comp); - uint16_t mod_id = net_buf_simple_pull_le16(comp); + for (i = 0; i < elem.nvnd; i++) { + struct bt_mesh_mod_id_vnd mod = + bt_mesh_comp_p0_elem_mod_vnd(&elem, i); - printk("\t\t\tCompany 0x%04x: 0x%04x\n", cid, mod_id); + printk("\t\t\tCompany 0x%04x: 0x%04x", + mod.company, mod.id); } } + if (buf->om_len) { + printk("\t\t...truncated data!"); + } done: - os_mbuf_free_chain(comp); + os_mbuf_free_chain(buf); return err; } From 8fa05b8f2d83e82e9170ebf7bb5eaeb48b1d14f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 13:22:56 +0200 Subject: [PATCH 153/306] host/mesh: Introduce acknowledged message API The implementation of blocking calls is common for all the client models. This change reduces the code duplication by introducing new API that helps to manage acknowledged messages. This is port of a94c7e3a23fc1225aec9f13c1e37cc2853f70c82 and c5e4011e29b878fc1771876fc30db0ddcc084829 --- nimble/host/mesh/include/mesh/access.h | 80 +----- nimble/host/mesh/include/mesh/cfg_cli.h | 6 +- nimble/host/mesh/include/mesh/glue.h | 4 + nimble/host/mesh/include/mesh/health_cli.h | 4 +- nimble/host/mesh/include/mesh/mesh.h | 1 + nimble/host/mesh/include/mesh/msg.h | 225 ++++++++++++++++ nimble/host/mesh/src/access.c | 25 -- nimble/host/mesh/src/cfg_cli.c | 300 +++++++++------------ nimble/host/mesh/src/health_cli.c | 106 +++----- nimble/host/mesh/src/msg.c | 83 ++++++ 10 files changed, 482 insertions(+), 352 deletions(-) create mode 100644 nimble/host/mesh/include/mesh/msg.h create mode 100644 nimble/host/mesh/src/msg.c diff --git a/nimble/host/mesh/include/mesh/access.h b/nimble/host/mesh/include/mesh/access.h index 4892e43402..0efee414f8 100644 --- a/nimble/host/mesh/include/mesh/access.h +++ b/nimble/host/mesh/include/mesh/access.h @@ -10,6 +10,8 @@ #ifndef __BT_MESH_ACCESS_H #define __BT_MESH_ACCESS_H +#include "msg.h" + /** * @brief Bluetooth Mesh Access Layer * @defgroup bt_mesh_access Bluetooth Mesh Access Layer @@ -138,33 +140,6 @@ struct bt_mesh_elem { #define BT_MESH_MODEL_ID_LIGHT_LC_SETUPSRV 0x1310 #define BT_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311 -/** Message sending context. */ -struct bt_mesh_msg_ctx { - /** NetKey Index of the subnet to send the message on. */ - uint16_t net_idx; - - /** AppKey Index to encrypt the message with. */ - uint16_t app_idx; - - /** Remote address. */ - uint16_t addr; - - /** Destination address of a received message. Not used for sending. */ - uint16_t recv_dst; - - /** RSSI of received packet. Not used for sending. */ - int8_t recv_rssi; - - /** Received TTL value. Not used for sending. */ - uint8_t recv_ttl; - - /** Force sending reliably by using segment acknowledgement */ - bool send_rel; - - /** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */ - uint8_t send_ttl; -}; - struct bt_mesh_model_op { /* OpCode encoded using the BT_MESH_MODEL_OP_* macros */ const uint32_t opcode; @@ -189,55 +164,6 @@ struct bt_mesh_model_op { /** Helper to define an empty model array */ #define BT_MESH_MODEL_NONE ((struct bt_mesh_model []){}) -/** Length of a short Mesh MIC. */ -#define BT_MESH_MIC_SHORT 4 -/** Length of a long Mesh MIC. */ -#define BT_MESH_MIC_LONG 8 - -/** @def BT_MESH_MODEL_OP_LEN - * - * @brief Helper to determine the length of an opcode. - * - * @param _op Opcode. - */ -#define BT_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3) - -/** @def BT_MESH_MODEL_BUF_LEN - * - * @brief Helper for model message buffer length. - * - * Returns the length of a Mesh model message buffer, including the opcode - * length and a short MIC. - * - * @param _op Opcode of the message. - * @param _payload_len Length of the model payload. - */ -#define BT_MESH_MODEL_BUF_LEN(_op, _payload_len) \ - (BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_SHORT) - -/** @def BT_MESH_MODEL_BUF_LEN_LONG_MIC - * - * @brief Helper for model message buffer length. - * - * Returns the length of a Mesh model message buffer, including the opcode - * length and a long MIC. - * - * @param _op Opcode of the message. - * @param _payload_len Length of the model payload. - */ -#define BT_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \ - (BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_LONG) - -/** @def BT_MESH_MODEL_BUF_DEFINE - * - * @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE. - * - * @param _op Opcode of the message. - * @param _payload_len Length of the model message payload. - */ -#define BT_MESH_MODEL_BUF(_op, _payload_len) \ - NET_BUF_SIMPLE(BT_MESH_MODEL_BUF_LEN(_op, (_payload_len))) - /** @def BT_MESH_MODEL_CB * * @brief Composition data SIG model entry with callback functions. @@ -544,8 +470,6 @@ struct bt_mesh_send_cb { void (*end)(int err, void *cb_data); }; -void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode); - /** Special TTL value to request using configured default TTL */ #define BT_MESH_TTL_DEFAULT 0xff diff --git a/nimble/host/mesh/include/mesh/cfg_cli.h b/nimble/host/mesh/include/mesh/cfg_cli.h index 745e6b27de..c117066d27 100644 --- a/nimble/host/mesh/include/mesh/cfg_cli.h +++ b/nimble/host/mesh/include/mesh/cfg_cli.h @@ -24,11 +24,7 @@ extern "C" { /** Mesh Configuration Client Model Context */ struct bt_mesh_cfg_cli { struct bt_mesh_model *model; - - struct k_sem op_sync; - uint32_t op_pending; - void *op_param; - uint16_t op_addr; + struct bt_mesh_msg_ack_ctx ack_ctx; }; extern const struct bt_mesh_model_op bt_mesh_cfg_cli_op[]; diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 760088b1c2..9dfd051096 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -478,6 +478,10 @@ static inline void k_sem_give(struct k_sem *sem) ble_npl_sem_release(sem); } +static inline void k_sem_reset(struct k_sem *sem) +{ + ble_npl_sem_init(sem, 0); +} /* Helpers to access the storage array, since we don't have access to its * type at this point anymore. */ diff --git a/nimble/host/mesh/include/mesh/health_cli.h b/nimble/host/mesh/include/mesh/health_cli.h index e9efe4b1f9..cb14ee6bcd 100644 --- a/nimble/host/mesh/include/mesh/health_cli.h +++ b/nimble/host/mesh/include/mesh/health_cli.h @@ -29,9 +29,7 @@ struct bt_mesh_health_cli { uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count); - struct k_sem op_sync; - uint32_t op_pending; - void *op_param; + struct bt_mesh_msg_ack_ctx ack_ctx; }; extern const struct bt_mesh_model_op bt_mesh_health_cli_op[]; diff --git a/nimble/host/mesh/include/mesh/mesh.h b/nimble/host/mesh/include/mesh/mesh.h index 83390ec4ce..c644d0bb0b 100644 --- a/nimble/host/mesh/include/mesh/mesh.h +++ b/nimble/host/mesh/include/mesh/mesh.h @@ -15,6 +15,7 @@ #include "os/os_mbuf.h" #include "glue.h" +#include "msg.h" #include "access.h" #include "main.h" #include "cfg.h" diff --git a/nimble/host/mesh/include/mesh/msg.h b/nimble/host/mesh/include/mesh/msg.h new file mode 100644 index 0000000000..0cc00ff35b --- /dev/null +++ b/nimble/host/mesh/include/mesh/msg.h @@ -0,0 +1,225 @@ +/** @file + * @brief Bluetooth Mesh Message APIs. + */ + +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ + +/** + * @brief Bluetooth Mesh Message API + * @defgroup bt_mesh_msg Bluetooth Mesh Message API + * @ingroup bt_mesh + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Length of a short Mesh MIC. */ +#define BT_MESH_MIC_SHORT 4 +/** Length of a long Mesh MIC. */ +#define BT_MESH_MIC_LONG 8 + +/** @def BT_MESH_MODEL_OP_LEN + * + * @brief Helper to determine the length of an opcode. + * + * @param _op Opcode. + */ +#define BT_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3) + + +/** @def BT_MESH_MODEL_BUF_LEN + * + * @brief Helper for model message buffer length. + * + * Returns the length of a Mesh model message buffer, including the opcode + * length and a short MIC. + * + * @param _op Opcode of the message. + * @param _payload_len Length of the model payload. + */ +#define BT_MESH_MODEL_BUF_LEN(_op, _payload_len) \ + (BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_SHORT) + + +/** @def BT_MESH_MODEL_BUF_LEN_LONG_MIC + * + * @brief Helper for model message buffer length. + * + * Returns the length of a Mesh model message buffer, including the opcode + * length and a long MIC. + * + * @param _op Opcode of the message. + * @param _payload_len Length of the model payload. + */ +#define BT_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \ + (BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_LONG) + + +/** @def BT_MESH_MODEL_BUF_DEFINE + * + * @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE_DEFINE. + * + * @param _buf Buffer name. + * @param _op Opcode of the message. + * @param _payload_len Length of the model message payload. + */ +#define BT_MESH_MODEL_BUF(_op, _payload_len) \ + NET_BUF_SIMPLE(BT_MESH_MODEL_BUF_LEN(_op, (_payload_len))) + + +/** Message sending context. */ +struct bt_mesh_msg_ctx { + /** NetKey Index of the subnet to send the message on. */ + uint16_t net_idx; + + /** AppKey Index to encrypt the message with. */ + uint16_t app_idx; + + /** Remote address. */ + uint16_t addr; + + /** Destination address of a received message. Not used for sending. */ + uint16_t recv_dst; + + /** RSSI of received packet. Not used for sending. */ + int8_t recv_rssi; + + /** Received TTL value. Not used for sending. */ + uint8_t recv_ttl; + + /** Force sending reliably by using segment acknowledgment */ + bool send_rel; + + /** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */ + uint8_t send_ttl; +}; + +/** @brief Initialize a model message. + * + * Clears the message buffer contents, and encodes the given opcode. + * The message buffer will be ready for filling in payload data. + * + * @param msg Message buffer. + * @param opcode Opcode to encode. + */ +void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode); + +/** + * Acknowledged message context for tracking the status of model messages pending a response. + */ +struct bt_mesh_msg_ack_ctx { + struct k_sem sem; /**< Sync semaphore. */ + uint32_t op; /**< Opcode we're waiting for. */ + uint16_t dst; /**< Address of the node that should respond. */ + void *user_data; /**< User specific parameter. */ +}; + +/** @brief Initialize an acknowledged message context. + * + * Initializes semaphore used for synchronization between @ref bt_mesh_msg_ack_ctx_wait and + * @ref bt_mesh_msg_ack_ctx_rx calls. Call this function before using @ref bt_mesh_msg_ack_ctx. + * + * @param ack Acknowledged message context to initialize. + */ +static inline void bt_mesh_msg_ack_ctx_init(struct bt_mesh_msg_ack_ctx *ack) +{ + k_sem_init(&ack->sem, 0, 1); +} + +/** @brief Reset the synchronization semaphore in an acknowledged message context. + * + * This function aborts call to @ref bt_mesh_msg_ack_ctx_wait. + * + * @param ack Acknowledged message context to be reset. + */ +static inline void bt_mesh_msg_ack_ctx_reset(struct bt_mesh_msg_ack_ctx *ack) +{ + k_sem_reset(&ack->sem); +} + +/** @brief Clear parameters of an acknowledged message context. + * + * This function clears the opcode, remote address and user data set + * by @ref bt_mesh_msg_ack_ctx_prepare. + * + * @param ack Acknowledged message context to be cleared. + */ +void bt_mesh_msg_ack_ctx_clear(struct bt_mesh_msg_ack_ctx *ack); + +/** @brief Prepare an acknowledged message context for the incoming message to wait. + * + * This function sets the opcode, remote address of the incoming message and stores the user data. + * Use this function before calling @ref bt_mesh_msg_ack_ctx_wait. + * + * @param ack Acknowledged message context to prepare. + * @param op The message OpCode. + * @param dst Destination address of the message. + * @param user_data User data for the acknowledged message context. + * + * @return 0 on success, or (negative) error code on failure. + */ +int bt_mesh_msg_ack_ctx_prepare(struct bt_mesh_msg_ack_ctx *ack, + uint32_t op, uint16_t dst, void *user_data); +/** @brief Check if the acknowledged message context is initialized with an opcode. + * + * @param ack Acknowledged message context. + * + * @return true if the acknowledged message context is initialized with an opcode, + * false otherwise. + */ +static inline bool bt_mesh_msg_ack_ctx_busy(struct bt_mesh_msg_ack_ctx *ack) +{ + return (ack->op != 0); +} + +/** @brief Wait for a message acknowledge. + * + * This function blocks execution until @ref bt_mesh_msg_ack_ctx_rx is called or by timeout. + * + * @param ack Acknowledged message context of the message to wait for. + * @param timeout Wait timeout. + * + * @return 0 on success, or (negative) error code on failure. + */ +int bt_mesh_msg_ack_ctx_wait(struct bt_mesh_msg_ack_ctx *ack, int32_t timeout); + +/** @brief Mark a message as acknowledged. + * + * This function unblocks call to @ref bt_mesh_msg_ack_ctx_wait. + * + * @param ack Context of a message to be acknowledged. + */ +static inline void bt_mesh_msg_ack_ctx_rx(struct bt_mesh_msg_ack_ctx *ack) +{ + k_sem_give(&ack->sem); +} + +/** @brief Check if an opcode and address of a message matches the expected one. + * + * @param ack Acknowledged message context to be checked. + * @param op OpCode of the incoming message. + * @param addr Source address of the incoming message. + * @param user_data If not NULL, returns a user data stored in the acknowledged message context + * by @ref bt_mesh_msg_ack_ctx_prepare. + * + * @return true if the incoming message matches the expected one, false otherwise. + */ +bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, + uint32_t op, uint16_t addr, void **user_data); + +#ifdef __cplusplus +} +#endif +/** + * @} + */ +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ */ \ No newline at end of file diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 9459da63e5..7211777d11 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -631,31 +631,6 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) } } -void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode) -{ - net_buf_simple_init(msg, 0); - - switch (BT_MESH_MODEL_OP_LEN(opcode)) { - case 1: - net_buf_simple_add_u8(msg, opcode); - break; - case 2: - net_buf_simple_add_be16(msg, opcode); - break; - case 3: - net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff)); - /* Using LE for the CID since the model layer is defined as - * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3 - * will declare the opcode in this way. - */ - net_buf_simple_add_le16(msg, opcode & 0xffff); - break; - default: - BT_WARN("Unknown opcode format"); - break; - } -} - static int model_send(struct bt_mesh_model *model, struct bt_mesh_net_tx *tx, bool implicit_bind, struct os_mbuf *msg, diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index 82e6a82a59..dc56f992d5 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -33,11 +33,6 @@ static int32_t msg_timeout = K_SECONDS(5); static struct bt_mesh_cfg_cli *cli; -static inline bool cli_response_check(uint32_t resp_opcode, uint16_t resp_addr) -{ - return cli->op_pending == resp_opcode && cli->op_addr == resp_addr; -} - static void comp_data_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) @@ -49,20 +44,18 @@ static void comp_data_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_DEV_COMP_DATA_STATUS, ctx->addr)) { - BT_WARN("Unexpected Composition Data Status"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_DEV_COMP_DATA_STATUS, ctx->addr, + (void **)¶m)) { return; } - param = cli->op_param; - if (param->page) { *(param->page) = net_buf_simple_pull_u8(buf); } to_copy = min(net_buf_simple_tailroom(param->comp), buf->om_len); net_buf_simple_add_mem(param->comp, buf->om_data, to_copy); - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } static void state_status_u8(struct bt_mesh_model *model, @@ -76,16 +69,14 @@ static void state_status_u8(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(expect_status, ctx->addr)) { - BT_WARN("Unexpected Status (0x%08x != 0x%08x)", - (unsigned) cli->op_pending, (unsigned) expect_status); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, expect_status, ctx->addr, + (void **)&status)) { return; } - status = cli->op_param; *status = net_buf_simple_pull_u8(buf); - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } static void beacon_status(struct bt_mesh_model *model, @@ -131,16 +122,15 @@ static void relay_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_RELAY_STATUS, ctx->addr)) { - BT_WARN("Unexpected Relay Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_RELAY_STATUS, ctx->addr, + (void **)¶m)) { return; } - param = cli->op_param; *param->status = net_buf_simple_pull_u8(buf); *param->transmit = net_buf_simple_pull_u8(buf); - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } static void net_transmit_status(struct bt_mesh_model *model, @@ -153,15 +143,14 @@ static void net_transmit_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_NET_TRANSMIT_STATUS, ctx->addr)) { - BT_WARN("Unexpected Net Transmit Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_TRANSMIT_STATUS, ctx->addr, + (void **)&status)) { return; } - status = cli->op_param; *status = net_buf_simple_pull_u8(buf); - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } struct net_key_param { @@ -181,15 +170,14 @@ static void net_key_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_NET_KEY_STATUS, ctx->addr)) { - BT_WARN("Unexpected Net Key Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_KEY_STATUS, ctx->addr, + (void **)¶m)) { return; } status = net_buf_simple_pull_u8(buf); net_idx = net_buf_simple_pull_le16(buf) & 0xfff; - param = cli->op_param; if (param->net_idx != net_idx) { BT_WARN("Net Key Status key index does not match"); return; @@ -199,7 +187,7 @@ static void net_key_status(struct bt_mesh_model *model, *param->status = status; } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } struct net_key_list_param { @@ -218,13 +206,11 @@ static void net_key_list(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_NET_KEY_LIST, ctx->addr)) { - BT_WARN("Unexpected Net Key List message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_KEY_LIST, ctx->addr, + (void **)¶m)) { return; } - param = cli->op_param; - for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) { key_idx_unpack(buf, ¶m->keys[i], ¶m->keys[i + 1]); } @@ -235,7 +221,7 @@ static void net_key_list(struct bt_mesh_model *model, *param->key_cnt = i; - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } static void node_reset_status(struct bt_mesh_model *model, @@ -245,17 +231,15 @@ static void node_reset_status(struct bt_mesh_model *model, BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x", ctx->net_idx, ctx->app_idx, ctx->addr); - if (!cli_response_check(OP_NODE_RESET_STATUS, ctx->addr)) { - BT_WARN("Unexpected Node Reset Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NODE_RESET_STATUS, ctx->addr, + (void **)¶m)) { return; } - param = cli->op_param; - if (param) { *param = true; } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } struct app_key_param { @@ -276,15 +260,14 @@ static void app_key_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_APP_KEY_STATUS, ctx->addr)) { - BT_WARN("Unexpected App Key Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_APP_KEY_STATUS, ctx->addr, + (void **)¶m)) { return; } status = net_buf_simple_pull_u8(buf); key_idx_unpack(buf, &net_idx, &app_idx); - param = cli->op_param; if (param->net_idx != net_idx || param->app_idx != app_idx) { BT_WARN("App Key Status key indices did not match"); return; @@ -294,7 +277,7 @@ static void app_key_status(struct bt_mesh_model *model, *param->status = status; } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } struct app_key_list_param { @@ -317,15 +300,14 @@ static void app_key_list(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_APP_KEY_LIST, ctx->addr)) { - BT_WARN("Unexpected App Key List message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_APP_KEY_LIST, ctx->addr, + (void **)¶m)) { return; } status = net_buf_simple_pull_u8(buf); net_idx = net_buf_simple_pull_le16(buf) & 0xfff; - param = cli->op_param; if (param->net_idx != net_idx) { BT_WARN("App Key List Net Key index did not match"); return; @@ -344,7 +326,7 @@ static void app_key_list(struct bt_mesh_model *model, *param->status = status; } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } struct mod_app_param { @@ -367,8 +349,8 @@ static void mod_app_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_MOD_APP_STATUS, ctx->addr)) { - BT_WARN("Unexpected Model App Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_APP_STATUS, ctx->addr, + (void **)¶m)) { return; } @@ -384,7 +366,6 @@ static void mod_app_status(struct bt_mesh_model *model, mod_id = net_buf_simple_pull_le16(buf); - param = cli->op_param; if (param->elem_addr != elem_addr || param->mod_app_idx != mod_app_idx || param->mod_id != mod_id || param->cid != cid) { @@ -396,7 +377,7 @@ static void mod_app_status(struct bt_mesh_model *model, *param->status = status; } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } struct mod_member_list_param { @@ -409,9 +390,9 @@ struct mod_member_list_param { }; static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf, bool vnd) + struct os_mbuf *buf, bool vnd, + struct mod_member_list_param *param) { - struct mod_member_list_param *param; uint16_t elem_addr, mod_id, cid; uint8_t status; int i; @@ -424,7 +405,6 @@ static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, mod_id = net_buf_simple_pull_le16(buf); - param = cli->op_param; if (param->elem_addr != elem_addr || param->mod_id != mod_id || (vnd && param->cid != cid)) { BT_WARN("Model Member List parameters did not match"); @@ -445,39 +425,43 @@ static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, *param->status = status; } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } static void mod_app_list(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + struct mod_member_list_param *param; + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_SIG_MOD_APP_LIST, ctx->addr)) { - BT_WARN("Unexpected Model App List message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SIG_MOD_APP_LIST, ctx->addr, + (void **)¶m)) { return; } - mod_member_list_handle(ctx, buf, false); + mod_member_list_handle(ctx, buf, false, param); } static void mod_app_list_vnd(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + struct mod_member_list_param *param; + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_VND_MOD_APP_LIST, ctx->addr)) { - BT_WARN("Unexpected Model App List Vendor message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_VND_MOD_APP_LIST, ctx->addr, + (void **)¶m)) { return; } - mod_member_list_handle(ctx, buf, true); + mod_member_list_handle(ctx, buf, true, param); } struct mod_pub_param { @@ -500,12 +484,12 @@ static void mod_pub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_MOD_PUB_STATUS, ctx->addr)) { + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_PUB_STATUS, ctx->addr, + (void **)¶m)) { BT_WARN("Unexpected Model Pub Status message"); return; } - param = cli->op_param; if (param->cid != CID_NVAL) { if (buf->om_len < 14) { BT_WARN("Unexpected Mod Pub Status with SIG Model"); @@ -552,7 +536,7 @@ static void mod_pub_status(struct bt_mesh_model *model, param->pub->transmit = net_buf_simple_pull_u8(buf); } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } struct mod_sub_param { @@ -576,8 +560,8 @@ static void mod_sub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_MOD_SUB_STATUS, ctx->addr)) { - BT_WARN("Unexpected Model Subscription Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_STATUS, ctx->addr, + (void **)¶m)) { return; } @@ -593,7 +577,6 @@ static void mod_sub_status(struct bt_mesh_model *model, mod_id = net_buf_simple_pull_le16(buf); - param = cli->op_param; if (param->elem_addr != elem_addr || param->mod_id != mod_id || (param->expect_sub && *param->expect_sub != sub_addr) || param->cid != cid) { @@ -609,39 +592,43 @@ static void mod_sub_status(struct bt_mesh_model *model, *param->status = status; } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } static void mod_sub_list(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + struct mod_member_list_param *param; + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_MOD_SUB_LIST, ctx->addr)) { - BT_WARN("Unexpected Model Subscription List message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_LIST, ctx->addr, + (void **)¶m)) { return; } - mod_member_list_handle(ctx, buf, false); + mod_member_list_handle(ctx, buf, false, param); } static void mod_sub_list_vnd(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + struct mod_member_list_param *param; + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_MOD_SUB_LIST_VND, ctx->addr)) { - BT_WARN("Unexpected Model Subscription List Vendor message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_LIST_VND, ctx->addr, + (void **)¶m)) { return; } - mod_member_list_handle(ctx, buf, true); + mod_member_list_handle(ctx, buf, true,param); } struct hb_sub_param { @@ -659,13 +646,11 @@ static void hb_sub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_HEARTBEAT_SUB_STATUS, ctx->addr)) { - BT_WARN("Unexpected Heartbeat Subscription Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_HEARTBEAT_SUB_STATUS, ctx->addr, + (void **)¶m)) { return; } - param = cli->op_param; - *param->status = net_buf_simple_pull_u8(buf); param->sub->src = net_buf_simple_pull_le16(buf); @@ -675,7 +660,7 @@ static void hb_sub_status(struct bt_mesh_model *model, param->sub->min = net_buf_simple_pull_u8(buf); param->sub->max = net_buf_simple_pull_u8(buf); - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } struct hb_pub_param { @@ -693,13 +678,11 @@ static void hb_pub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cli_response_check(OP_HEARTBEAT_PUB_STATUS, ctx->addr)) { - BT_WARN("Unexpected Heartbeat Publication Status message"); + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_HEARTBEAT_PUB_STATUS, ctx->addr, + (void **)¶m)) { return; } - param = cli->op_param; - *param->status = net_buf_simple_pull_u8(buf); if (param->pub) { @@ -711,7 +694,7 @@ static void hb_pub_status(struct bt_mesh_model *model, param->pub->net_idx = net_buf_simple_pull_u8(buf); } - k_sem_give(&cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); } const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { @@ -762,7 +745,7 @@ static int cfg_cli_init(struct bt_mesh_model *model) */ model->keys[0] = BT_MESH_KEY_DEV_ANY; - k_sem_init(&cli->op_sync, 0, 1); + bt_mesh_msg_ack_ctx_init(&cli->ack_ctx); return 0; } @@ -778,34 +761,7 @@ static int cli_prepare(void *param, uint32_t op, uint16_t addr) return -EINVAL; } - if (cli->op_pending) { - BT_WARN("Another synchronous operation pending"); - return -EBUSY; - } - - cli->op_param = param; - cli->op_pending = op; - cli->op_addr = addr; - - return 0; -} - -static void cli_reset(void) -{ - cli->op_pending = 0; - cli->op_param = NULL; - cli->op_addr = BT_MESH_ADDR_UNASSIGNED; -} - -static int cli_wait(void) -{ - int err; - - err = k_sem_take(&cli->op_sync, msg_timeout); - - cli_reset(); - - return err; + return bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, op, addr, param); } int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, @@ -835,11 +791,11 @@ int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -867,11 +823,11 @@ static int get_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t r err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -900,11 +856,11 @@ static int set_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t r err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -999,11 +955,11 @@ int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1037,11 +993,11 @@ int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1075,16 +1031,16 @@ int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_id err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1116,12 +1072,12 @@ int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); return err; } os_mbuf_free_chain(msg); - return cli_wait(); + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); } int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr, @@ -1151,16 +1107,16 @@ int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1196,16 +1152,16 @@ int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_id err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1237,16 +1193,16 @@ int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status) err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); if (err) { @@ -1287,12 +1243,12 @@ int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_id if (err) { BT_ERR("model_send() failed (err %d)", err); os_mbuf_free_chain(msg); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); return err; } os_mbuf_free_chain(msg); - return cli_wait(); + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); } int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr, @@ -1325,18 +1281,18 @@ int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr, if (err) { BT_ERR("model_send() failed (err %d)", err); os_mbuf_free_chain(msg); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); return err; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); os_mbuf_free_chain(msg); return 0; } os_mbuf_free_chain(msg); - return cli_wait(); + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); } static int mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, @@ -1377,16 +1333,16 @@ static int mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1449,12 +1405,12 @@ static int mod_app_unbind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); err = 0; goto done; } @@ -1464,7 +1420,7 @@ static int mod_app_unbind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, if (err) { return err; } else { - return cli_wait(); + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); } } @@ -1531,11 +1487,11 @@ static int mod_member_list_get(uint32_t op, uint32_t expect_op, uint16_t net_idx err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1600,17 +1556,17 @@ static int mod_sub(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_a err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); err = 0; goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1715,16 +1671,16 @@ static int mod_sub_va(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t ele err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1852,16 +1808,16 @@ static int mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1929,16 +1885,16 @@ static int mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -1992,16 +1948,16 @@ int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -2033,16 +1989,16 @@ int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -2079,16 +2035,16 @@ int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -2120,16 +2076,16 @@ int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr, err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } if (!status) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; diff --git a/nimble/host/mesh/src/health_cli.c b/nimble/host/mesh/src/health_cli.c index 76d639c5f3..c6057c5643 100644 --- a/nimble/host/mesh/src/health_cli.c +++ b/nimble/host/mesh/src/health_cli.c @@ -45,13 +45,11 @@ static void health_fault_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (health_cli->op_pending != OP_HEALTH_FAULT_STATUS) { - BT_WARN("Unexpected Health Fault Status message"); + if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_HEALTH_FAULT_STATUS, ctx->addr, + (void **)¶m)) { return; } - param = health_cli->op_param; - test_id = net_buf_simple_pull_u8(buf); if (param->expect_test_id && test_id != *param->expect_test_id) { BT_WARN("Health fault with unexpected Test ID"); @@ -76,7 +74,7 @@ static void health_fault_status(struct bt_mesh_model *model, memcpy(param->faults, buf->om_data, *param->fault_count); - k_sem_give(&health_cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); } static void health_current_status(struct bt_mesh_model *model, @@ -119,16 +117,14 @@ static void health_period_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (health_cli->op_pending != OP_HEALTH_PERIOD_STATUS) { - BT_WARN("Unexpected Health Period Status message"); + if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_HEALTH_PERIOD_STATUS, ctx->addr, + (void **)¶m)) { return; } - param = health_cli->op_param; - *param->divisor = net_buf_simple_pull_u8(buf); - k_sem_give(&health_cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); } struct health_attention_param { @@ -145,18 +141,16 @@ static void health_attention_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (health_cli->op_pending != OP_ATTENTION_STATUS) { - BT_WARN("Unexpected Health Attention Status message"); + if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_ATTENTION_STATUS, ctx->addr, + (void **)¶m)) { return; } - param = health_cli->op_param; - if (param->attention) { *param->attention = net_buf_simple_pull_u8(buf); } - k_sem_give(&health_cli->op_sync); + bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); } const struct bt_mesh_model_op bt_mesh_health_cli_op[] = { @@ -167,39 +161,14 @@ const struct bt_mesh_model_op bt_mesh_health_cli_op[] = { BT_MESH_MODEL_OP_END, }; -static int cli_prepare(void *param, uint32_t op) +static int cli_prepare(void *param, uint32_t op, uint16_t addr) { if (!health_cli) { BT_ERR("No available Health Client context!"); return -EINVAL; } - if (health_cli->op_pending) { - BT_WARN("Another synchronous operation pending"); - return -EBUSY; - } - - health_cli->op_param = param; - health_cli->op_pending = op; - - return 0; -} - -static void cli_reset(void) -{ - health_cli->op_pending = 0; - health_cli->op_param = NULL; -} - -static int cli_wait(void) -{ - int err; - - err = k_sem_take(&health_cli->op_sync, msg_timeout); - - cli_reset(); - - return err; + return bt_mesh_msg_ack_ctx_prepare(&health_cli->ack_ctx, op, addr, param); } int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention) @@ -215,7 +184,7 @@ int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *atten }; int err; - err = cli_prepare(¶m, OP_ATTENTION_STATUS); + err = cli_prepare(¶m, OP_ATTENTION_STATUS, addr); if (err) { goto done; } @@ -225,11 +194,11 @@ int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *atten err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -249,7 +218,7 @@ int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attent }; int err; - err = cli_prepare(¶m, OP_ATTENTION_STATUS); + err = cli_prepare(¶m, OP_ATTENTION_STATUS, addr); if (err) { goto done; } @@ -265,16 +234,16 @@ int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attent err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } if (!updated_attention) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -293,7 +262,7 @@ int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor) }; int err; - err = cli_prepare(¶m, OP_HEALTH_PERIOD_STATUS); + err = cli_prepare(¶m, OP_HEALTH_PERIOD_STATUS, addr); if (err) { goto done; } @@ -303,11 +272,11 @@ int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor) err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -327,7 +296,7 @@ int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor, }; int err; - err = cli_prepare(¶m, OP_HEALTH_PERIOD_STATUS); + err = cli_prepare(¶m, OP_HEALTH_PERIOD_STATUS, addr); if (err) { goto done; } @@ -343,16 +312,16 @@ int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor, err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } if (!updated_divisor) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -376,7 +345,7 @@ int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid, }; int err; - err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS); + err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS, addr); if (err) { goto done; } @@ -393,16 +362,16 @@ int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid, err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } if (!faults) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -426,7 +395,7 @@ int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid, }; int err; - err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS); + err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS, addr); if (err) { goto done; } @@ -442,16 +411,16 @@ int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid, err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } if (!test_id) { - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -475,7 +444,7 @@ int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid, }; int err; - err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS); + err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS, addr); if (err) { goto done; } @@ -486,11 +455,11 @@ int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid, err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); if (err) { BT_ERR("model_send() failed (err %d)", err); - cli_reset(); + bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); goto done; } - err = cli_wait(); + err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); done: os_mbuf_free_chain(msg); return err; @@ -533,13 +502,12 @@ static int health_cli_init(struct bt_mesh_model *model) cli = model->user_data; cli->model = model; - k_sem_init(&cli->op_sync, 0, 1); - /* Set the default health client pointer */ if (!health_cli) { health_cli = cli; } + bt_mesh_msg_ack_ctx_init(&health_cli->ack_ctx); return 0; } diff --git a/nimble/host/mesh/src/msg.c b/nimble/host/mesh/src/msg.c new file mode 100644 index 0000000000..853a0f43dc --- /dev/null +++ b/nimble/host/mesh/src/msg.c @@ -0,0 +1,83 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mesh/mesh.h" + +#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ACCESS) +#define LOG_MODULE_NAME bt_mesh_msg + +void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode) +{ + net_buf_simple_init(msg, 0); + + switch (BT_MESH_MODEL_OP_LEN(opcode)) { + case 1: + net_buf_simple_add_u8(msg, opcode); + break; + case 2: + net_buf_simple_add_be16(msg, opcode); + break; + case 3: + net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff)); + /* Using LE for the CID since the model layer is defined as + * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3 + * will declare the opcode in this way. + */ + net_buf_simple_add_le16(msg, opcode & 0xffff); + break; + default: + BT_WARN("Unknown opcode format"); + break; + } +} + +void bt_mesh_msg_ack_ctx_clear(struct bt_mesh_msg_ack_ctx *ack) +{ + ack->op = 0U; + ack->user_data = NULL; + ack->dst = BT_MESH_ADDR_UNASSIGNED; +} + +int bt_mesh_msg_ack_ctx_prepare(struct bt_mesh_msg_ack_ctx *ack, + uint32_t op, uint16_t dst, void *user_data) +{ + if (ack->op) { + BT_WARN("Another synchronous operation pending"); + return -EBUSY; + } + + ack->op = op; + ack->user_data = user_data; + ack->dst = dst; + + return 0; +} + +int bt_mesh_msg_ack_ctx_wait(struct bt_mesh_msg_ack_ctx *ack, int32_t timeout) +{ + int err; + + err = k_sem_take(&ack->sem, timeout); + bt_mesh_msg_ack_ctx_clear(ack); + + return err; + } + +bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, + uint32_t op, uint16_t addr, void **user_data) +{ + if (ack->op != op || (BT_MESH_ADDR_IS_UNICAST(ack->dst) && ack->dst != addr)) { + return false; + } + + if (user_data != NULL) { + *user_data = ack->user_data; + } + + return true; +} \ No newline at end of file From f173ca2cc71d83da8659ac9b3dc3c7c442bc63f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 14:55:28 +0200 Subject: [PATCH 154/306] host/mesh: Rework publication timer Periodic publication would previously build and send the first publication inside the bt_mesh_model_pub() function, before cancelling and rescheduling the next publication. The timer handler would only handle retransmissions, and would abandon the rest of the publication event if one of the packets failed to send. This design has three issues: - If the initial timer cancel fails, the publication would interfer with the periodic publication management, which might skip an event or send too many packets. - If any of the messages fail to publish, the full publication event would be abandoned. This is not predictable or expected from the API. - bt_mesh_model_pub() required 384 bytes of stack to build the message, which has to be factored into all calling threads. This patch moves all transmission into the publication timer by replacing k_work_cancel with a single k_work_reschedule(K_NO_WAIT). It also changes the error recovery behavior to attempt to finish the full publication event even if some of the transmissions fail. This is port of 820cfc52adc728a727a33a182a2d360af86ecdd9 --- nimble/host/mesh/include/mesh/access.h | 12 +- nimble/host/mesh/src/access.c | 176 ++++++++++--------------- nimble/host/mesh/src/cfg_srv.c | 8 +- nimble/host/mesh/src/mesh.c | 8 +- 4 files changed, 88 insertions(+), 116 deletions(-) diff --git a/nimble/host/mesh/include/mesh/access.h b/nimble/host/mesh/include/mesh/access.h index 0efee414f8..c3f36f43a0 100644 --- a/nimble/host/mesh/include/mesh/access.h +++ b/nimble/host/mesh/include/mesh/access.h @@ -310,17 +310,17 @@ struct bt_mesh_model_pub { /** The model the context belongs to. Initialized by the stack. */ struct bt_mesh_model *mod; - uint16_t addr; /**< Publish Address. */ - uint16_t key; /**< Publish AppKey Index. */ + uint16_t addr; /**< Publish Address. */ + uint16_t key:12, /**< Publish AppKey Index. */ + cred:1, /**< Friendship Credentials Flag. */ + send_rel:1, /**< Force reliable sending (segment acks) */ + fast_period:1; /**< Use FastPeriodDivisor */ uint8_t ttl; /**< Publish Time to Live. */ uint8_t retransmit; /**< Retransmit Count & Interval Steps. */ uint8_t period; /**< Publish Period. */ uint8_t period_div:4, /**< Divisor for the Period. */ - cred:1, /**< Friendship Credentials Flag. */ - send_rel:1, - fast_period:1,/**< Use FastPeriodDivisor */ - count:3; /**< Retransmissions left. */ + count:4; uint32_t period_start; /**< Start of the current period. */ diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 7211777d11..1c34b2ec2a 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -148,7 +148,7 @@ static void publish_sent(int err, void *user_data) if (delay) { BT_DBG("Publishing next time in %dms", (int) delay); - k_work_reschedule(&mod->pub->timer, delay); + k_work_schedule(&mod->pub->timer, delay); } } @@ -159,6 +159,7 @@ static void publish_start(uint16_t duration, int err, void *user_data) if (err) { BT_ERR("Failed to publish: err %d", err); + publish_sent(err, user_data); return; } @@ -173,7 +174,7 @@ static const struct bt_mesh_send_cb pub_sent_cb = { .end = publish_sent, }; -static int publish_retransmit(struct bt_mesh_model *mod) +static int publish_transmit(struct bt_mesh_model *mod) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_model_pub *pub = mod->pub; @@ -192,67 +193,68 @@ static int publish_retransmit(struct bt_mesh_model *mod) net_buf_simple_init(sdu, 0); net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len); - pub->count--; - err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod); os_mbuf_free_chain(sdu); return err; } -static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub) +static int pub_period_start(struct bt_mesh_model_pub *pub) { - /* Cancel all retransmits for this publish attempt */ - pub->count = 0U; - /* Make sure the publish timer gets reset */ - publish_sent(err, pub->mod); + int err; + + pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit); + + if (!pub->update) { + return 0; + } + + err = pub->update(pub->mod); + if (err) { + /* Skip this publish attempt. */ + BT_DBG("Update failed, skipping publish (err: %d)", err); + pub->count = 0; + pub->period_start = k_uptime_get_32(); + publish_sent(err, pub); + return err; + } + + return 0; } static void mod_publish(struct ble_npl_event *work) { struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work); - int32_t period_ms; int err; - BT_DBG(""); + if (pub->addr == BT_MESH_ADDR_UNASSIGNED || + atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) { + /* Publication is no longer active, but the cancellation of the + * delayed work failed. Abandon recurring timer. + */ + return; + } - period_ms = bt_mesh_model_pub_period_get(pub->mod); - BT_DBG("period %u ms", (unsigned) period_ms); + BT_DBG(""); if (pub->count) { - err = publish_retransmit(pub->mod); + pub->count--; + } else { + /* First publication in this period */ + err = pub_period_start(pub); if (err) { - BT_ERR("Failed to retransmit (err %d)", err); - - pub->count = 0; - - /* Continue with normal publication */ - if (period_ms) { - k_work_reschedule(&pub->timer, period_ms); - } + return; } - - return; } - if (!period_ms) { - return; - } - - __ASSERT_NO_MSG(pub->update != NULL); - - err = pub->update(pub->mod); + err = publish_transmit(pub->mod); if (err) { - /* Cancel this publish attempt. */ - BT_DBG("Update failed, skipping publish (err: %d)", err); - pub->period_start = k_uptime_get_32(); - publish_retransmit_end(err, pub); - return; - } + BT_ERR("Failed to publish (err %d)", err); + if (pub->count == BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit)) { + pub->period_start = k_uptime_get_32(); + } - err = bt_mesh_model_publish(pub->mod); - if (err) { - BT_ERR("Publishing failed (err %d)", err); + publish_sent(err, pub->mod); } } @@ -631,13 +633,17 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) } } -static int model_send(struct bt_mesh_model *model, - struct bt_mesh_net_tx *tx, bool implicit_bind, - struct os_mbuf *msg, - const struct bt_mesh_send_cb *cb, void *cb_data) +int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *msg, + const struct bt_mesh_send_cb *cb, void *cb_data) { - BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->ctx->net_idx, - tx->ctx->app_idx, tx->ctx->addr); + struct bt_mesh_net_tx tx = { + .ctx = ctx, + .src = bt_mesh_model_elem(model)->addr, + }; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx.ctx->net_idx, + tx.ctx->app_idx, tx.ctx->addr); BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len)); if (!bt_mesh_is_provisioned()) { @@ -645,95 +651,51 @@ static int model_send(struct bt_mesh_model *model, return -EAGAIN; } - if (net_buf_simple_tailroom(msg) < 4) { - BT_ERR("Not enough tailroom for TransMIC"); + if (!model_has_key(model, tx.ctx->app_idx)) { + BT_ERR("Model not bound to AppKey 0x%04x", tx.ctx->app_idx); return -EINVAL; } - if (msg->om_len > BT_MESH_TX_SDU_MAX - 4) { - BT_ERR("Too big message"); - return -EMSGSIZE; - } - - if (!implicit_bind && !model_has_key(model, tx->ctx->app_idx)) { - BT_ERR("Model not bound to AppKey 0x%04x", tx->ctx->app_idx); - return -EINVAL; - } - - return bt_mesh_trans_send(tx, msg, cb, cb_data); -} - -int bt_mesh_model_send(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *msg, - const struct bt_mesh_send_cb *cb, void *cb_data) -{ - struct bt_mesh_net_tx tx = { - .ctx = ctx, - .src = bt_mesh_model_elem(model)->addr, - }; - - return model_send(model, &tx, false, msg, cb, cb_data); + return bt_mesh_trans_send(&tx, msg, cb, cb_data); } int bt_mesh_model_publish(struct bt_mesh_model *model) { - int err; - struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_model_pub *pub = model->pub; if (!pub) { - err = -ENOTSUP; - goto done; + return -ENOTSUP; } - struct bt_mesh_msg_ctx ctx = { - .addr = pub->addr, - .send_ttl = pub->ttl, - .send_rel = pub->send_rel, - .app_idx = pub->key, - }; - struct bt_mesh_net_tx tx = { - .ctx = &ctx, - .src = bt_mesh_model_elem(model)->addr, - }; - BT_DBG(""); if (pub->addr == BT_MESH_ADDR_UNASSIGNED) { - err = -EADDRNOTAVAIL; - goto done; + return -EADDRNOTAVAIL; } - if (pub->msg->om_len + 4 > BT_MESH_TX_SDU_MAX) { + if (!pub->msg || !pub->msg->om_len) { + BT_ERR("No publication message"); + return -EINVAL; + } + + if (pub->msg->om_len + BT_MESH_MIC_SHORT > BT_MESH_TX_SDU_MAX) { BT_ERR("Message does not fit maximum SDU size"); - err = -EMSGSIZE; - goto done; + return -EMSGSIZE; } if (pub->count) { BT_WARN("Clearing publish retransmit timer"); - k_work_cancel_delayable(&pub->timer); } - net_buf_simple_init(sdu, 0); - net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len); - - tx.friend_cred = pub->cred; - - pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit); + /* Account for initial transmission */ + pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit) + 1; BT_DBG("Publish Retransmit Count %u Interval %ums", pub->count, BT_MESH_PUB_TRANSMIT_INT(pub->retransmit)); - err = model_send(model, &tx, true, sdu, &pub_sent_cb, model); - if (err) { - publish_retransmit_end(err, pub); - } + k_work_reschedule(&pub->timer, K_NO_WAIT); -done: - os_mbuf_free_chain(sdu); - return err; + return 0; } struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, @@ -1225,7 +1187,7 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, if (ms > 0) { BT_DBG("Starting publish timer (period %u ms)", ms); - k_work_reschedule(&mod->pub->timer, K_MSEC(ms)); + k_work_schedule(&mod->pub->timer, K_MSEC(ms)); } } diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 919c26a94a..158970c250 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -200,7 +200,10 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, model->pub->count = 0; if (model->pub->update) { - k_work_cancel_delayable(&model->pub->timer); + /* If this fails, the timer will check pub->addr and + * exit without transmitting. + */ + (void)k_work_cancel_delayable(&model->pub->timer); } if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { @@ -240,6 +243,9 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, if (period_ms > 0) { k_work_reschedule(&model->pub->timer, period_ms); } else { + /* If this fails, publication will stop after the + * ongoing set of retransmits. + */ k_work_cancel_delayable(&model->pub->timer); } } diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index a9bdb3154c..ae01888351 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -240,7 +240,10 @@ static void model_suspend(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, { if (mod->pub && mod->pub->update) { mod->pub->count = 0; - k_work_cancel_delayable(&mod->pub->timer); + /* If this fails, the work handler will check the suspend call + * and exit without transmitting. + */ + (void)k_work_cancel_delayable(&mod->pub->timer); } } @@ -281,7 +284,8 @@ static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, int32_t period_ms = bt_mesh_model_pub_period_get(mod); if (period_ms) { - k_work_reschedule(&mod->pub->timer, period_ms); + k_work_reschedule(&mod->pub->timer, + K_MSEC(period_ms)); } } } From a24783923040895d29c3f2b4f5d57959c7ffaf11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 14:57:44 +0200 Subject: [PATCH 155/306] host/mesh: Transport length checks should account for MIC The Transport layer would previously rely on the access layer to check whether there's room for the full message and a MIC in the available buffer space, and its own checks would ignore the MIC. This should be handled by the Transport layer checks, so the access layer doesn't have to. This is port of 5c6df442ff1dcbeaf4115f866a10a91a7f97225f --- nimble/host/mesh/src/transport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 643606349c..4d528bf941 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -630,12 +630,12 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg, return -EINVAL; } - if (msg->om_len > BT_MESH_TX_SDU_MAX) { - BT_ERR("Not enough segment buffers for length %u", msg->om_len); + if (msg->om_len > BT_MESH_TX_SDU_MAX - BT_MESH_MIC_SHORT) { + BT_ERR("Message too big: %u", msg->om_len); return -EMSGSIZE; } - if (net_buf_simple_tailroom(msg) < 4) { + if (net_buf_simple_tailroom(msg) < BT_MESH_MIC_SHORT) { BT_ERR("Insufficient tailroom for Transport MIC"); return -EINVAL; } From 92b86e8404b1ee5bcf6b25dd5306a07e86758010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 14:59:29 +0200 Subject: [PATCH 156/306] host/mesh: Report configured LPNTimeout in cfg_srv Changes lpn_timeout_get behavior in the config server to report the configured LPN timeout, instead of the currently remaining timeout time. According to the Bluetooth Mesh Profile specification, section 4.2.21, the PollTimeout list is a list of the PollTimeout timer values, and according to table 4.32 in this section, values 1-9 are prohibited. Although this is not explicitly stated, this indicates that the PollTimeout value is the configured poll timeout time - not the time remaining until the timeout value expires. This patch changes the implementation to reflect this. This is port of bf942bdf9abb0d7bed83f6297ccb79d443e85d69 --- nimble/host/mesh/src/cfg_srv.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 158970c250..35a00bd9e5 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -2106,8 +2106,8 @@ static void lpn_timeout_get(struct bt_mesh_model *model, { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_STATUS, 5); struct bt_mesh_friend *frnd; + int32_t timeout_steps; uint16_t lpn_addr; - int32_t timeout; lpn_addr = net_buf_simple_pull_le16(buf); @@ -2124,21 +2124,21 @@ static void lpn_timeout_get(struct bt_mesh_model *model, net_buf_simple_add_le16(msg, lpn_addr); if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { - timeout = 0; + timeout_steps = 0; goto send_rsp; } frnd = bt_mesh_friend_find(BT_MESH_KEY_ANY, lpn_addr, true, true); if (!frnd) { - timeout = 0; + timeout_steps = 0; goto send_rsp; } - timeout = k_ticks_to_ms_floor32( - k_work_delayable_remaining_get(&frnd->timer)) / 100; + /* PollTimeout should be reported in steps of 100ms. */ + timeout_steps = frnd->poll_to / 100; send_rsp: - net_buf_simple_add_le24(msg, timeout); + net_buf_simple_add_le24(msg, timeout_steps); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send LPN PollTimeout Status"); From a1faca303de159e0c2b9a1d26598ce3b23f27a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 15:22:09 +0200 Subject: [PATCH 157/306] host/mesh: Convert beacon timer to delayable work Moves the beacon_enabled check in the beacon work handler to check the beacon flag before sending anything, in case a cancel call fails. This is port of 286d9c22cd96121c2bbef437fee6212e84aacb99 --- nimble/host/mesh/src/beacon.c | 54 +++++++++++++++++------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/nimble/host/mesh/src/beacon.c b/nimble/host/mesh/src/beacon.c index d7be9c5e1c..2b678f9008 100644 --- a/nimble/host/mesh/src/beacon.c +++ b/nimble/host/mesh/src/beacon.c @@ -228,33 +228,30 @@ static void update_beacon_observation(void) static void beacon_send(struct ble_npl_event *work) { - /* Don't send anything if we have an active provisioning link */ - if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && bt_mesh_prov_active()) { - k_work_reschedule(&beacon_timer, - K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT))); - return; - } BT_DBG(""); if (bt_mesh_is_provisioned()) { + if (!bt_mesh_beacon_enabled() && + !atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { + return; + } + update_beacon_observation(); (void)bt_mesh_subnet_find(secure_beacon_send, NULL); - /* Only resubmit if beaconing is still enabled */ - if (bt_mesh_beacon_enabled() || - atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { - k_work_reschedule(&beacon_timer, - PROVISIONED_INTERVAL); - } + k_work_schedule(&beacon_timer, PROVISIONED_INTERVAL); return; } if (IS_ENABLED(BLE_MESH_PB_ADV)) { - unprovisioned_beacon_send(); - k_work_reschedule(&beacon_timer, - K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT))); + /* Don't send anything if we have an active provisioning link */ + if (!bt_mesh_prov_active()) { + unprovisioned_beacon_send(); + } + + k_work_schedule(&beacon_timer, K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT))); } } @@ -426,7 +423,7 @@ static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) void bt_mesh_beacon_init(void) { - if (!bt_mesh_subnet_cb_list[1]) { + if (!bt_mesh_subnet_cb_list[1]) { bt_mesh_subnet_cb_list[1] = subnet_evt; } @@ -437,11 +434,16 @@ void bt_mesh_beacon_ivu_initiator(bool enable) { atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable); - if (enable) { - k_work_reschedule(&beacon_timer, K_NO_WAIT); - } else if (!bt_mesh_beacon_enabled()) { - k_work_cancel_delayable(&beacon_timer); - } + /* Fire the beacon handler straight away if it's not already pending - + * in which case we'll fire according to the ongoing periodic sending. + * If beacons are disabled, the handler will exit early. + * + * An alternative solution would be to check whether beacons are enabled + * here, and cancel if not. As the cancel operation may fail, we would + * still have to implement an early exit mechanism, so we might as well + * just use this every time. + */ + k_work_schedule(&beacon_timer, K_NO_WAIT); } static void subnet_beacon_enable(struct bt_mesh_subnet *sub) @@ -454,19 +456,17 @@ static void subnet_beacon_enable(struct bt_mesh_subnet *sub) void bt_mesh_beacon_enable(void) { - if (!bt_mesh_is_provisioned()) { - k_work_reschedule(&beacon_timer, K_NO_WAIT); - return; + if (bt_mesh_is_provisioned()) { + bt_mesh_subnet_foreach(subnet_beacon_enable); } - bt_mesh_subnet_foreach(subnet_beacon_enable); - k_work_reschedule(&beacon_timer, K_NO_WAIT); } void bt_mesh_beacon_disable(void) { if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { - k_work_cancel_delayable(&beacon_timer); + /* If this fails, we'll do an early exit in the work handler. */ + (void)k_work_cancel_delayable(&beacon_timer); } } From f715ad64dadca9916bd6603d5d48e3bed161d292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 7 Oct 2021 15:26:28 +0200 Subject: [PATCH 158/306] host/mesh: move lpn logic for msg_received inside lpn.c The Transport layer implements some checks surrounding the lpn_msg_received call, with an accompanying comment that explains the logic. Move this inside the msg_received call instead. This is port of 777718ea6e3e0f59c61f404285bb75960bf3af96 --- nimble/host/mesh/src/lpn.c | 8 ++++++++ nimble/host/mesh/src/lpn.h | 9 --------- nimble/host/mesh/src/transport.c | 16 ++-------------- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/nimble/host/mesh/src/lpn.c b/nimble/host/mesh/src/lpn.c index 4c6c708ca2..ad6cfe4d25 100644 --- a/nimble/host/mesh/src/lpn.c +++ b/nimble/host/mesh/src/lpn.c @@ -501,6 +501,14 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) return; } + /* If the message was a Friend control message, it's possible that a + * Poll was already queued for sending. In this case, we're already in + * a different state. + */ + if (lpn->state != BT_MESH_LPN_WAIT_UPDATE) { + return; + } + if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) { BT_WARN("Unexpected message withouth a preceding Poll"); return; diff --git a/nimble/host/mesh/src/lpn.h b/nimble/host/mesh/src/lpn.h index 90de2ca086..cb2e1f2fef 100644 --- a/nimble/host/mesh/src/lpn.h +++ b/nimble/host/mesh/src/lpn.h @@ -47,15 +47,6 @@ static inline bool bt_mesh_lpn_waiting_update(void) #endif } -static inline bool bt_mesh_lpn_timer(void) -{ -#if MYNEWT_VAL(BLE_MESH_LOW_POWER) && MYNEWT_VAL(BLE_MESH_LPN_AUTO) - return (bt_mesh.lpn.state == BT_MESH_LPN_TIMER); -#else - return false; -#endif -} - void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx); void bt_mesh_lpn_group_add(uint16_t group); diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index 4d528bf941..aae72bf378 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -1586,20 +1586,8 @@ int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx) err = trans_unseg(buf, rx, &seq_auth); } - /* Notify LPN state machine so a Friend Poll will be sent. If the - * message was a Friend Update it's possible that a Poll was already - * queued for sending, however that's fine since then the - * bt_mesh_lpn_waiting_update() function will return false: - * we still need to go through the actual sending to the bearer and - * wait for ReceiveDelay before transitioning to WAIT_UPDATE state. - * Another situation where we want to notify the LPN state machine - * is if it's configured to use an automatic Friendship establishment - * timer, in which case we want to reset the timer at this point. - * - */ - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && - (bt_mesh_lpn_timer() || - (bt_mesh_lpn_established() && bt_mesh_lpn_waiting_update()))) { + /* Notify LPN state machine so a Friend Poll will be sent. */ + if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { bt_mesh_lpn_msg_received(rx); } From ceefdcb8a9c8c596b804d73b85179e36dfdb2979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 07:56:34 +0200 Subject: [PATCH 159/306] hoat/mesh: Provisioning output count number should be at least 1 When selecting a random count for blink, beep or vibrate, the Bluetooth Mesh Profile Specification v1.0.1, section 5.4.2.4 states: "the device shall select a random integer between 0 and 10 to the power of the Authentication Size exclusive". This means that if size is 1, the integer should be in the range 1-9, while the implementation chose an integer in the range 0-9. Reduce the range and add 1 to the num to correct this for these actions. This is port of 3656f7f60972dc03aa00071d21028f7b582e7765 --- nimble/host/mesh/src/prov.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c index 170fc1d099..d44d8ec030 100644 --- a/nimble/host/mesh/src/prov.c +++ b/nimble/host/mesh/src/prov.c @@ -161,7 +161,19 @@ int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size) uint32_t num; bt_rand(&num, sizeof(num)); - num %= div[size - 1]; + + if (output == BT_MESH_BLINK || + output == BT_MESH_BEEP || + output == BT_MESH_VIBRATE) { + /* According to the Bluetooth Mesh Profile + * Specification Section 5.4.2.4, blink, beep + * and vibrate should be a random integer + * between 0 and 10^size, *exclusive*: + */ + num = (num % (div[size - 1] - 1)) + 1; + } else { + num %= div[size - 1]; + } sys_put_be32(num, &bt_mesh_prov_link.auth[12]); memset(bt_mesh_prov_link.auth, 0, 12); From 6f1e5f23860bd6dfafcab3310e611d96a5a4604b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 08:00:30 +0200 Subject: [PATCH 160/306] host/mesh: Add friend_is_allocated utility Friend structure allocaction logic is implemented over and over throughout the friend module. Move it into a static utility function for readability. This is port of 0f5b5f74acbfefaee23b5172da2c1aa0807553d0 --- nimble/host/mesh/src/friend.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 402930f9f8..a1662a3179 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -72,6 +72,11 @@ static struct bt_mesh_adv *adv_alloc(int id) return &adv_pool[id].adv; } +static bool friend_is_allocated(const struct bt_mesh_friend *frnd) +{ + return frnd->subnet != NULL; +} + static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr) { if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) { @@ -91,7 +96,7 @@ struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr, for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - if (valid && !frnd->subnet) { + if (valid && !friend_is_allocated(frnd)) { continue; } @@ -193,7 +198,7 @@ void bt_mesh_friends_clear(void) for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - if (!frnd->subnet) { + if (!friend_is_allocated(frnd)) { continue; } @@ -212,7 +217,7 @@ void bt_mesh_friend_sec_update(uint16_t net_idx) for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - if (!frnd->subnet) { + if (!friend_is_allocated(frnd)) { continue; } @@ -548,7 +553,7 @@ static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, uint8_t md) struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*upd)); struct os_mbuf *buf; - __ASSERT_NO_MSG(frnd->subnet); + __ASSERT_NO_MSG(friend_is_allocated(frnd)); BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md); From dec5e2ccf500c51a2b79d6c747576e5dca55a41e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 08:10:12 +0200 Subject: [PATCH 161/306] host/mesh: Core delayable work updates Switch to the new API in friend, net and main. This is port of 38609d34e09dccd4998f55e97dbfa5bb90dfa635 --- nimble/host/mesh/src/friend.c | 17 ++++++++++++++--- nimble/host/mesh/src/net.c | 4 ++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index a1662a3179..13ce285d51 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -156,7 +156,7 @@ static void friend_clear(struct bt_mesh_friend *frnd) BT_DBG("LPN 0x%04x", frnd->lpn); - k_work_cancel_delayable(&frnd->timer); + (void)k_work_cancel_delayable(&frnd->timer); memset(frnd->cred, 0, sizeof(frnd->cred)); @@ -816,6 +816,11 @@ static void clear_timeout(struct ble_npl_event *work) struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work); uint32_t duration; + if (frnd->clear.frnd == BT_MESH_ADDR_UNASSIGNED) { + /* Failed cancelling timer, return early. */ + return; + } + BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd); duration = k_uptime_get_32() - frnd->clear.start; @@ -872,7 +877,8 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx, return 0; } - k_work_cancel_delayable(&frnd->clear.timer); + /* If this fails, the unassigned check will make the handler return early. */ + (void)k_work_cancel_delayable(&frnd->clear.timer); frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED; return 0; @@ -1159,7 +1165,8 @@ static void buf_send_end(int err, void *user_data) } if (frnd->established) { - k_work_reschedule(&frnd->timer, frnd->poll_to); + /* Always restart poll timeout timer after sending */ + k_work_reschedule(&frnd->timer, K_MSEC(frnd->poll_to)); BT_DBG("Waiting %u ms for next poll", (unsigned) frnd->poll_to); } else { @@ -1211,6 +1218,10 @@ static void friend_timeout(struct ble_npl_event *work) uint8_t md; + if (!friend_is_allocated(frnd)) { + return; + } + __ASSERT_NO_MSG(frnd->pending_buf == 0); BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn, diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 4c102f7a8c..e8d3c471d4 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -856,6 +856,10 @@ void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi, static void ivu_refresh(struct ble_npl_event *work) { + if (!bt_mesh_is_provisioned()) { + return; + } + bt_mesh.ivu_duration = MIN(UINT8_MAX, bt_mesh.ivu_duration + BT_MESH_IVU_HOURS); From a5d34c82e42f8cf5d5516e64f314f36c73b4b43f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 08:22:51 +0200 Subject: [PATCH 162/306] host/mesh: Mesh: pb_adv: update delayable work Switch to the new API. Consolidates reliable sending logic for the first transmission and the retransmit into one. Adds check for link active in protocol timeout. This is port of 45e5914ce90bdb424aa16c5e87cbe1a0f16c5b82 --- nimble/host/mesh/src/pb_adv.c | 43 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/nimble/host/mesh/src/pb_adv.c b/nimble/host/mesh/src/pb_adv.c index 1fa4c8e996..eed19eacc9 100644 --- a/nimble/host/mesh/src/pb_adv.c +++ b/nimble/host/mesh/src/pb_adv.c @@ -181,7 +181,12 @@ static void prov_clear_tx(void) { BT_DBG(""); - k_work_cancel_delayable(&link.tx.retransmit); + /* If this fails, the work handler will not find any buffers to send, + * and return without rescheduling. The work handler also checks the + * LINK_ACTIVE flag, so if this call is part of reset_adv_link, it'll + * exit early. + */ + (void)k_work_cancel_delayable(&link.tx.retransmit); free_segments(); } @@ -191,7 +196,10 @@ static void reset_adv_link(void) BT_DBG(""); prov_clear_tx(); - k_work_cancel_delayable(&link.prot_timer); + /* If this fails, the work handler will exit early on the LINK_ACTIVE + * check. + */ + (void)k_work_cancel_delayable(&link.prot_timer); if (atomic_test_bit(link.flags, ADV_PROVISIONER)) { /* Clear everything except the retransmit and protocol timer @@ -279,6 +287,10 @@ static void prov_msg_recv(void) static void protocol_timeout(struct ble_npl_event *work) { + if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { + return; + } + BT_DBG(""); link.rx.seg = 0U; @@ -553,6 +565,12 @@ static void send_reliable(void) break; } + if (BT_MESH_ADV(buf)->busy) { + continue; + } + + BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); + if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) { bt_mesh_adv_send(buf, NULL, NULL); } else { @@ -564,7 +582,6 @@ static void send_reliable(void) static void prov_retransmit(struct ble_npl_event *work) { int32_t timeout_ms; - int i; BT_DBG(""); @@ -595,25 +612,7 @@ static void prov_retransmit(struct ble_npl_event *work) return; } - for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) { - struct os_mbuf *buf = link.tx.buf[i]; - - if (!buf) { - break; - } - - if (BT_MESH_ADV(buf)->busy) { - continue; - } - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) { - bt_mesh_adv_send(buf, NULL, NULL); - } else { - bt_mesh_adv_send(buf, &buf_sent_cb, NULL); - } - } + send_reliable(); } static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len, From ee0dc5e70d7cb0696bdf7f37f3741b54fa763b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 08:25:17 +0200 Subject: [PATCH 163/306] host/mesh: pb_gatt: update delayable work Switch to the new API. Adds a link check to the protocol timeout to ensure the link is still active. This is port of 3cba9613a43a7026104ba338666c6b61c41037e7 --- nimble/host/mesh/src/pb_gatt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/pb_gatt.c b/nimble/host/mesh/src/pb_gatt.c index c358e2e43e..bd119c15ef 100644 --- a/nimble/host/mesh/src/pb_gatt.c +++ b/nimble/host/mesh/src/pb_gatt.c @@ -36,7 +36,8 @@ static void reset_state(void) { link.conn_handle = BLE_HS_CONN_HANDLE_NONE; - k_work_cancel_delayable(&link.prot_timer); + /* If this fails, the protocol timeout handler will exit early. */ + (void)k_work_cancel_delayable(&link.prot_timer); link.rx.buf = bt_mesh_proxy_get_buf(); } @@ -54,6 +55,11 @@ static void link_closed(enum prov_bearer_link_status status) static void protocol_timeout(struct ble_npl_event *work) { + if (!link.conn_handle) { + /* Already disconnected */ + return; + } + BT_DBG("Protocol timeout"); link_closed(PROV_BEARER_LINK_STATUS_TIMEOUT); From 3918bd9e9cf135cab2ff173a584e80daa2f8497f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 08:30:39 +0200 Subject: [PATCH 164/306] host/mesh: proxy: update delayable work Switch to the new API. Adds check for a pending buffer in the SAR timeout handler. This is port of 1577fec8511d18778e39e0edb952cf468ff0735c --- nimble/host/mesh/src/proxy.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/proxy.c index 515d86e8c3..042c1f6c9b 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/proxy.c @@ -424,17 +424,21 @@ static void proxy_sar_timeout(struct ble_npl_event *work) { struct bt_mesh_proxy_client *client; int rc; - - BT_WARN("Proxy SAR timeout"); - client = ble_npl_event_get_arg(work); - assert(client != NULL); - if ((client->conn_handle != BLE_HS_CONN_HANDLE_NONE)) { - rc = ble_gap_terminate(client->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); + if (!client->conn_handle) { + return; } + + if (!client->buf->om_len) { + BT_DBG("No pending Proxy SAR message"); + return; + } + + BT_WARN("Proxy SAR timeout"); + rc = ble_gap_terminate(client->conn_handle, + BLE_ERR_REM_USER_CONN_TERM); + assert(rc == 0); } void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub) @@ -599,7 +603,10 @@ static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle, return -EINVAL; } - k_work_cancel_delayable(&client->sar_timer); + /* If this fails, the work handler exits early, as there's no + * active SAR buffer. + */ + (void)k_work_cancel_delayable(&client->sar_timer); net_buf_simple_add_mem(client->buf, data + 1, len - 1); proxy_complete_pdu(client); break; @@ -661,7 +668,10 @@ static void proxy_disconnected(uint16_t conn_handle, int reason) bt_mesh_pb_gatt_close(conn_handle); } - k_work_cancel_delayable(&client->sar_timer); + /* If this fails, the work handler exits early, as + * there's no active connection. + */ + (void)k_work_cancel_delayable(&client->sar_timer); client->conn_handle = BLE_HS_CONN_HANDLE_NONE; break; } From 5af4b9d4c48c800b8ce2da2595de37e08a3a57b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 08:40:47 +0200 Subject: [PATCH 165/306] host/mesh: transport: update delayable work Switch to the new API. Adds early exits for the ack and retransmit timers, and replaces a remaining_time() + submit() call with schedule(). This is port of 4e6cb116f87bb2ff0ece7d8f968adac4dd2c9b3d --- nimble/host/mesh/src/transport.c | 45 +++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index aae72bf378..b1d41dbf53 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -256,7 +256,8 @@ static void seg_tx_reset(struct seg_tx *tx) { int i; - k_work_cancel_delayable(&tx->retransmit); + /* If this call fails, the handler will exit early, as nack_count is 0. */ + (void)k_work_cancel_delayable(&tx->retransmit); tx->cb = NULL; tx->cb_data = NULL; @@ -318,7 +319,8 @@ static void schedule_retransmit(struct seg_tx *tx) * retransmit immediately, as we just freed up a tx buffer. */ k_work_reschedule(&tx->retransmit, - tx->seg_o ? 0 : K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx))); + tx->seg_o ? K_NO_WAIT : + K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx))); } static void seg_send_start(uint16_t duration, int err, void *user_data) @@ -440,7 +442,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx) end: if (!tx->seg_pending) { k_work_reschedule(&tx->retransmit, - SEG_RETRANSMIT_TIMEOUT(tx)); + K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx))); } tx->sending = 0U; @@ -860,8 +862,6 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, return -EINVAL; } - k_work_cancel_delayable(&tx->retransmit); - while ((bit = find_lsb_set(ack))) { if (tx->seg[bit - 1]) { BT_DBG("seg %u/%u acked", bit - 1, tx->seg_n); @@ -872,7 +872,11 @@ static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr, } if (tx->nack_count) { - seg_tx_send_unacked(tx); + /* According to the Bluetooth Mesh Profile specification, + * section 3.5.3.3, we should reset the retransmit timer and + * retransmit immediately when receiving a valid ack message: + */ + k_work_reschedule(&tx->retransmit, K_NO_WAIT); } else { BT_DBG("SDU TX complete"); seg_tx_complete(tx, 0); @@ -1094,7 +1098,10 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset) BT_DBG("rx %p", rx); - k_work_cancel_delayable(&rx->ack); + /* If this fails, the handler will exit early on the next execution, as + * it checks rx->in_use. + */ + (void)k_work_cancel_delayable(&rx->ack); if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && rx->obo && rx->block != BLOCK_COMPLETE(rx->seg_n)) { @@ -1131,6 +1138,16 @@ static void seg_ack(struct ble_npl_event *work) struct seg_rx *rx = ble_npl_event_get_arg(work); int32_t timeout; + if (!rx->in_use || rx->block == BLOCK_COMPLETE(rx->seg_n)) { + /* Cancellation of this timer may have failed. If it fails as + * part of seg_reset, in_use will be false. + * If it fails as part of the processing of a fully received + * SDU, the ack is already being sent from the receive handler, + * and the timer based ack sending can be ignored. + */ + return; + } + BT_DBG("rx %p", rx); if (k_uptime_get_32() - rx->last > K_SECONDS(60)) { @@ -1148,7 +1165,7 @@ static void seg_ack(struct ble_npl_event *work) rx->block, rx->obo); timeout = ack_timeout(rx); - k_work_reschedule(&rx->ack, K_MSEC(timeout)); + k_work_schedule(&rx->ack, K_MSEC(timeout)); } static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n) @@ -1453,11 +1470,10 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, /* Reset the Incomplete Timer */ rx->last = k_uptime_get_32(); - if (!k_work_delayable_remaining_get(&rx->ack) && - !bt_mesh_lpn_established()) { + if (!bt_mesh_lpn_established()) { int32_t timeout = ack_timeout(rx); - - k_work_reschedule(&rx->ack, K_MSEC(timeout)); + /* Should only start ack timer if it isn't running already: */ + k_work_schedule(&rx->ack, K_MSEC(timeout)); } /* Allocated segment here */ @@ -1494,7 +1510,10 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, *pdu_type = BT_MESH_FRIEND_PDU_COMPLETE; - k_work_cancel_delayable(&rx->ack); + /* If this fails, the work handler will either exit early because the + * block is fully received, or rx->in_use is false. + */ + (void)k_work_cancel_delayable(&rx->ack); send_ack(net_rx->sub, net_rx->ctx.recv_dst, net_rx->ctx.addr, net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo); From 7d0aa8d6e3f3cfb6f57a27c8356b423feeb52071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 08:43:37 +0200 Subject: [PATCH 166/306] host/mesh: Allow to be NODE when PROVISIONER is enabled When PROVISIONER and CDB is enabled then IUT couldn't be a NODE. This patch fixes this by not returning an error when CDB is not configured. This is useful especially in testing environment, when all the features are compiled in and we can choose role in runtime. This is port of b9c8d270ab642ae18c83aad66ab5e1d962de74d3 --- nimble/host/mesh/src/mesh.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index ae01888351..4ff992d53c 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -69,18 +69,12 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, * FIXME: * Should net_key and iv_index be over-ridden? */ - if (IS_ENABLED(BLE_MESH_CDB)) { + if (IS_ENABLED(CONFIG_BT_MESH_CDB) && + atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID)) { const struct bt_mesh_comp *comp; const struct bt_mesh_prov *prov; struct bt_mesh_cdb_node *node; - if (!atomic_test_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_VALID)) { - BT_ERR("No valid network"); - atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); - return -EINVAL; - } - comp = bt_mesh_comp_get(); if (comp == NULL) { BT_ERR("Failed to get node composition"); From 517f819191529f6ee25fd7f62a64d5a47b872b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 11:24:36 +0200 Subject: [PATCH 167/306] host/mesh: Add option to include bt name in scan rsp Sometimes it may be needed to know device name when proxy feature is enabled. This commit adds an option to include device name in scan response. This is port of a335c755a70fd279a221a24fa944ea21d231bad4 --- nimble/host/mesh/src/proxy.c | 71 +++++++++++++++++++++++++++++------- nimble/host/mesh/syscfg.yml | 6 +++ 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/proxy.c index 042c1f6c9b..44c3376a0e 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/proxy.c @@ -88,19 +88,27 @@ ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); #define CLIENT_BUF_SIZE 65 -static const struct ble_gap_adv_params slow_adv_param = { - .conn_mode = (BLE_GAP_CONN_MODE_UND), +#if MYNEWT_VAL(BLE_MESH_PROXY_USE_DEVICE_NAME) +#define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME +#else +#define ADV_OPT_USE_NAME 0 +#endif + +#define ADV_OPT_PROV \ + .conn_mode = (BLE_GAP_CONN_MODE_UND), \ .disc_mode = (BLE_GAP_DISC_MODE_GEN), - .itvl_min = BT_GAP_ADV_SLOW_INT_MIN, - .itvl_max = BT_GAP_ADV_SLOW_INT_MAX, -}; -static const struct ble_gap_adv_params fast_adv_param = { - .conn_mode = (BLE_GAP_CONN_MODE_UND), +#define ADV_OPT_PROXY \ + .conn_mode = (BLE_GAP_CONN_MODE_UND), \ .disc_mode = (BLE_GAP_DISC_MODE_GEN), - .itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, + +#define ADV_SLOW_INT \ + .itvl_min = BT_GAP_ADV_SLOW_INT_MIN, \ + .itvl_max = BT_GAP_ADV_SLOW_INT_MAX, + +#define ADV_FAST_INT \ + .itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, \ .itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, -}; static bool proxy_adv_enabled; @@ -1123,6 +1131,21 @@ static const struct bt_data net_id_ad[] = { static int node_id_adv(struct bt_mesh_subnet *sub) { + struct ble_gap_adv_params fast_adv_param = { + ADV_OPT_PROXY + ADV_FAST_INT + }; +#if ADV_OPT_USE_NAME + const char *name = CONFIG_BT_DEVICE_NAME; + size_t name_len = strlen(name); + struct bt_data sd = { + .type = BT_DATA_NAME_COMPLETE, + .data_len = name_len, + .data = (void *)name + }; +#else + struct bt_data *sd = NULL; +#endif uint8_t tmp[16]; int err; @@ -1148,7 +1171,7 @@ static int node_id_adv(struct bt_mesh_subnet *sub) memcpy(proxy_svc_data + 3, tmp + 8, 8); err = bt_le_adv_start(&fast_adv_param, node_id_ad, - ARRAY_SIZE(node_id_ad), NULL, 0); + ARRAY_SIZE(node_id_ad), sd, 0); if (err) { BT_WARN("Failed to advertise using Node ID (err %d)", err); return err; @@ -1161,6 +1184,21 @@ static int node_id_adv(struct bt_mesh_subnet *sub) static int net_id_adv(struct bt_mesh_subnet *sub) { + struct ble_gap_adv_params slow_adv_param = { + ADV_OPT_PROXY + ADV_SLOW_INT + }; +#if ADV_OPT_USE_NAME + const char *name = CONFIG_BT_DEVICE_NAME; + size_t name_len = strlen(name); + struct bt_data sd = { + .type = BT_DATA_NAME_COMPLETE, + .data_len = name_len, + .data = (void *)name + }; +#else + struct bt_data *sd = NULL; +#endif int err; BT_DBG(""); @@ -1171,9 +1209,8 @@ static int net_id_adv(struct bt_mesh_subnet *sub) bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8)); memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8); - err = bt_le_adv_start(&slow_adv_param, net_id_ad, - ARRAY_SIZE(net_id_ad), NULL, 0); + ARRAY_SIZE(net_id_ad), sd, 0); if (err) { BT_WARN("Failed to advertise using Network ID (err %d)", err); return err; @@ -1360,12 +1397,20 @@ int32_t bt_mesh_proxy_adv_start(void) #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) if (!bt_mesh_is_provisioned()) { const struct ble_gap_adv_params *param; - struct bt_data prov_sd[2]; + struct ble_gap_adv_params fast_adv_param = { + ADV_OPT_PROV + ADV_FAST_INT + }; + struct bt_data prov_sd[1]; size_t prov_sd_len; if (prov_fast_adv) { param = &fast_adv_param; } else { + struct ble_gap_adv_params slow_adv_param = { + ADV_OPT_PROV + ADV_SLOW_INT + }; param = &slow_adv_param; } diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index 99b18c2056..241ea8f276 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -136,6 +136,12 @@ syscfg.defs: node supports. value: 1 + BLE_MESH_PROXY_USE_DEVICE_NAME: + description: > + Include Bluetooth device name in scan response + value: 0 + restrictions: BLE_MESH_GATT_PROXY + BLE_MESH_SUBNET_COUNT: description: > This option specifies how many subnets a Mesh network can From cf8f35298817f3434bc4fe8bb00687583dda8fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 11:30:19 +0200 Subject: [PATCH 168/306] host/mesh: Fix incorrect flag check in mesh settings This bug was introduced in PR #31176, where setting's flags were moved out from bt_mesh.flags to pending_flags. This is port of 3ae0f96acb67aafe1e13a545e7a1b86159103733 --- nimble/host/mesh/src/settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index 19a9c3f87a..3c74c3863c 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -105,7 +105,7 @@ void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag) timeout_ms = 0; } else if (atomic_test_bit(pending_flags, BT_MESH_SETTINGS_RPL_PENDING) && - (!(atomic_get(bt_mesh.flags) & GENERIC_PENDING_BITS) || + (!(atomic_get(pending_flags) & GENERIC_PENDING_BITS) || (CONFIG_BT_MESH_RPL_STORE_TIMEOUT < CONFIG_BT_MESH_STORE_TIMEOUT))) { timeout_ms = CONFIG_BT_MESH_RPL_STORE_TIMEOUT * MSEC_PER_SEC; From 373a6fb5c3b4dc96f46fc3f2b969eb49e179cb4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 11:31:40 +0200 Subject: [PATCH 169/306] host/mesh: Add VA flag to generic pending flags This adds BT_MESH_SETTINGS_VA_PENDING to GENERIC_PENDING_BITS as it should be stored by CONFIG_BT_MESH_STORE_TIMEOUT. This is port of 22fabefdf2c112d4d5bfe214ddf512bb41ada6e9 --- nimble/host/mesh/src/settings.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index 3c74c3863c..b8938d4543 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -93,7 +93,8 @@ static int mesh_commit(void) BIT(BT_MESH_SETTINGS_APP_KEYS_PENDING) | \ BIT(BT_MESH_SETTINGS_HB_PUB_PENDING) | \ BIT(BT_MESH_SETTINGS_CFG_PENDING) | \ - BIT(BT_MESH_SETTINGS_MOD_PENDING)) + BIT(BT_MESH_SETTINGS_MOD_PENDING) | \ + BIT(BT_MESH_SETTINGS_VA_PENDING)) void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag) { From 452d1a5543a20b3507ad61b5ac705c92ed61f0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 11:38:10 +0200 Subject: [PATCH 170/306] host/mesh: Change friend_cred decision point to friend selection The network layer previously decided to use the friend credentials if there was an established friendship. During the friendship setup phase, the friendship is not considered established until the LPN receives the first friend poll. Before this happens, the LPN should send a friend poll message, encrypted with the friendship credentials. This wrongly gets encrypted with the master credentials. Change the decision point to whether the LPN has selected a friend, which happens after the friend offer, and before the friend poll. This will remain set for the duration of the friendship. This is port of 878043aff19c1c7468a55fa332fa695fbb6bf154 --- nimble/host/mesh/src/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index e8d3c471d4..f1e44b0503 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -389,7 +389,7 @@ static void bt_mesh_net_local(struct ble_npl_event *work) static const struct bt_mesh_net_cred *net_tx_cred_get(struct bt_mesh_net_tx *tx) { #if IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) - if (tx->friend_cred && bt_mesh_lpn_established()) { + if (tx->friend_cred && bt_mesh.lpn.frnd) { return &bt_mesh.lpn.cred[SUBNET_KEY_TX_IDX(tx->sub)]; } #endif From 03076b3eb9f5c9de73542fe7adc64165ce73d50c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 11:39:42 +0200 Subject: [PATCH 171/306] host/mesh: Pass correct pointer to publish_sent This commit fixes a bug where incorrect pointer passed to publish_sent in access.c caused bus fault. This is port of 8717a0f6787421c0adb566a6b20495a34f76f1d5 --- nimble/host/mesh/src/access.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 1c34b2ec2a..85717aa51b 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -215,7 +215,7 @@ static int pub_period_start(struct bt_mesh_model_pub *pub) BT_DBG("Update failed, skipping publish (err: %d)", err); pub->count = 0; pub->period_start = k_uptime_get_32(); - publish_sent(err, pub); + publish_sent(err, pub->mod); return err; } From 275ea539a85daafba2b941fe89e4ede11b064526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 12:07:14 +0200 Subject: [PATCH 172/306] host/mesh: Remove outated RPL entry from persistent storage This commit fixes a bug where outdated RPL entries might not be removed properly from the persistent storage making those entries dead. This is port of 1b129c50c2fdb4d7e8a270356dd5fba623deb1cc --- nimble/host/mesh/src/rpl.c | 59 +++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/nimble/host/mesh/src/rpl.c b/nimble/host/mesh/src/rpl.c index 3c4045ca5b..b767752c86 100644 --- a/nimble/host/mesh/src/rpl.c +++ b/nimble/host/mesh/src/rpl.c @@ -32,6 +32,27 @@ static inline int rpl_idx(const struct bt_mesh_rpl *rpl) return rpl - &replay_list[0]; } +static void clear_rpl(struct bt_mesh_rpl *rpl) +{ + int err; + char path[18]; + + if (!rpl->src) { + return; + } + + snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear RPL"); + } else { + BT_DBG("Cleared RPL"); + } + + (void)memset(rpl, 0, sizeof(*rpl)); + atomic_clear_bit(store, rpl_idx(rpl)); +} + static void schedule_rpl_store(struct bt_mesh_rpl *entry) { atomic_set_bit(store, rpl_idx(entry)); @@ -171,13 +192,16 @@ void bt_mesh_rpl_reset(void) if (rpl->src) { if (rpl->old_iv) { - (void)memset(rpl, 0, sizeof(*rpl)); + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + clear_rpl(rpl); + } else { + (void)memset(rpl, 0, sizeof(*rpl)); + } } else { rpl->old_iv = true; - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - schedule_rpl_store(rpl); + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + schedule_rpl_store(rpl); + } } } } @@ -246,6 +270,10 @@ static void store_rpl(struct bt_mesh_rpl *entry) char *str; int err; + if (!entry->src) { + return; + } + BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src, (unsigned) entry->seq, entry->old_iv); @@ -269,27 +297,6 @@ static void store_rpl(struct bt_mesh_rpl *entry) } } -static void clear_rpl(struct bt_mesh_rpl *rpl) -{ - int err; - char path[18]; - - if (!rpl->src) { - return; - } - - snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear RPL"); - } else { - BT_DBG("Cleared RPL"); - } - - (void)memset(rpl, 0, sizeof(*rpl)); - atomic_clear_bit(store, rpl_idx(rpl)); -} - static void store_pending_rpl(struct bt_mesh_rpl *rpl) { BT_DBG(""); From e9567a603483f44a54b59917e9adafea4a15710f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 12:08:55 +0200 Subject: [PATCH 173/306] host/mesh: Don't reset PB ADV reliable timer on retransmit The send_reliable function was reused in multiple places as part of the k_delayed_work changes for Bluetooth Mesh in #33782. This function contains a line that resets the start timer, causing prov_retransmit to continously move the goal post for when to give up sending. Extract this line out of the send_reliable function, and put it along with the other link.tx initialization in bearer_ctl_send and prov_send_adv. This is port of 85ad497c39ecf6d12bea31241d774cf300d620c2 --- nimble/host/mesh/src/pb_adv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/pb_adv.c b/nimble/host/mesh/src/pb_adv.c index eed19eacc9..405a1530a9 100644 --- a/nimble/host/mesh/src/pb_adv.c +++ b/nimble/host/mesh/src/pb_adv.c @@ -556,8 +556,6 @@ static void send_reliable(void) { int i; - link.tx.start = k_uptime_get(); - for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) { struct os_mbuf *buf = link.tx.buf[i]; @@ -638,6 +636,7 @@ static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len, net_buf_add_mem(buf, data, data_len); if (reliable) { + link.tx.start = k_uptime_get(); link.tx.buf[0] = buf; send_reliable(); } else { @@ -673,6 +672,7 @@ static int prov_send_adv(struct os_mbuf *msg, link.tx.buf[0] = start; link.tx.cb = cb; link.tx.cb_data = cb_data; + link.tx.start = k_uptime_get(); BT_DBG("xact_id: 0x%x len: %u", link.tx.id, msg->om_len); From 026cbf947c9813fc0cec9fd148c7db3dcbc7d437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 12:10:24 +0200 Subject: [PATCH 174/306] host/mesh: Reject identical public keys This commit address Erratum E10395 and Errata Correction E16350 to ensure that public keys exchanged between Provisioner and a device aren't identical. This is port of 33fafe1e2f41e5b61b1dc71f9ad0d8cb0930607f --- nimble/host/mesh/src/provisioner.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index 3b4b76598d..9e8df89375 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -385,8 +385,11 @@ static void prov_dh_key_cb(const uint8_t dhkey[32]) static void prov_dh_key_gen(void) { - uint8_t remote_pk_le[64], *remote_pk; + uint8_t remote_pk_le[64]; + const uint8_t *remote_pk; + const uint8_t *local_pk; + local_pk = &bt_mesh_prov_link.conf_inputs[17]; remote_pk = &bt_mesh_prov_link.conf_inputs[81]; /* Copy remote key in little-endian for bt_dh_key_gen(). @@ -396,6 +399,12 @@ static void prov_dh_key_gen(void) sys_memcpy_swap(remote_pk_le, remote_pk, 32); sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32); + if (!memcmp(local_pk, remote_pk, 64)) { + BT_ERR("Public keys are identical"); + prov_fail(PROV_ERR_NVAL_FMT); + return; + } + if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) { BT_ERR("Failed to generate DHKey"); prov_fail(PROV_ERR_UNEXP_ERR); From 9e4cd9ae78002c1de84667b6969447ce8c5de722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 12:36:02 +0200 Subject: [PATCH 175/306] host/mesh: Add OOB Public Key support for provisionee role This commit allows an unprovisioned device to exchange its public key using out-of-band techology (see MeshPRFv1.0.1, table 5.19 and section 5.4.2.3). For in-band public key exchange, the mesh stack uses HCI commands to generate public and private keys, and DH key. This, however, doesn't work for OOB public key exchange since there is no command to generate DH key with a private key provided by an application. Therefore, this commit adds direct usage of TinyCrypto into the mesh stack for DH key generation for OOB public key support. This is port of 0335d5fb0147b70f31a5f05c0d776adfff04ccc4 --- nimble/host/mesh/include/mesh/main.h | 17 ++++++ nimble/host/mesh/src/prov.h | 1 + nimble/host/mesh/src/prov_device.c | 84 +++++++++++++++++++++++----- nimble/host/mesh/syscfg.yml | 5 ++ 4 files changed, 92 insertions(+), 15 deletions(-) diff --git a/nimble/host/mesh/include/mesh/main.h b/nimble/host/mesh/include/mesh/main.h index 2bcb05c830..213950b17b 100644 --- a/nimble/host/mesh/include/mesh/main.h +++ b/nimble/host/mesh/include/mesh/main.h @@ -101,6 +101,23 @@ struct bt_mesh_prov { /** Out of Band information field. */ bt_mesh_prov_oob_info_t oob_info; + /** Pointer to Public Key in big-endian for OOB public key type support. + * + * Remember to enable @option{CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY} + * when initializing this parameter. + * + * Must be used together with @ref bt_mesh_prov::private_key_be. + */ + const uint8_t *public_key_be; + /** Pointer to Private Key in big-endian for OOB public key type support. + * + * Remember to enable @option{CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY} + * when initializing this parameter. + * + * Must be used together with @ref bt_mesh_prov::public_key_be. + */ + const uint8_t *private_key_be; + /** Static OOB value */ const uint8_t *static_val; /** Static OOB value length */ diff --git a/nimble/host/mesh/src/prov.h b/nimble/host/mesh/src/prov.h index 89f027256a..d300b1d5c6 100644 --- a/nimble/host/mesh/src/prov.h +++ b/nimble/host/mesh/src/prov.h @@ -75,6 +75,7 @@ enum { WAIT_CONFIRM, /* Wait for send confirm */ WAIT_AUTH, /* Wait for auth response */ OOB_STATIC_KEY, /* OOB Static Authentication */ + WAIT_DH_KEY, /* Wait for DH Key */ NUM_FLAGS, }; diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index 38a96e7a6b..b7828fa311 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -76,8 +76,9 @@ static void prov_invite(const uint8_t *data) /* Supported algorithms - FIPS P-256 Eliptic Curve */ net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256)); - /* Public Key Type, Only "No OOB" Public Key is supported */ - net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB); + /* Public Key Type */ + net_buf_simple_add_u8(buf, + bt_mesh_prov->public_key_be == NULL ? PUB_KEY_NO_OOB : PUB_KEY_OOB); /* Static OOB Type */ net_buf_simple_add_u8(buf, bt_mesh_prov->static_val ? BIT(0) : 0x00); @@ -118,12 +119,16 @@ static void prov_start(const uint8_t *data) return; } - if (data[1] != PUB_KEY_NO_OOB) { + if (data[1] == PUB_KEY_OOB && + !(MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && + bt_mesh_prov->public_key_be)) { BT_ERR("Invalid public key type: 0x%02x", data[1]); prov_fail(PROV_ERR_NVAL_FMT); return; } + atomic_set_bit_to(bt_mesh_prov_link.flags, OOB_PUB_KEY, data[1] == PUB_KEY_OOB); + memcpy(&bt_mesh_prov_link.conf_inputs[12], data, 5); bt_mesh_prov_link.expect = PROV_PUB_KEY; @@ -216,6 +221,16 @@ static void public_key_sent(int err, void *cb_data) } } +static void start_auth(void) +{ + if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) || + atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING)) { + bt_mesh_prov_link.expect = PROV_NO_PDU; /* Wait for input */ + } else { + bt_mesh_prov_link.expect = PROV_CONFIRM; + } +} + static void send_pub_key(void) { struct os_mbuf *buf = PROV_BUF(65); @@ -244,11 +259,18 @@ static void send_pub_key(void) return; } - if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) || - atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING)) { - bt_mesh_prov_link.expect = PROV_NO_PDU; /* Wait for input */ - } else { - bt_mesh_prov_link.expect = PROV_CONFIRM; + start_auth(); +} + +static void dh_key_gen_complete(void) +{ + BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32)); + + if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY) && + atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { + send_confirm(); + } else if (!atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { + send_pub_key(); } } @@ -264,16 +286,31 @@ static void prov_dh_key_cb(const uint8_t dhkey[32]) sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32); - BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32)); - - send_pub_key(); + dh_key_gen_complete(); } static void prov_dh_key_gen(void) { - uint8_t remote_pk_le[64], *remote_pk; + const uint8_t *remote_pk; + uint8_t remote_pk_le[64]; remote_pk = &bt_mesh_prov_link.conf_inputs[17]; + if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && + atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { + if (uECC_valid_public_key(remote_pk, &curve_secp256r1)) { + BT_ERR("Public key is not valid"); + } else if (uECC_shared_secret(remote_pk, bt_mesh_prov->private_key_be, + bt_mesh_prov_link.dhkey, + &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + BT_ERR("DHKey generation failed"); + } else { + dh_key_gen_complete(); + return; + } + + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } /* Copy remote key in little-endian for bt_dh_key_gen(). * X and Y halves are swapped independently. The bt_dh_key_gen() @@ -295,7 +332,21 @@ static void prov_pub_key(const uint8_t *data) /* PublicKeyProvisioner */ memcpy(&bt_mesh_prov_link.conf_inputs[17], data, 64); - if (!bt_pub_key_get()) { + if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && + atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { + if (!bt_mesh_prov->public_key_be || !bt_mesh_prov->private_key_be) { + BT_ERR("Public or private key is not ready"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + /* No swap needed since user provides public key in big-endian */ + memcpy(&bt_mesh_prov_link.conf_inputs[81], bt_mesh_prov->public_key_be, 64); + + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY); + + start_auth(); + } else if (!bt_pub_key_get()) { /* Clear retransmit timer */ bt_mesh_prov_link.bearer->clear_tx(); atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY); @@ -390,7 +441,9 @@ static void prov_confirm(const uint8_t *data) notify_input_complete(); - send_confirm(); + if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY)) { + send_confirm(); + } } static inline bool is_pb_gatt(void) @@ -492,7 +545,8 @@ static void prov_data(const uint8_t *data) static void local_input_complete(void) { - if (atomic_test_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT)) { + if (atomic_test_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT) || + atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { send_input_complete(); } else { atomic_set_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE); diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index 241ea8f276..d9bb70d7bc 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -23,6 +23,11 @@ syscfg.defs: BLE_MESH_PB_ADV or BLE_MESH_PB_GATT is set. value: 1 + BLE_MESH_PROV_OOB_PUBLIC_KEY: + description: > + Enable this option if public key is to be exchanged via Out of Band (OOB) technology. + value: 0 + BLE_MESH_PB_ADV: description: > Enable this option to allow the device to be provisioned over From d9413d20fb9ce4a1ab76cd9ad1261ce01660c864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 8 Oct 2021 12:38:07 +0200 Subject: [PATCH 176/306] host/mesh: Fix setting remote public key in provisioner This aligns provisioner and provisionee APIs in terms of endianess of public key provided by an application. This is port of f5ba999257e977688e7eae6a36a554ceed51d95f --- nimble/host/mesh/include/mesh/main.h | 2 +- nimble/host/mesh/src/provisioner.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/nimble/host/mesh/include/mesh/main.h b/nimble/host/mesh/include/mesh/main.h index 213950b17b..dff5eb1db8 100644 --- a/nimble/host/mesh/include/mesh/main.h +++ b/nimble/host/mesh/include/mesh/main.h @@ -287,7 +287,7 @@ int bt_mesh_input_number(uint32_t num); /** @brief Provide Device public key. * - * @param public_key Device public key. + * @param public_key Device public key in big-endian. * * @return Zero on success or (negative) error code otherwise. */ diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index 9e8df89375..7a8c40d8f6 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -724,8 +724,7 @@ int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]) } /* Swap X and Y halves independently to big-endian */ - memcpy(&bt_mesh_prov_link.conf_inputs[81], public_key, 32); - memcpy(&bt_mesh_prov_link.conf_inputs[81 + 32], &public_key[32], 32); + memcpy(&bt_mesh_prov_link.conf_inputs[81], public_key, 64); return 0; } From 23217d8622c2e6389a4c55e59d777fd0aec982b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 11 Oct 2021 07:01:03 +0200 Subject: [PATCH 177/306] host/mesh: Add API to manually store pending RPL entries The current approach with storing RPL by timeout doesn't solve all issues as the node may loss power before the timer is fired. In addition to that this may wear out flash quickly if short timeout is used. This change adds an API to store the pending RPL entry upon user request. Additional Kconfig option allows to completely disable timer so that the whole storing relies on the user. The mesh stack still stays responsible for outdating RPL entries in case of IV Index update as this happens implicitly for the user. This is port of 65f798a00abb6bbb7c51091e754b926d15405d14 --- nimble/host/mesh/include/mesh/main.h | 13 +++++++++++ nimble/host/mesh/src/rpl.c | 34 ++++++++++++++++++++++++---- nimble/host/mesh/src/rpl.h | 1 - nimble/host/mesh/src/settings.c | 16 ++++++++----- nimble/host/mesh/src/settings.h | 1 + nimble/host/mesh/syscfg.yml | 26 +++++++++++++-------- 6 files changed, 70 insertions(+), 21 deletions(-) diff --git a/nimble/host/mesh/include/mesh/main.h b/nimble/host/mesh/include/mesh/main.h index dff5eb1db8..d196522dea 100644 --- a/nimble/host/mesh/include/mesh/main.h +++ b/nimble/host/mesh/include/mesh/main.h @@ -565,6 +565,19 @@ void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established)); */ int bt_mesh_friend_terminate(uint16_t lpn_addr); +/** @brief Store pending RPL entry(ies) in the persistent storage. + * + * This API allows the user to store pending RPL entry(ies) in the persistent + * storage without waiting for the timeout. + * + * @note When flash is used as the persistent storage, calling this API too + * frequently may wear it out. + * + * @param addr Address of the node which RPL entry needs to be stored or + * @ref BT_MESH_ADDR_ALL_NODES to store all pending RPL entries. + */ +void bt_mesh_rpl_pending_store(uint16_t addr); + #ifdef __cplusplus } #endif diff --git a/nimble/host/mesh/src/rpl.c b/nimble/host/mesh/src/rpl.c index b767752c86..bf5743e417 100644 --- a/nimble/host/mesh/src/rpl.c +++ b/nimble/host/mesh/src/rpl.c @@ -53,10 +53,17 @@ static void clear_rpl(struct bt_mesh_rpl *rpl) atomic_clear_bit(store, rpl_idx(rpl)); } -static void schedule_rpl_store(struct bt_mesh_rpl *entry) +static void schedule_rpl_store(struct bt_mesh_rpl *entry, bool force) { atomic_set_bit(store, rpl_idx(entry)); bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); + if (force +#ifdef CONFIG_BT_MESH_RPL_STORE_TIMEOUT + || CONFIG_BT_MESH_RPL_STORE_TIMEOUT >= 0 +#endif + ) { + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); + } } static void schedule_rpl_clear(void) @@ -79,7 +86,7 @@ void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, rpl->old_iv = rx->old_iv; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - schedule_rpl_store(rpl); + schedule_rpl_store(rpl, false); } } @@ -200,7 +207,7 @@ void bt_mesh_rpl_reset(void) } else { rpl->old_iv = true; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - schedule_rpl_store(rpl); + schedule_rpl_store(rpl, true); } } } @@ -306,16 +313,35 @@ static void store_pending_rpl(struct bt_mesh_rpl *rpl) } } -void bt_mesh_rpl_pending_store(void) +void bt_mesh_rpl_pending_store(uint16_t addr) { int i; + if (!IS_ENABLED(CONFIG_BT_SETTINGS) || + (!BT_MESH_ADDR_IS_UNICAST(addr) && + addr != BT_MESH_ADDR_ALL_NODES)) { + return; + } + + if (addr == BT_MESH_ADDR_ALL_NODES) { + bt_mesh_settings_store_cancel(BT_MESH_SETTINGS_RPL_PENDING); + } + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + if (addr != BT_MESH_ADDR_ALL_NODES && + addr != replay_list[i].src) { + continue; + } + if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { store_pending_rpl(&replay_list[i]); } else { clear_rpl(&replay_list[i]); } + + if (addr != BT_MESH_ADDR_ALL_NODES) { + break; + } } } diff --git a/nimble/host/mesh/src/rpl.h b/nimble/host/mesh/src/rpl.h index 9a1d49ff07..b79ce887d4 100644 --- a/nimble/host/mesh/src/rpl.h +++ b/nimble/host/mesh/src/rpl.h @@ -29,5 +29,4 @@ bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, void bt_mesh_rpl_clear(void); void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx); -void bt_mesh_rpl_pending_store(void); void bt_mesh_rpl_init(void); \ No newline at end of file diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index b8938d4543..5ec6d71e9e 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -104,11 +104,9 @@ void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag) if (atomic_get(pending_flags) & NO_WAIT_PENDING_BITS) { timeout_ms = 0; - } else if (atomic_test_bit(pending_flags, - BT_MESH_SETTINGS_RPL_PENDING) && - (!(atomic_get(pending_flags) & GENERIC_PENDING_BITS) || - (CONFIG_BT_MESH_RPL_STORE_TIMEOUT < - CONFIG_BT_MESH_STORE_TIMEOUT))) { + } else if (CONFIG_BT_MESH_RPL_STORE_TIMEOUT >= 0 && + atomic_test_bit(pending_flags, BT_MESH_SETTINGS_RPL_PENDING) && + !(atomic_get(pending_flags) & GENERIC_PENDING_BITS)) { timeout_ms = CONFIG_BT_MESH_RPL_STORE_TIMEOUT * MSEC_PER_SEC; } else { timeout_ms = CONFIG_BT_MESH_STORE_TIMEOUT * MSEC_PER_SEC; @@ -127,12 +125,18 @@ void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag) k_work_schedule(&pending_store, K_MSEC(timeout_ms)); } } + +void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag) +{ + atomic_clear_bit(pending_flags, flag); +} + static void store_pending(struct ble_npl_event *work) { BT_DBG(""); if (atomic_test_and_clear_bit(pending_flags, BT_MESH_SETTINGS_RPL_PENDING)) { - bt_mesh_rpl_pending_store(); + bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES); } if (atomic_test_and_clear_bit(pending_flags, diff --git a/nimble/host/mesh/src/settings.h b/nimble/host/mesh/src/settings.h index 95f78f50ff..73105fb345 100644 --- a/nimble/host/mesh/src/settings.h +++ b/nimble/host/mesh/src/settings.h @@ -23,3 +23,4 @@ enum bt_mesh_settings_flag { void bt_mesh_settings_init(void); int settings_name_next(char *name, char **next); void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag); +void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag); diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index d9bb70d7bc..d0ba860a33 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -619,16 +619,22 @@ syscfg.defs: BLE_MESH_RPL_STORE_TIMEOUT: description: > - This value defines in seconds how soon the RPL gets written to - persistent storage after a change occurs. If the node receives - messages frequently it may make sense to have this set to a - large value, whereas if the RPL gets updated infrequently a - value as low as 0 (write immediately) may make sense. Note that - if the node operates a security sensitive use case, and there's - a risk of sudden power loss, it may be a security vulnerability - to set this value to anything else than 0 (a power loss before - writing to storage exposes the node to potential message - replay attacks). + Minimum interval after which unsaved RPL entries are updated in storage + + This value defines in seconds how soon unsaved RPL entries + gets written to the persistent storage. Setting this value + to a large number may lead to security vulnerabilities if a node + gets powered off before the timer is fired. When flash is used + as the persistent storage setting this value to a low number + may wear out flash sooner or later. However, if the RPL gets + updated infrequently a value as low as 0 (write immediately) + may make sense. Setting this value to -1 will disable this timer. + In this case, a user is responsible to store pending RPL entries + using @ref bt_mesh_rpl_pending_store. In the mean time, when + IV Index is updated, the outdated RPL entries will still be + stored by @ref BT_MESH_STORE_TIMEOUT. Finding the right balance + between this timeout and calling @ref bt_mesh_rpl_pending_store + may reduce a risk of security vulnerability and flash wear out. value: 5 BLE_MESH_DEVICE_NAME: From 9dc019d6cd1d28ee3ba4693170be642679f9c206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 11 Oct 2021 15:56:50 +0200 Subject: [PATCH 178/306] host/mesh: Add proxy send callback Zephyr Bluetooth Mesh did not check whether the proxy message was actually sent out, so that the response message could not be received during reset. This is port of 7531d2e3c8ffa73c9e1d1fcf33d2b26991ea5f8c --- nimble/host/mesh/src/adv.c | 9 ---- nimble/host/mesh/src/adv.h | 10 ++++ nimble/host/mesh/src/cfg_srv.c | 35 +++++++------ nimble/host/mesh/src/net.c | 5 +- nimble/host/mesh/src/pb_gatt.c | 18 ++++++- nimble/host/mesh/src/proxy.c | 93 ++++++++++++++++------------------ nimble/host/mesh/src/proxy.h | 17 +++---- 7 files changed, 99 insertions(+), 88 deletions(-) diff --git a/nimble/host/mesh/src/adv.c b/nimble/host/mesh/src/adv.c index 7e0e1927fa..a9afb42fd8 100644 --- a/nimble/host/mesh/src/adv.c +++ b/nimble/host/mesh/src/adv.c @@ -66,15 +66,6 @@ static struct bt_mesh_adv *adv_alloc(int id) return &adv_pool[id]; } -static inline void adv_send_start(uint16_t duration, int err, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->start) { - cb->start(duration, err, cb_data); - } -} - static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, void *cb_data) { diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index 6dd2c8107c..ba6d3c8d7f 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -34,6 +34,16 @@ enum bt_mesh_adv_type typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration, int err, void *user_data); + +static inline void adv_send_start(uint16_t duration, int err, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + if (cb && cb->start) { + cb->start(duration, err, cb_data); + } +} + struct bt_mesh_adv { /** Fragments associated with this buffer. */ struct os_mbuf *frags; diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 35a00bd9e5..201af6a88a 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -2023,11 +2023,27 @@ static void mod_app_get(struct bt_mesh_model *model, os_mbuf_free_chain(msg); } +static void reset_send_start(uint16_t duration, int err, void *cb_data) +{ + if (err) { + BT_ERR("Sending Node Reset Status failed (err %d)", err); + bt_mesh_reset(); + } +} + +static void reset_send_end(int err, void *cb_data) +{ + bt_mesh_reset(); +} + static void node_reset(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - static struct bt_mesh_proxy_idle_cb proxy_idle = {.cb = bt_mesh_reset}; + static const struct bt_mesh_send_cb reset_cb = { + .start = reset_send_start, + .end = reset_send_end, + }; struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET_STATUS, 0); @@ -2035,26 +2051,13 @@ static void node_reset(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - bt_mesh_model_msg_init(msg, OP_NODE_RESET_STATUS); - /* Send the response first since we wont have any keys left to - * send it later. - */ - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + if (bt_mesh_model_send(model, ctx, msg, &reset_cb, NULL)) { BT_ERR("Unable to send Node Reset Status"); } - if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - bt_mesh_reset(); - return; - } - - /* If the response goes to a proxy node, we'll wait for the sending to - * complete before moving on. - */ - bt_mesh_proxy_on_idle(&proxy_idle); - os_mbuf_free_chain(msg); + os_mbuf_free_chain(msg); } static void send_friend_status(struct bt_mesh_model *model, diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index f1e44b0503..386f4d0f8c 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -534,12 +534,13 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, goto done; } + BT_MESH_ADV(buf)->cb = cb; + BT_MESH_ADV(buf)->cb_data = cb_data; + /* Deliver to GATT Proxy Clients if necessary. */ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && bt_mesh_proxy_relay(buf, tx->ctx->addr) && BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - /* Notify completion if this only went through the Mesh Proxy */ - send_cb_finalize(cb, cb_data); err = 0; goto done; diff --git a/nimble/host/mesh/src/pb_gatt.c b/nimble/host/mesh/src/pb_gatt.c index bd119c15ef..fb04963219 100644 --- a/nimble/host/mesh/src/pb_gatt.c +++ b/nimble/host/mesh/src/pb_gatt.c @@ -15,10 +15,16 @@ #include "adv.h" #include "prov.h" +struct prov_bearer_send_cb { + prov_bearer_send_complete_t cb; + void *cb_data; +}; + struct prov_link { uint16_t conn_handle; const struct prov_bearer_cb *cb; void *cb_data; + struct prov_bearer_send_cb comp; struct { uint8_t id; /* Transaction ID */ uint8_t prev_id; /* Previous Transaction ID */ @@ -130,6 +136,13 @@ static int link_accept(const struct prov_bearer_cb *cb, void *cb_data) return 0; } +static void buf_send_end(uint16_t conn_handle, void *user_data) +{ + if (link.comp.cb) { + link.comp.cb(0, link.comp.cb_data); + } +} + static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb, void *cb_data) { @@ -137,9 +150,12 @@ static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb, return -ENOTCONN; } + link.comp.cb = cb; + link.comp.cb_data = cb_data; + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); - return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, buf); + return bt_mesh_pb_gatt_send(link.conn_handle, buf, buf_send_end, NULL); } static void clear_tx(void) diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/proxy.c index 44c3376a0e..e05cbb5830 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/proxy.c @@ -139,9 +139,6 @@ static struct bt_mesh_proxy_client { [0 ... (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1)] = { 0 }, }; -static sys_slist_t idle_waiters; -static atomic_t pending_notifications; - /* Track which service is enabled */ static enum { MESH_GATT_NONE, @@ -213,7 +210,8 @@ static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) static struct bt_mesh_subnet *beacon_sub; static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, - struct os_mbuf *msg); + struct os_mbuf *msg, + void (*end)(uint16_t, void *), void *user_data); static int filter_set(struct bt_mesh_proxy_client *client, struct os_mbuf *buf) @@ -328,7 +326,8 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, return; } - err = proxy_segment_and_send(client->conn_handle, BT_MESH_PROXY_CONFIG, buf); + err = proxy_segment_and_send(client->conn_handle, BT_MESH_PROXY_CONFIG, buf, + NULL, NULL); if (err) { BT_ERR("Failed to send proxy cfg message (err %d)", err); } @@ -407,7 +406,8 @@ static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub) net_buf_simple_init(buf, 1); bt_mesh_beacon_create(sub, buf); - rc = proxy_segment_and_send(conn_handle, BT_MESH_PROXY_BEACON, buf); + rc = proxy_segment_and_send(conn_handle, BT_MESH_PROXY_BEACON, buf, + NULL, NULL); os_mbuf_free_chain(buf); return rc; } @@ -953,10 +953,19 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, return false; } +static void buf_send_end(uint16_t conn_handle, void *user_data) +{ + struct os_mbuf *buf = user_data; + + net_buf_unref(buf); +} + bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) { + const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb; + void *cb_data = BT_MESH_ADV(buf)->cb_data; bool relayed = false; - int i; + int i, err; BT_DBG("%u bytes to dst 0x%04x", buf->om_len, dst); @@ -972,6 +981,11 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) continue; } + if (client->filter_type == PROV) { + BT_ERR("Invalid PDU type for Proxy Client"); + return -EINVAL; + } + /* Proxy PDU sending modifies the original buffer, * so we need to make a copy. */ @@ -979,7 +993,14 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) net_buf_simple_init(msg, 1); net_buf_simple_add_mem(msg, buf->om_data, buf->om_len); - bt_mesh_proxy_send(client->conn_handle, BT_MESH_PROXY_NET_PDU, msg); + err = proxy_segment_and_send(client->conn_handle, BT_MESH_PROXY_NET_PDU, + msg, buf_send_end, net_buf_ref(buf)); + + adv_send_start(0, err, cb, cb_data); + if (err) { + BT_ERR("Failed to send proxy message (err %d)", err); + continue; + } os_mbuf_free_chain(msg); relayed = true; } @@ -989,22 +1010,9 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) #endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */ -static void notify_complete(void) -{ - sys_snode_t *n; - - if (atomic_dec(&pending_notifications) > 1) { - return; - } - - BT_DBG(""); - - while ((n = sys_slist_get(&idle_waiters))) { - CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb(); - } -} - -static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len) +static int proxy_send(uint16_t conn_handle, + const void *data, uint16_t len, + void (*end)(uint16_t, void *), void *user_data) { struct os_mbuf *om; int err = 0; @@ -1016,7 +1024,7 @@ static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len) om = ble_hs_mbuf_from_flat(data, len); assert(om); err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); - notify_complete(); + /* We do not pass cb into ble_gattc_notify_custom - execute it at the end */ } #endif @@ -1025,19 +1033,16 @@ static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len) om = ble_hs_mbuf_from_flat(data, len); assert(om); err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); - notify_complete(); } #endif - if (!err) { - atomic_inc(&pending_notifications); - } - + end(conn_handle, user_data); return err; } static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, - struct os_mbuf *msg) + struct os_mbuf *msg, + void (*end)(uint16_t, void *), void *user_data) { uint16_t mtu; @@ -1048,30 +1053,30 @@ static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, mtu = ble_att_mtu(conn_handle) - 3; if (mtu > msg->om_len) { net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); - return proxy_send(conn_handle, msg->om_data, msg->om_len); + return proxy_send(conn_handle, msg->om_data, msg->om_len, end, user_data); } net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); - proxy_send(conn_handle, msg->om_data, mtu); + proxy_send(conn_handle, msg->om_data, mtu, NULL, NULL); net_buf_simple_pull_mem(msg, mtu); while (msg->om_len) { if (msg->om_len + 1 < mtu) { net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); - proxy_send(conn_handle, msg->om_data, msg->om_len); + proxy_send(conn_handle, msg->om_data, msg->om_len, end, user_data); break; } net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); - proxy_send(conn_handle, msg->om_data, mtu); + proxy_send(conn_handle, msg->om_data, mtu, NULL, NULL); net_buf_simple_pull_mem(msg, mtu); } return 0; } -int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, - struct os_mbuf *msg) +int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, + void (*end)(uint16_t, void *), void *user_data) { struct bt_mesh_proxy_client *client = find_client(conn_handle); @@ -1080,12 +1085,12 @@ int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, return -ENOTCONN; } - if ((client->filter_type == PROV) != (type == BT_MESH_PROXY_PROV)) { + if (client->filter_type == PROV) { BT_ERR("Invalid PDU type for Proxy Client"); return -EINVAL; } - return proxy_segment_and_send(conn_handle, type, msg); + return proxy_segment_and_send(conn_handle, BT_MESH_PROXY_PROV, buf, end, user_data); } #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) @@ -1610,14 +1615,4 @@ int bt_mesh_proxy_init(void) return 0; } -void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb) -{ - if (!atomic_get(&pending_notifications)) { - cb->cb(); - return; - } - - sys_slist_append(&idle_waiters, &cb->n); -} - #endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ diff --git a/nimble/host/mesh/src/proxy.h b/nimble/host/mesh/src/proxy.h index ebade45ab6..27124901f2 100644 --- a/nimble/host/mesh/src/proxy.h +++ b/nimble/host/mesh/src/proxy.h @@ -6,8 +6,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __PROXY_H__ -#define __PROXY_H__ +#ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ +#define ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ + +int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, + void (*end)(uint16_t, void *), void *user_data); #define BT_MESH_PROXY_NET_PDU 0x00 #define BT_MESH_PROXY_BEACON 0x01 @@ -17,13 +20,6 @@ #include "mesh/mesh.h" #include "mesh/slist.h" -struct bt_mesh_proxy_idle_cb { - sys_snode_t n; - void (*cb)(void); -}; - -int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg); - int bt_mesh_proxy_prov_enable(void); int bt_mesh_proxy_prov_disable(bool disconnect); @@ -45,8 +41,7 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst); void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr); int bt_mesh_proxy_init(void); -void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb); int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg); -#endif +#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ */ From e8a42b4fd1a335e00ddf6de248e3b97ad23582c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 11 Oct 2021 16:12:20 +0200 Subject: [PATCH 179/306] host/mesh: Increase default CDB node count The old default of 1 makes provisioner devices useless, as they can only provision themselves before they run out of space. This is port of f2579cb3f26bde3050306401de9cd2837c94024f --- nimble/host/mesh/syscfg.yml | 2 +- porting/examples/linux_blemesh/include/syscfg/syscfg.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index d0ba860a33..f992500d02 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -69,7 +69,7 @@ syscfg.defs: description: > This option specifies how many nodes each network can at most save in the configuration database. - value: 1 + value: 8 BLE_MESH_CDB_SUBNET_COUNT: description: > diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index a3df8b6ea0..2fd5232b94 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -1041,7 +1041,7 @@ #endif #ifndef MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT -#define MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT (1) +#define MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT (8) #endif #ifndef MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT From e0f018c52c5a6f1d9975e5817753f54891882b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 11 Oct 2021 16:18:04 +0200 Subject: [PATCH 180/306] host/mesh: sequence number limit config Set sequence number limit by Kconfig This is port of f6d7f8f36fffdf2b311252eee54f765d854a51b7 --- nimble/host/mesh/include/mesh/glue.h | 1 + nimble/host/mesh/src/net.c | 2 +- nimble/host/mesh/syscfg.yml | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 9dfd051096..4edefd9f54 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -431,6 +431,7 @@ static inline unsigned int find_msb_set(uint32_t op) #define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT) #define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) #define CONFIG_BT_MESH_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_STORE_TIMEOUT) +#define CONFIG_BT_MESH_IV_UPDATE_SEQ_LIMIT MYNEWT_VAL(BLE_MESH_IV_UPDATE_SEQ_LIMIT) #define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER) #define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME) #define CONFIG_BT_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 386f4d0f8c..b8136e99bd 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -39,7 +39,7 @@ #define LOOPBACK_BUF_SUB(buf) (*(struct bt_mesh_subnet **)net_buf_user_data(buf)) /* Seq limit after IV Update is triggered */ -#define IV_UPDATE_SEQ_LIMIT 8000000 +#define IV_UPDATE_SEQ_LIMIT CONFIG_BT_MESH_IV_UPDATE_SEQ_LIMIT #define IVI(pdu) ((pdu)[0] >> 7) #define NID(pdu) ((pdu)[0] & 0x7f) diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index f992500d02..c0ebac5bd2 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -214,6 +214,11 @@ syscfg.defs: absolutely necessary value: 768 + BLE_MESH_IV_UPDATE_SEQ_LIMIT: + description: > + This option specifies the sequence number value to start iv update. + value: 0x800000 + BLE_MESH_IVU_DIVIDER: description: > When the IV Update state enters Normal operation or IV Update From 53d610b73d133b47a90717937a643485a34324a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 11 Oct 2021 16:21:30 +0200 Subject: [PATCH 181/306] host/mesh: Fix missing proxy send status Add an error judgment during `proxy_send` to avoid missing `net_buf_unref`. This is port of c45ec6fc0da1d5c183d9b2628ef2fdab60b0c978 --- nimble/host/mesh/src/proxy.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/proxy.c index e05cbb5830..bc62f2b036 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/proxy.c @@ -999,6 +999,12 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) adv_send_start(0, err, cb, cb_data); if (err) { BT_ERR("Failed to send proxy message (err %d)", err); + /* If segment_and_send() fails the buf_send_end() callback will + * not be called, so we need to clear the user data (net_buf, + * which is just opaque data to segment_and send) reference given + * to segment_and_send() here. + */ + net_buf_unref(buf); continue; } os_mbuf_free_chain(msg); @@ -1044,6 +1050,7 @@ static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg, void (*end)(uint16_t, void *), void *user_data) { + int err; uint16_t mtu; BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len, @@ -1057,18 +1064,27 @@ static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, } net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); - proxy_send(conn_handle, msg->om_data, mtu, NULL, NULL); + err = proxy_send(conn_handle, msg->om_data, mtu, NULL, NULL); + if (err) { + return err; + } net_buf_simple_pull_mem(msg, mtu); while (msg->om_len) { if (msg->om_len + 1 < mtu) { net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); - proxy_send(conn_handle, msg->om_data, msg->om_len, end, user_data); + err = proxy_send(conn_handle, msg->om_data, msg->om_len, end, user_data); + if (err) { + return err; + } break; } net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); - proxy_send(conn_handle, msg->om_data, mtu, NULL, NULL); + err = proxy_send(conn_handle, msg->om_data, mtu, NULL, NULL); + if (err) { + return err; + } net_buf_simple_pull_mem(msg, mtu); } From c3a4b94f6f34e2be00ee8f4dacd42f58015a91a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 11 Oct 2021 16:22:25 +0200 Subject: [PATCH 182/306] host/mesh: comp pointer check comp data pointer check before using This is port of d466a807ee20670e90169eb2ad36996210277893 --- nimble/host/mesh/src/access.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 85717aa51b..79f4be7b45 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -328,7 +328,7 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp) int err; /* There must be at least one element */ - if (!comp->elem_count) { + if (!comp || !comp->elem_count) { return -EINVAL; } From 4b0e34959271c031df8f8669dee7dcc09cb89374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 11 Oct 2021 16:24:13 +0200 Subject: [PATCH 183/306] host/mesh: Update SNB beacon before sending it Authentication value must be recalculated before sending it. This is port of 5513b86864e3ccd3de710724308e46abbcaa44af --- nimble/host/mesh/src/net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index b8136e99bd..865747b048 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -314,13 +314,13 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) bt_mesh_friend_sec_update(BT_MESH_KEY_ANY); } + bt_mesh_subnet_foreach(bt_mesh_beacon_update); + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) { bt_mesh_proxy_beacon_send(NULL); } - bt_mesh_subnet_foreach(bt_mesh_beacon_update); - if (MYNEWT_VAL(BLE_MESH_CDB)) { bt_mesh_cdb_iv_update(iv_index, iv_update); } From 7baecc0fa49593c0cca8e12c874fd423655d85c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 11 Oct 2021 16:36:40 +0200 Subject: [PATCH 184/306] host/mesh: Fix regression in PB-ADV After #35702, the provisioner is unable to mark a link as closed, as it depends on the send_end callback to be called, so it can start its timer. PB-Adv keeps a reference to the buffers of reliable messages, which prevents this callback to be invoked, as the buffer destructor is never called. Move scheduling of the retransmit timer to the initial transmission, and replace the timer based LINK_CLOSE message tx duration with a message counting solution. This is port of 534177b2ca02f52ad04d8da08167a3e847242de7 --- nimble/host/mesh/src/pb_adv.c | 118 ++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 55 deletions(-) diff --git a/nimble/host/mesh/src/pb_adv.c b/nimble/host/mesh/src/pb_adv.c index 405a1530a9..3e136a2070 100644 --- a/nimble/host/mesh/src/pb_adv.c +++ b/nimble/host/mesh/src/pb_adv.c @@ -55,10 +55,10 @@ /* Acked messages, will do retransmissions manually, taking acks into account: */ #define RETRANSMITS_RELIABLE 0 -/* Unacked messages: */ -#define RETRANSMITS_UNRELIABLE 2 /* PDU acks: */ #define RETRANSMITS_ACK 2 +/* Link close retransmits: */ +#define RETRANSMITS_LINK_CLOSE 2 enum { ADV_LINK_ACTIVE, /* Link has been opened */ @@ -126,20 +126,27 @@ static void link_open(struct prov_rx *rx, struct os_mbuf *buf); static void link_ack(struct prov_rx *rx, struct os_mbuf *buf); static void link_close(struct prov_rx *rx, struct os_mbuf *buf); static void prov_link_close(enum prov_bearer_link_status status); +static void close_link(enum prov_bearer_link_status status); static void buf_sent(int err, void *user_data) { BT_DBG("buf_send"); - if (!link.tx.buf[0]) { + if (atomic_test_and_clear_bit(link.flags, ADV_LINK_CLOSING)) { + close_link(PROV_BEARER_LINK_STATUS_SUCCESS); return; } +} - BT_DBG("submit retransmit"); - k_work_reschedule(&link.tx.retransmit, RETRANSMIT_TIMEOUT); +static void buf_start(uint16_t duration, int err, void *user_data) +{ + if (err) { + buf_sent(err, user_data); + } } static struct bt_mesh_send_cb buf_sent_cb = { + .start = buf_start, .end = buf_sent, }; @@ -569,18 +576,14 @@ static void send_reliable(void) BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) { - bt_mesh_adv_send(buf, NULL, NULL); - } else { - bt_mesh_adv_send(buf, &buf_sent_cb, NULL); - } + bt_mesh_adv_send(buf, NULL, NULL); } + + k_work_reschedule(&link.tx.retransmit, RETRANSMIT_TIMEOUT); } static void prov_retransmit(struct ble_npl_event *work) { - int32_t timeout_ms; - BT_DBG(""); if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { @@ -588,45 +591,25 @@ static void prov_retransmit(struct ble_npl_event *work) return; } - /* - * According to mesh profile spec (5.3.1.4.3), the close message should - * be restransmitted at least three times. Retransmit the link_close - * message until CLOSING_TIMEOUT has elapsed. - */ - if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) { - timeout_ms = CLOSING_TIMEOUT; - } else { - timeout_ms = TRANSACTION_TIMEOUT; - } - - if (k_uptime_get() - link.tx.start > timeout_ms) { - if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) { - close_link(PROV_BEARER_LINK_STATUS_SUCCESS); - } else { - BT_WARN("Giving up transaction"); - prov_link_close(PROV_BEARER_LINK_STATUS_TIMEOUT); - } - + if (k_uptime_get() - link.tx.start > TRANSACTION_TIMEOUT) { + BT_WARN("Giving up transaction"); + prov_link_close(PROV_BEARER_LINK_STATUS_FAIL); return; } send_reliable(); } -static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len, - bool reliable) +static struct os_mbuf *ctl_buf_create(uint8_t op, const void *data, uint8_t data_len, + uint8_t retransmits) { struct os_mbuf *buf; BT_DBG("op 0x%02x data_len %u", op, data_len); - prov_clear_tx(); - k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); - - buf = adv_buf_create(reliable ? RETRANSMITS_RELIABLE : - RETRANSMITS_UNRELIABLE); + buf = adv_buf_create(retransmits); if (!buf) { - return -ENOBUFS; + return NULL; } net_buf_add_be32(buf, link.id); @@ -634,16 +617,35 @@ static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len, net_buf_add_u8(buf, 0x00); net_buf_add_u8(buf, GPC_CTL(op)); net_buf_add_mem(buf, data, data_len); + return buf; +} - if (reliable) { - link.tx.start = k_uptime_get(); - link.tx.buf[0] = buf; - send_reliable(); - } else { - bt_mesh_adv_send(buf, &buf_sent_cb, NULL); - net_buf_unref(buf); +static int bearer_ctl_send(struct os_mbuf *buf) +{ + if (!buf) { + return -ENOMEM; + } + prov_clear_tx(); + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); + + link.tx.start = k_uptime_get(); + link.tx.buf[0] = buf; + send_reliable(); + + return 0; + } + +static int bearer_ctl_send_unacked(struct os_mbuf *buf) +{ + if (!buf) { + return -ENOMEM; } + prov_clear_tx(); + k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); + + bt_mesh_adv_send(buf, &buf_sent_cb, NULL); + net_buf_unref(buf); return 0; } @@ -720,6 +722,8 @@ static int prov_send_adv(struct os_mbuf *msg, static void link_open(struct prov_rx *rx, struct os_mbuf *buf) { + int err; + BT_DBG("len %u", buf->om_len); if (buf->om_len < 16) { @@ -729,13 +733,14 @@ static void link_open(struct prov_rx *rx, struct os_mbuf *buf) if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { /* Send another link ack if the provisioner missed the last */ - if (link.id == rx->link_id) { - BT_DBG("Resending link ack"); - bearer_ctl_send(LINK_ACK, NULL, 0, false); - } else { + if (link.id != rx->link_id) { BT_DBG("Ignoring bearer open: link already active"); + return; } + BT_DBG("Resending link ack"); + /* Ignore errors, message will be attempted again if we keep receiving link open: */ + (void)bearer_ctl_send_unacked(ctl_buf_create(LINK_ACK, NULL, 0, RETRANSMITS_ACK)); return; } @@ -748,7 +753,11 @@ static void link_open(struct prov_rx *rx, struct os_mbuf *buf) atomic_set_bit(link.flags, ADV_LINK_ACTIVE); net_buf_simple_reset(link.rx.buf); - bearer_ctl_send(LINK_ACK, NULL, 0, false); + err = bearer_ctl_send_unacked(ctl_buf_create(LINK_ACK, NULL, 0, RETRANSMITS_ACK)); + if (err) { + reset_adv_link(); + return; + } link.cb->link_opened(&pb_adv, link.cb_data); } @@ -828,9 +837,7 @@ static int prov_link_open(const uint8_t uuid[16], int32_t timeout, net_buf_simple_reset(link.rx.buf); - bearer_ctl_send(LINK_OPEN, uuid, 16, true); - - return 0; + return bearer_ctl_send(ctl_buf_create(LINK_OPEN, uuid, 16, RETRANSMITS_RELIABLE)); } static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data) @@ -858,7 +865,8 @@ static void prov_link_close(enum prov_bearer_link_status status) return; } - bearer_ctl_send(LINK_CLOSE, &status, 1, true); + /* Ignore errors, the link will time out eventually if this doesn't get sent */ + bearer_ctl_send_unacked(ctl_buf_create(LINK_CLOSE, &status, 1, RETRANSMITS_LINK_CLOSE)); } void pb_adv_init(void) From 2dad0b9f2f9fcc9a83ac4ab563136cd9e0701964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 12 Oct 2021 07:32:30 +0200 Subject: [PATCH 185/306] host/mesh: Check the CID field before opcode compare Bluetooth Mesh Vendor model hava company id field. Accordin MeshPRFV1.0.1 3.7.3.1 Operation codes. The 3-octet opcodes are used for manufacturer-specific opcodes. The company identifiers are 16-bit values defined by the Bluetooth SIG and are coded into the second and third octets of the 3-octet opcodes. Therefore, we can speed up the search process by checking whether CID fields match, rather than comparing opcodes one by one. This is port of cc0abee3db739413f2498d465386ab5a8bf7c1eb --- nimble/host/mesh/include/mesh/glue.h | 1 + nimble/host/mesh/src/access.c | 78 ++++++++++++++++++------ nimble/host/mesh/syscfg.yml | 6 ++ porting/targets/linux_blemesh/syscfg.yml | 1 + 4 files changed, 67 insertions(+), 19 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 4edefd9f54..ec0e609a0b 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -439,6 +439,7 @@ static inline unsigned int find_msb_set(uint32_t op) #define CONFIG_BT_MESH_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX) #define CONFIG_BT_MESH_RX_SEG_MSG_COUNT MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT) #define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT) +#define CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE MYNEWT_VAL(BLE_MESH_MODEL_VND_MSG_CID_FORCE) #define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT) #define CONFIG_BT_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED) #define CONFIG_BT_MESH_DEFAULT_TTL MYNEWT_VAL(BLE_MESH_DEFAULT_TTL) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 79f4be7b45..359d8c4e27 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -291,6 +291,30 @@ struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_ } } +#if defined(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE) +static int bt_mesh_vnd_mod_msg_cid_check(struct bt_mesh_model *mod) +{ + uint16_t cid; + const struct bt_mesh_model_op *op; + + for (op = mod->op; op->func; op++) { + cid = (uint16_t)(op->opcode & 0xffff); + + if (cid == mod->vnd.company) { + continue; + } + + BT_ERR("Invalid vendor model(company:0x%04x" + " id:0x%04x) message opcode 0x%08x", + mod->vnd.company, mod->vnd.id, op->opcode); + + return -EINVAL; + } + + return 0; +} +#endif + static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { @@ -314,6 +338,13 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, mod->elem_idx = elem - dev_comp->elem; if (vnd) { mod->mod_idx = mod - elem->vnd_models; + + if (CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE) { + *err = bt_mesh_vnd_mod_msg_cid_check(mod); + if (*err) { + return; + } + } } else { mod->mod_idx = mod - elem->models; } @@ -509,15 +540,37 @@ static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst) return mod->elem_idx == 0; } -static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models, - uint8_t model_count, uint32_t opcode, - struct bt_mesh_model **model) +static const struct bt_mesh_model_op *find_op(struct bt_mesh_elem *elem, + uint32_t opcode, struct bt_mesh_model **model) { uint8_t i; + uint8_t count; + /* This value shall not be used in shipping end products. */ + uint32_t cid = UINT32_MAX; + struct bt_mesh_model *models; + + /* SIG models cannot contain 3-byte (vendor) OpCodes, and + * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so + * we only need to do the lookup in one of the model lists. + */ + if (BT_MESH_MODEL_OP_LEN(opcode) < 3) { + models = elem->models; + count = elem->model_count; + } else { + models = elem->vnd_models; + count = elem->vnd_model_count; + + cid = (uint16_t)(opcode & 0xffff); + } - for (i = 0; i < model_count; i++) { + for (i = 0U; i < count; i++) { const struct bt_mesh_model_op *op; + if (CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE && + cid != UINT32_MAX && + cid != models[i].vnd.company) { + continue; + } *model = &models[i]; for (op = (*model)->op; op->func; op++) { @@ -571,10 +624,9 @@ static int get_opcode(struct os_mbuf *buf, uint32_t *opcode) void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { - struct bt_mesh_model *models, *model; + struct bt_mesh_model *model; const struct bt_mesh_model_op *op; uint32_t opcode; - uint8_t count; int i; BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx, @@ -589,22 +641,10 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) BT_DBG("OpCode 0x%08x", (unsigned) opcode); for (i = 0; i < dev_comp->elem_count; i++) { - struct bt_mesh_elem *elem = &dev_comp->elem[i]; struct net_buf_simple_state state; - /* SIG models cannot contain 3-byte (vendor) OpCodes, and - * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so - * we only need to do the lookup in one of the model lists. - */ - if (BT_MESH_MODEL_OP_LEN(opcode) < 3) { - models = elem->models; - count = elem->model_count; - } else { - models = elem->vnd_models; - count = elem->vnd_model_count; - } + op = find_op(&dev_comp->elem[i], opcode, &model); - op = find_op(models, count, opcode, &model); if (!op) { BT_DBG("No OpCode 0x%08x for elem %d", opcode, i); continue; diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index c0ebac5bd2..dcde094443 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -171,6 +171,12 @@ syscfg.defs: at most be subscribed to. value: 1 + BLE_MESH_MODEL_VND_MSG_CID_FORCE: + description: > + This option forces vendor model to use messages for the + corresponding CID field. + value: 1 + BLE_MESH_LABEL_COUNT: description: > This option specifies how many Label UUIDs can be stored. diff --git a/porting/targets/linux_blemesh/syscfg.yml b/porting/targets/linux_blemesh/syscfg.yml index efc4150b4c..8ef7972184 100644 --- a/porting/targets/linux_blemesh/syscfg.yml +++ b/porting/targets/linux_blemesh/syscfg.yml @@ -34,6 +34,7 @@ syscfg.vals: BLE_MESH_LABEL_COUNT: 2 BLE_MESH_SUBNET_COUNT: 2 BLE_MESH_MODEL_GROUP_COUNT: 2 + BLE_MESH_MODEL_VND_MSG_CID_FORCE: 1 BLE_MESH_APP_KEY_COUNT: 4 BLE_MESH_IV_UPDATE_TEST: 1 BLE_MESH_TESTING: 1 From de8d513602e27644b4af09b81215ac43a2c4805f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 12 Oct 2021 07:35:49 +0200 Subject: [PATCH 186/306] host/mesh: Restore default device configuration on reset This commit fixes an issue where bt_mesh_reset() call just erases all mesh flags set at the initialization instead of restoring them and thus disabling some features until the board reboot. This is port of 6c9411656c3a282155f9b9f780da95b2767649bb --- nimble/host/mesh/src/cfg.c | 2 +- nimble/host/mesh/src/cfg.h | 2 +- nimble/host/mesh/src/cfg_srv.c | 2 +- nimble/host/mesh/src/foundation.h | 2 +- nimble/host/mesh/src/mesh.c | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/nimble/host/mesh/src/cfg.c b/nimble/host/mesh/src/cfg.c index b9daa8fda2..9ed212abc4 100644 --- a/nimble/host/mesh/src/cfg.c +++ b/nimble/host/mesh/src/cfg.c @@ -348,7 +348,7 @@ static struct conf_handler bt_mesh_cfg_conf_handler = { .ch_export = NULL, }; -void bt_mesh_cfg_init(void) +void bt_mesh_cfg_default_set(void) { int rc; diff --git a/nimble/host/mesh/src/cfg.h b/nimble/host/mesh/src/cfg.h index 40f7ed92bc..0bd7ad39c6 100644 --- a/nimble/host/mesh/src/cfg.h +++ b/nimble/host/mesh/src/cfg.h @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -void bt_mesh_cfg_init(void); +void bt_mesh_cfg_default_set(void); void bt_mesh_cfg_pending_store(void); bool bt_mesh_fixed_group_match(uint16_t addr); \ No newline at end of file diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 201af6a88a..734faa7c8f 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -2511,7 +2511,7 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, } } -void bt_mesh_cfg_reset(void) +void bt_mesh_model_reset(void) { bt_mesh_model_foreach(mod_reset, NULL); } diff --git a/nimble/host/mesh/src/foundation.h b/nimble/host/mesh/src/foundation.h index 012afbbb07..21734047ec 100644 --- a/nimble/host/mesh/src/foundation.h +++ b/nimble/host/mesh/src/foundation.h @@ -115,7 +115,7 @@ #define STATUS_UNSPECIFIED 0x10 #define STATUS_INVALID_BINDING 0x11 -void bt_mesh_cfg_reset(void); +void bt_mesh_model_reset(void); void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time); diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index 4ff992d53c..3dfba16763 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -170,8 +170,8 @@ void bt_mesh_reset(void) k_work_cancel_delayable(&bt_mesh.ivu_timer); - bt_mesh_cfg_reset(); - + bt_mesh_model_reset(); + bt_mesh_cfg_default_set(); bt_mesh_trans_reset(); bt_mesh_app_keys_reset(); bt_mesh_net_keys_reset(); @@ -351,7 +351,7 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, #if CONFIG_BT_MESH_CDB bt_mesh_cdb_init(); #endif - bt_mesh_cfg_init(); + bt_mesh_cfg_default_set(); bt_mesh_net_init(); bt_mesh_trans_init(); bt_mesh_hb_init(); From 115e911619048f8f1db4136cda4ae5368ff7648b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 13 Oct 2021 12:41:48 +0200 Subject: [PATCH 187/306] host/mesh: Modularizing the proxy The Bluetooth proxy feature includes proxy client and proxy server. In addition to the proxy pdu message used above, pb-gatt also uses the same proxy pdu message. Currently zephyr bluetooth mesh couples them in one file. A file at the separation is called gatt_services.c, which is used to contain Mesh Provisioning Service and Mesh Proxy Service. Another file in the separation is called proxy_msg.c, which is used to process Proxy pdu messages. Also according to Trond's suggestion: Rename `CONFIG_BT_MESH_PROXY` to `CONFIG_BT_MESH_GATT`. Create an additional promptless entry `CONFIG_BT_MESH_GATT_SERVER` that selects `CONFIG_BT_MESH_GATT` and is selected by `CONFIG_BT_MESH_GATT_PROXY` or `CONFIG_BT_MESH_PB_GATT`. Create additional `CONFIG_BT_MESH_PROXY` used to represent proxy feature (also include proxy client). This is port of 3a559e972a415449cb577a35aed3e0514bba77df, 7b2e51881c8eab839b4a8f1e914a7accb6fe1598 and 3d2ad8e653b533d83ebf31b672d52922bca2d481 --- .../mesh/src/{proxy.c => gatt_services.c} | 1420 +++++++---------- nimble/host/mesh/src/proxy.h | 6 +- nimble/host/mesh/src/proxy_msg.c | 231 +++ nimble/host/mesh/src/proxy_msg.h | 47 + nimble/host/mesh/syscfg.yml | 12 + 5 files changed, 908 insertions(+), 808 deletions(-) rename nimble/host/mesh/src/{proxy.c => gatt_services.c} (70%) create mode 100644 nimble/host/mesh/src/proxy_msg.c create mode 100644 nimble/host/mesh/src/proxy_msg.h diff --git a/nimble/host/mesh/src/proxy.c b/nimble/host/mesh/src/gatt_services.c similarity index 70% rename from nimble/host/mesh/src/proxy.c rename to nimble/host/mesh/src/gatt_services.c index bc62f2b036..38f5ee1147 100644 --- a/nimble/host/mesh/src/proxy.c +++ b/nimble/host/mesh/src/gatt_services.c @@ -2,32 +2,28 @@ /* * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2021 Lingao Meng * * SPDX-License-Identifier: Apache-2.0 */ -#include "syscfg/syscfg.h" -#define MESH_LOG_MODULE BLE_MESH_PROXY_LOG +#define BT_DBG_ENABLED CONFIG_BT_MESH_DEBUG_PROXY +#define LOG_MODULE_NAME bt_mesh_gatt -#if MYNEWT_VAL(BLE_MESH_PROXY) - -#include "mesh/mesh.h" -#include "host/ble_att.h" -#include "services/gatt/ble_svc_gatt.h" #include "../../host/src/ble_hs_priv.h" +#include "services/gatt/ble_svc_gatt.h" #include "mesh_priv.h" #include "adv.h" #include "net.h" #include "rpl.h" +#include "transport.h" #include "prov.h" #include "beacon.h" #include "foundation.h" #include "access.h" #include "proxy.h" - -#define PDU_TYPE(data) (data[0] & BIT_MASK(6)) -#define PDU_SAR(data) (data[0] >> 6) +#include "proxy_msg.h" #define BT_UUID_16_ENCODE(w16) \ (((w16) >> 0) & 0xFF), \ @@ -38,15 +34,8 @@ */ #define PROXY_SAR_TIMEOUT K_SECONDS(20) -#define SAR_COMPLETE 0x00 -#define SAR_FIRST 0x01 -#define SAR_CONT 0x02 -#define SAR_LAST 0x03 +#define CLIENT_BUF_SIZE 65 -#define CFG_FILTER_SET 0x00 -#define CFG_FILTER_ADD 0x01 -#define CFG_FILTER_REMOVE 0x02 -#define CFG_FILTER_STATUS 0x03 /** @def BT_UUID_MESH_PROV * @brief Mesh Provisioning Service @@ -84,44 +73,64 @@ ble_uuid16_t BT_UUID_MESH_PROXY_DATA_IN = BLE_UUID16_INIT(0x2add); ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); #define BT_UUID_MESH_PROXY_DATA_OUT_VAL 0x2ade -#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) - -#define CLIENT_BUF_SIZE 65 +#if CONFIG_BT_MESH_DEBUG_USE_ID_ADDR +#define ADV_OPT_USE_IDENTITY BT_LE_ADV_OPT_USE_IDENTITY +#else +#define ADV_OPT_USE_IDENTITY 0 +#endif -#if MYNEWT_VAL(BLE_MESH_PROXY_USE_DEVICE_NAME) +#if CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME #define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME #else #define ADV_OPT_USE_NAME 0 #endif #define ADV_OPT_PROV \ - .conn_mode = (BLE_GAP_CONN_MODE_UND), \ - .disc_mode = (BLE_GAP_DISC_MODE_GEN), +.conn_mode = (BLE_GAP_CONN_MODE_UND), \ +.disc_mode = (BLE_GAP_DISC_MODE_GEN), #define ADV_OPT_PROXY \ - .conn_mode = (BLE_GAP_CONN_MODE_UND), \ - .disc_mode = (BLE_GAP_DISC_MODE_GEN), +.conn_mode = (BLE_GAP_CONN_MODE_UND), \ +.disc_mode = (BLE_GAP_DISC_MODE_GEN), #define ADV_SLOW_INT \ - .itvl_min = BT_GAP_ADV_SLOW_INT_MIN, \ - .itvl_max = BT_GAP_ADV_SLOW_INT_MAX, +.itvl_min = BT_GAP_ADV_SLOW_INT_MIN, \ +.itvl_max = BT_GAP_ADV_SLOW_INT_MAX, #define ADV_FAST_INT \ - .itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, \ - .itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, +.itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, \ +.itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, -static bool proxy_adv_enabled; +static bool gatt_adv_enabled; -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) +static struct { + uint16_t proxy_h; + uint16_t proxy_data_out_h; + uint16_t prov_h; + uint16_t prov_data_in_h; + uint16_t prov_data_out_h; +} svc_handles; + +#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) static void proxy_send_beacons(struct ble_npl_event *work); -#endif +static void proxy_filter_recv(uint16_t conn_handle, + struct bt_mesh_net_rx *rx, struct os_mbuf *buf); +#endif /* CONFIG_BT_MESH_GATT_PROXY */ -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) +#if MYNEWT_VAL(BLE_MESH_PB_GATT) static bool prov_fast_adv; +#endif /* CONFIG_BT_MESH_PB_GATT */ + +static int proxy_send(uint16_t conn_handle, + const void *data, uint16_t len, + void (*end)(uint16_t, void *), void *user_data); + +#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) + static bool prov_fast_adv; #endif static struct bt_mesh_proxy_client { - uint16_t conn_handle; + struct bt_mesh_proxy_role cli; uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)]; enum __packed { NONE, @@ -129,16 +138,22 @@ static struct bt_mesh_proxy_client { BLACKLIST, PROV, } filter_type; - uint8_t msg_type; -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) +#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) struct ble_npl_callout send_beacons; -#endif - struct k_work_delayable sar_timer; - struct os_mbuf *buf; -} clients[MYNEWT_VAL(BLE_MAX_CONNECTIONS)] = { - [0 ... (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1)] = { 0 }, +#endif /* CONFIG_BT_MESH_GATT_PROXY */ +} clients[CONFIG_BT_MAX_CONN] = { + [0 ... (CONFIG_BT_MAX_CONN - 1)] = { + .cli.cb = { + .send = proxy_send, +#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) + .recv = proxy_filter_recv, +#endif /* CONFIG_BT_MESH_GATT_PROXY */ + }, + }, }; +//static uint8_t __noinit client_buf_data[CLIENT_BUF_SIZE * CONFIG_BT_MAX_CONN]; + /* Track which service is enabled */ static enum { MESH_GATT_NONE, @@ -146,73 +161,55 @@ static enum { MESH_GATT_PROXY, } gatt_svc = MESH_GATT_NONE; -static struct { - uint16_t proxy_h; - uint16_t proxy_data_out_h; - uint16_t prov_h; - uint16_t prov_data_in_h; - uint16_t prov_data_out_h; -} svc_handles; +static int conn_count; -static void resolve_svc_handles(void) +static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) { - int rc; + int i; - /* Either all handles are already resolved, or none of them */ - if (svc_handles.prov_data_out_h) { - return; + for (i = 0; i < ARRAY_SIZE(clients); i++) { + if (clients[i].cli.conn_handle == conn_handle) { + return &clients[i]; + } } - /* - * We assert if attribute is not found since at this stage all attributes - * shall be already registered and thus shall be found. - */ - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - &svc_handles.proxy_h); - assert(rc == 0); + return NULL; +} - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - NULL, &svc_handles.proxy_data_out_h); - assert(rc == 0); +#define ATTR_IS_PROV(attr) (attr->user_data != NULL) - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - &svc_handles.prov_h); - assert(rc == 0); +static ssize_t gatt_recv(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + struct bt_mesh_proxy_client *client = find_client(conn_handle); + const uint8_t *data = ctxt->om->om_data; + uint16_t len = ctxt->om->om_len; - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - NULL, &svc_handles.prov_data_in_h); - assert(rc == 0); + client = find_client(conn_handle); - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - NULL, &svc_handles.prov_data_out_h); - assert(rc == 0); -} + if (!client) { + return -ENOTCONN; + } -static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) -{ - int i; + if (len < 1) { + BT_WARN("Too small Proxy PDU"); + return -EINVAL; + } - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle == conn_handle) { - return &clients[i]; - } + if ((attr_handle == svc_handles.prov_data_in_h) != + (PDU_TYPE(data) == BT_MESH_PROXY_PROV)) { + BT_WARN("Proxy PDU type doesn't match GATT service"); + return -EINVAL; } - return NULL; + return bt_mesh_proxy_msg_recv(&client->cli, data, len); } -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) + +#if defined(CONFIG_BT_MESH_GATT_PROXY) /* Next subnet in queue to be advertised */ static struct bt_mesh_subnet *beacon_sub; -static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, - struct os_mbuf *msg, - void (*end)(uint16_t, void *), void *user_data); - static int filter_set(struct bt_mesh_proxy_client *client, struct os_mbuf *buf) { @@ -227,17 +224,17 @@ static int filter_set(struct bt_mesh_proxy_client *client, BT_DBG("type 0x%02x", type); switch (type) { - case 0x00: - memset(client->filter, 0, sizeof(client->filter)); - client->filter_type = WHITELIST; - break; - case 0x01: - memset(client->filter, 0, sizeof(client->filter)); - client->filter_type = BLACKLIST; - break; - default: - BT_WARN("Prohibited Filter Type 0x%02x", type); - return -EINVAL; + case 0x00: + (void)memset(client->filter, 0, sizeof(client->filter)); + client->filter_type = WHITELIST; + break; + case 0x01: + (void)memset(client->filter, 0, sizeof(client->filter)); + client->filter_type = BLACKLIST; + break; + default: + BT_WARN("Prohibited Filter Type 0x%02x", type); + return -EINVAL; } return 0; @@ -310,7 +307,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, net_buf_simple_add_u8(buf, 0x01); } - for (filter_size = 0, i = 0; i < ARRAY_SIZE(client->filter); i++) { + for (filter_size = 0U, i = 0; i < ARRAY_SIZE(client->filter); i++) { if (client->filter[i] != BT_MESH_ADDR_UNASSIGNED) { filter_size++; } @@ -326,79 +323,55 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, return; } - err = proxy_segment_and_send(client->conn_handle, BT_MESH_PROXY_CONFIG, buf, - NULL, NULL); + err = bt_mesh_proxy_msg_send(&client->cli, BT_MESH_PROXY_CONFIG, + buf, NULL, NULL); if (err) { BT_ERR("Failed to send proxy cfg message (err %d)", err); } } -static void proxy_cfg(struct bt_mesh_proxy_client *client) +static void proxy_filter_recv(uint16_t conn_handle, + struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { - struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_NET_MAX_PDU_LEN); - struct bt_mesh_net_rx rx; + struct bt_mesh_proxy_client *client; uint8_t opcode; - int err; - - err = bt_mesh_net_decode(client->buf, BT_MESH_NET_IF_PROXY_CFG, - &rx, buf); - if (err) { - BT_ERR("Failed to decode Proxy Configuration (err %d)", err); - goto done; - } - - rx.local_match = 1U; - if (bt_mesh_rpl_check(&rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", - rx.ctx.addr, rx.ctx.recv_dst, rx.seq); - goto done; - } - - /* Remove network headers */ - net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN); - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_len < 1) { - BT_WARN("Too short proxy configuration PDU"); - goto done; + client = find_client(conn_handle); + if (!client) { + return; } opcode = net_buf_simple_pull_u8(buf); switch (opcode) { case CFG_FILTER_SET: filter_set(client, buf); - send_filter_status(client, &rx, buf); + send_filter_status(client, rx, buf); break; - case CFG_FILTER_ADD: - while (buf->om_len >= 2) { - uint16_t addr; + case CFG_FILTER_ADD: + while (buf->om_len >= 2) { + uint16_t addr; - addr = net_buf_simple_pull_be16(buf); - filter_add(client, addr); - } - send_filter_status(client, &rx, buf); - break; - case CFG_FILTER_REMOVE: - while (buf->om_len >= 2) { - uint16_t addr; + addr = net_buf_simple_pull_be16(buf); + filter_add(client, addr); + } + send_filter_status(client, rx, buf); + break; + case CFG_FILTER_REMOVE: + while (buf->om_len >= 2) { + uint16_t addr; - addr = net_buf_simple_pull_be16(buf); - filter_remove(client, addr); - } - send_filter_status(client, &rx, buf); - break; - default: - BT_WARN("Unhandled configuration OpCode 0x%02x", opcode); - break; + addr = net_buf_simple_pull_be16(buf); + filter_remove(client, addr); + } + send_filter_status(client, rx, buf); + break; + default: + BT_WARN("Unhandled configuration OpCode 0x%02x", opcode); + break; } - -done: - os_mbuf_free_chain(buf); } -static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub) +static int beacon_send(struct bt_mesh_proxy_client *client, struct bt_mesh_subnet *sub) { struct os_mbuf *buf = NET_BUF_SIMPLE(23); int rc; @@ -406,7 +379,7 @@ static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub) net_buf_simple_init(buf, 1); bt_mesh_beacon_create(sub, buf); - rc = proxy_segment_and_send(conn_handle, BT_MESH_PROXY_BEACON, buf, + rc = bt_mesh_proxy_msg_send(&client->cli, BT_MESH_PROXY_BEACON, buf, NULL, NULL); os_mbuf_free_chain(buf); return rc; @@ -416,7 +389,7 @@ static int send_beacon_cb(struct bt_mesh_subnet *sub, void *cb_data) { struct bt_mesh_proxy_client *client = cb_data; - return beacon_send(client->conn_handle, sub); + return beacon_send(client, sub); } static void proxy_send_beacons(struct ble_npl_event *work) @@ -428,27 +401,6 @@ static void proxy_send_beacons(struct ble_npl_event *work) (void)bt_mesh_subnet_find(send_beacon_cb, client); } -static void proxy_sar_timeout(struct ble_npl_event *work) -{ - struct bt_mesh_proxy_client *client; - int rc; - client = ble_npl_event_get_arg(work); - - if (!client->conn_handle) { - return; - } - - if (!client->buf->om_len) { - BT_DBG("No pending Proxy SAR message"); - return; - } - - BT_WARN("Proxy SAR timeout"); - rc = ble_gap_terminate(client->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); -} - void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub) { int i; @@ -460,8 +412,8 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub) } for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle != BLE_HS_CONN_HANDLE_NONE) { - beacon_send(clients[i].conn_handle, sub); + if (clients[i].cli.conn_handle) { + beacon_send(&clients[i], sub); } } } @@ -475,14 +427,15 @@ static void node_id_start(struct bt_mesh_subnet *sub) void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub) { node_id_start(sub); + /* Prioritize the recently enabled subnet */ beacon_sub = sub; } void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub) -{ + { sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED; - sub->node_id_start = 0; + sub->node_id_start = 0U; } int bt_mesh_proxy_identity_enable(void) @@ -500,306 +453,250 @@ int bt_mesh_proxy_identity_enable(void) return 0; } -#endif /* GATT_PROXY */ - -static void proxy_complete_pdu(struct bt_mesh_proxy_client *client) -{ - switch (client->msg_type) { -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - case BT_MESH_PROXY_NET_PDU: - BT_INFO("Mesh Network PDU"); - bt_mesh_net_recv(client->buf, 0, BT_MESH_NET_IF_PROXY); - break; - case BT_MESH_PROXY_BEACON: - BT_INFO("Mesh Beacon PDU"); - bt_mesh_beacon_recv(client->buf); - break; - case BT_MESH_PROXY_CONFIG: - BT_INFO("Mesh Configuration PDU"); - proxy_cfg(client); - break; -#endif -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - case BT_MESH_PROXY_PROV: - BT_INFO("Mesh Provisioning PDU"); - bt_mesh_pb_gatt_recv(client->conn_handle, client->buf); - break; -#endif - default: - BT_WARN("Unhandled Message Type 0x%02x", client->msg_type); - break; - } +#define ID_TYPE_NET 0x00 +#define ID_TYPE_NODE 0x01 - net_buf_simple_init(client->buf, 0); -} +#define NODE_ID_LEN 19 +#define NET_ID_LEN 11 -static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - struct bt_mesh_proxy_client *client = find_client(conn_handle); - const uint8_t *data = ctxt->om->om_data; - uint16_t len = ctxt->om->om_len; +#define NODE_ID_TIMEOUT (CONFIG_BT_MESH_NODE_ID_TIMEOUT * MSEC_PER_SEC) - client = find_client(conn_handle); +static uint8_t proxy_svc_data[NODE_ID_LEN] = { + BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL), +}; - if (!client) { - return -ENOTCONN; - } +static const struct bt_data node_id_ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, + BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)), + BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN), +}; - if (len < 1) { - BT_WARN("Too small Proxy PDU"); - return -EINVAL; - } +static const struct bt_data net_id_ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, + BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)), + BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN), +}; - if ((attr_handle == svc_handles.prov_data_in_h) != - (PDU_TYPE(data) == BT_MESH_PROXY_PROV)) { - BT_WARN("Proxy PDU type doesn't match GATT service"); - return -EINVAL; - } +static int node_id_adv(struct bt_mesh_subnet *sub) +{ + struct ble_gap_adv_params fast_adv_param = { + ADV_OPT_PROXY + ADV_FAST_INT + }; +#if ADV_OPT_USE_NAME + const char *name = CONFIG_BT_DEVICE_NAME; + size_t name_len = strlen(name); + struct bt_data sd = { + .type = BT_DATA_NAME_COMPLETE, + .data_len = name_len, + .data = (void *)name + }; +#else + struct bt_data *sd = NULL; +#endif + uint8_t tmp[16]; + int err; - if (len - 1 > net_buf_simple_tailroom(client->buf)) { - BT_WARN("Too big proxy PDU"); - return -EINVAL; - } + BT_DBG(""); - switch (PDU_SAR(data)) { - case SAR_COMPLETE: - if (client->buf->om_len) { - BT_WARN("Complete PDU while a pending incomplete one"); - return -EINVAL; - } + proxy_svc_data[2] = ID_TYPE_NODE; - client->msg_type = PDU_TYPE(data); - net_buf_simple_add_mem(client->buf, data + 1, len - 1); - proxy_complete_pdu(client); - break; + err = bt_rand(proxy_svc_data + 11, 8); + if (err) { + return err; + } - case SAR_FIRST: - if (client->buf->om_len) { - BT_WARN("First PDU while a pending incomplete one"); - return -EINVAL; - } + (void)memset(tmp, 0, 6); + memcpy(tmp + 6, proxy_svc_data + 11, 8); + sys_put_be16(bt_mesh_primary_addr(), tmp + 14); - k_work_reschedule(&client->sar_timer, PROXY_SAR_TIMEOUT); - client->msg_type = PDU_TYPE(data); - net_buf_simple_add_mem(client->buf, data + 1, len - 1); - break; + err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp, + tmp); + if (err) { + return err; + } - case SAR_CONT: - if (!client->buf->om_len) { - BT_WARN("Continuation with no prior data"); - return -EINVAL; - } + memcpy(proxy_svc_data + 3, tmp + 8, 8); - if (client->msg_type != PDU_TYPE(data)) { - BT_WARN("Unexpected message type in continuation"); - return -EINVAL; - } + err = bt_le_adv_start(&fast_adv_param, node_id_ad, + ARRAY_SIZE(node_id_ad), sd, 0); + if (err) { + BT_WARN("Failed to advertise using Node ID (err %d)", err); + return err; + } - k_work_reschedule(&client->sar_timer, PROXY_SAR_TIMEOUT); - net_buf_simple_add_mem(client->buf, data + 1, len - 1); - break; + return 0; +} - case SAR_LAST: - if (!client->buf->om_len) { - BT_WARN("Last SAR PDU with no prior data"); - return -EINVAL; - } - - if (client->msg_type != PDU_TYPE(data)) { - BT_WARN("Unexpected message type in last SAR PDU"); - return -EINVAL; - } - - /* If this fails, the work handler exits early, as there's no - * active SAR buffer. - */ - (void)k_work_cancel_delayable(&client->sar_timer); - net_buf_simple_add_mem(client->buf, data + 1, len - 1); - proxy_complete_pdu(client); - break; - } - - return len; -} - -static int conn_count; - -static void proxy_connected(uint16_t conn_handle) +static int net_id_adv(struct bt_mesh_subnet *sub) { - struct bt_mesh_proxy_client *client; - int i; - - BT_INFO("conn_handle %d", conn_handle); + struct ble_gap_adv_params slow_adv_param = { + ADV_OPT_PROXY + ADV_SLOW_INT + }; +#if ADV_OPT_USE_NAME + const char *name = CONFIG_BT_DEVICE_NAME; + size_t name_len = strlen(name); + struct bt_data sd = { + .type = BT_DATA_NAME_COMPLETE, + .data_len = name_len, + .data = (void *)name + }; +#else + struct bt_data *sd = NULL; +#endif + int err; - conn_count++; + BT_DBG(""); - /* Since we use ADV_OPT_ONE_TIME */ - proxy_adv_enabled = false; + proxy_svc_data[2] = ID_TYPE_NET; - /* Try to re-enable advertising in case it's possible */ - if (conn_count < CONFIG_BT_MAX_CONN) { - bt_mesh_adv_update(); - } + BT_DBG("Advertising with NetId %s", + bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8)); - for (client = NULL, i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle == BLE_HS_CONN_HANDLE_NONE) { - client = &clients[i]; - break; - } - } + memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8); - if (!client) { - BT_ERR("No free Proxy Client objects"); - return; + err = bt_le_adv_start(&slow_adv_param, net_id_ad, + ARRAY_SIZE(net_id_ad), sd, 0); + if (err) { + BT_WARN("Failed to advertise using Network ID (err %d)", err); + return err; } - client->conn_handle = conn_handle; - client->filter_type = NONE; - memset(client->filter, 0, sizeof(client->filter)); - net_buf_simple_init(client->buf, 0); + return 0; } -static void proxy_disconnected(uint16_t conn_handle, int reason) +static bool advertise_subnet(struct bt_mesh_subnet *sub) { - int i; - - BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason); - conn_count--; + if (sub->net_idx == BT_MESH_KEY_UNUSED) { + return false; + } - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; + return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING || + bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED); +} - if (client->conn_handle == conn_handle) { - if ((MYNEWT_VAL(BLE_MESH_PB_GATT)) && - client->filter_type == PROV) { - bt_mesh_pb_gatt_close(conn_handle); - } +static struct bt_mesh_subnet *next_sub(void) +{ + struct bt_mesh_subnet *sub = NULL; - /* If this fails, the work handler exits early, as - * there's no active connection. - */ - (void)k_work_cancel_delayable(&client->sar_timer); - client->conn_handle = BLE_HS_CONN_HANDLE_NONE; - break; + if (!beacon_sub) { + beacon_sub = bt_mesh_subnet_next(NULL); + if (!beacon_sub) { + /* No valid subnets */ + return NULL; } } - bt_mesh_adv_update(); + sub = beacon_sub; + do { + if (advertise_subnet(sub)) { + beacon_sub = sub; + return sub; + } + + sub = bt_mesh_subnet_next(sub); + } while (sub != beacon_sub); + + /* No subnets to advertise on */ + return NULL; } -struct os_mbuf *bt_mesh_proxy_get_buf(void) +static int sub_count_cb(struct bt_mesh_subnet *sub, void *cb_data) { - struct os_mbuf *buf = clients[0].buf; + int *count = cb_data; - if (buf != NULL) { - net_buf_simple_init(buf, 0); + if (advertise_subnet(sub)) { + (*count)++; } - return buf; + return 0; } -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -static void prov_ccc_write(uint16_t conn_handle) +static int sub_count(void) { - struct bt_mesh_proxy_client *client; - - BT_DBG("conn_handle %d", conn_handle); + int count = 0; - /* If a connection exists there must be a client */ - client = find_client(conn_handle); - __ASSERT(client, "No client for connection"); + (void)bt_mesh_subnet_find(sub_count_cb, &count); - if (client->filter_type == NONE) { - client->filter_type = PROV; - bt_mesh_pb_gatt_open(conn_handle); - } + return count; } -int bt_mesh_proxy_prov_enable(void) +static int gatt_proxy_advertise(struct bt_mesh_subnet *sub) { - uint16_t handle; - int rc; - int i; + int32_t remaining = K_FOREVER; + int subnet_count; BT_DBG(""); - if (gatt_svc == MESH_GATT_PROV) { - return -EALREADY; + if (conn_count == CONFIG_BT_MAX_CONN) { + BT_DBG("Connectable advertising deferred (max connections %d)", conn_count); + return -ENOMEM; } - if (gatt_svc != MESH_GATT_NONE) { - return -EBUSY; + sub = beacon_sub ? beacon_sub : bt_mesh_subnet_next(beacon_sub); + if (!sub) { + BT_WARN("No subnets to advertise on"); + return -ENOENT; } - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 1); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - - gatt_svc = MESH_GATT_PROV; - prov_fast_adv = true; + if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) { + uint32_t active = k_uptime_get_32() - sub->node_id_start; - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle != BLE_HS_CONN_HANDLE_NONE) { - clients[i].filter_type = PROV; + if (active < NODE_ID_TIMEOUT) { + remaining = NODE_ID_TIMEOUT - active; + BT_DBG("Node ID active for %u ms, %d ms remaining", + (unsigned) active, (int) remaining); + node_id_adv(sub); + } else { + bt_mesh_proxy_identity_stop(sub); + BT_DBG("Node ID stopped"); } } + if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) { + net_id_adv(sub); + } - return 0; -} - -int bt_mesh_proxy_prov_disable(bool disconnect) -{ - uint16_t handle; - int rc; - int i; - - BT_DBG(""); + subnet_count = sub_count(); + BT_DBG("sub_count %u", subnet_count); + if (subnet_count > 1) { + int32_t max_timeout; - if (gatt_svc == MESH_GATT_NONE) { - return -EALREADY; - } + /* We use NODE_ID_TIMEOUT as a starting point since it may + * be less than 60 seconds. Divide this period into at least + * 6 slices, but make sure that a slice is at least one + * second long (to avoid excessive rotation). + */ + max_timeout = NODE_ID_TIMEOUT / max(subnet_count, 6); + max_timeout = max(max_timeout, K_SECONDS(1)); - if (gatt_svc != MESH_GATT_PROV) { - return -EBUSY; + if (remaining > max_timeout || remaining < 0) { + remaining = max_timeout; + } } - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 0); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - - gatt_svc = MESH_GATT_NONE; + BT_DBG("Advertising %d ms for net_idx 0x%04x", + (int) remaining, sub->net_idx); - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; + beacon_sub = bt_mesh_subnet_next(beacon_sub); - if ((client->conn_handle == BLE_HS_CONN_HANDLE_NONE) - || (client->filter_type != PROV)) { - continue; - } + return remaining; +} - if (disconnect) { - rc = ble_gap_terminate(client->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); - } else { - bt_mesh_pb_gatt_close(client->conn_handle); - client->filter_type = NONE; +static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) +{ + if (evt == BT_MESH_KEY_DELETED) { + if (sub == beacon_sub) { + beacon_sub = NULL; } + } else { + bt_mesh_proxy_beacon_send(sub); } - - bt_mesh_adv_update(); - - return 0; } -#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */ -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) static void proxy_ccc_write(uint16_t conn_handle) { struct bt_mesh_proxy_client *client; @@ -841,11 +738,10 @@ int bt_mesh_proxy_gatt_enable(void) gatt_svc = MESH_GATT_PROXY; for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle != BLE_HS_CONN_HANDLE_NONE) { + if (clients[i].cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) { clients[i].filter_type = WHITELIST; } } - return 0; } @@ -859,11 +755,11 @@ void bt_mesh_proxy_gatt_disconnect(void) for (i = 0; i < ARRAY_SIZE(clients); i++) { struct bt_mesh_proxy_client *client = &clients[i]; - if ((client->conn_handle != BLE_HS_CONN_HANDLE_NONE) && + if ((client->cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) && (client->filter_type == WHITELIST || client->filter_type == BLACKLIST)) { client->filter_type = NONE; - rc = ble_gap_terminate(client->conn_handle, + rc = ble_gap_terminate(client->cli.conn_handle, BLE_ERR_REM_USER_CONN_TERM); assert(rc == 0); } @@ -874,7 +770,6 @@ int bt_mesh_proxy_gatt_disable(void) { uint16_t handle; int rc; - BT_DBG(""); if (gatt_svc == MESH_GATT_NONE) { @@ -892,7 +787,6 @@ int bt_mesh_proxy_gatt_disable(void) ble_gatts_svc_set_visibility(handle, 0); /* FIXME: figure out end handle */ ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff); - gatt_svc = MESH_GATT_NONE; return 0; @@ -900,17 +794,8 @@ int bt_mesh_proxy_gatt_disable(void) void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr) { - struct bt_mesh_proxy_client *client = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - client = &clients[i]; - if (client->buf == buf) { - break; - } - } - - assert(client); + struct bt_mesh_proxy_client *client = + CONTAINER_OF(buf, struct bt_mesh_proxy_client, cli.buf); BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); @@ -973,7 +858,7 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) struct bt_mesh_proxy_client *client = &clients[i]; struct os_mbuf *msg; - if (client->conn_handle == BLE_HS_CONN_HANDLE_NONE) { + if (client->cli.conn_handle == BLE_HS_CONN_HANDLE_NONE) { continue; } @@ -993,12 +878,13 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) net_buf_simple_init(msg, 1); net_buf_simple_add_mem(msg, buf->om_data, buf->om_len); - err = proxy_segment_and_send(client->conn_handle, BT_MESH_PROXY_NET_PDU, + err = bt_mesh_proxy_msg_send(&client->cli, BT_MESH_PROXY_NET_PDU, msg, buf_send_end, net_buf_ref(buf)); adv_send_start(0, err, cb, cb_data); if (err) { BT_ERR("Failed to send proxy message (err %d)", err); + /* If segment_and_send() fails the buf_send_end() callback will * not be called, so we need to clear the user data (net_buf, * which is just opaque data to segment_and send) reference given @@ -1014,354 +900,282 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) return relayed; } -#endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */ -static int proxy_send(uint16_t conn_handle, - const void *data, uint16_t len, - void (*end)(uint16_t, void *), void *user_data) +static void proxy_sar_timeout(struct ble_npl_event *work) { - struct os_mbuf *om; - int err = 0; + struct bt_mesh_proxy_role *role; + int rc; + role = ble_npl_event_get_arg(work); - BT_DBG("%u bytes: %s", len, bt_hex(data, len)); -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - if (gatt_svc == MESH_GATT_PROXY) { - om = ble_hs_mbuf_from_flat(data, len); - assert(om); - err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); - /* We do not pass cb into ble_gattc_notify_custom - execute it at the end */ - } -#endif + BT_WARN("Proxy SAR timeout"); -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - if (gatt_svc == MESH_GATT_PROV) { - om = ble_hs_mbuf_from_flat(data, len); - assert(om); - err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); + if (role->conn_handle) { + rc = ble_gap_terminate(role->conn_handle, + BLE_ERR_REM_USER_CONN_TERM); + assert(rc == 0); } -#endif - - end(conn_handle, user_data); - return err; } +#endif /* CONFIG_BT_MESH_GATT_PROXY */ -static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, - struct os_mbuf *msg, - void (*end)(uint16_t, void *), void *user_data) +static void gatt_connected(uint16_t conn_handle) { - int err; - uint16_t mtu; - - BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len, - bt_hex(msg->om_data, msg->om_len)); + struct bt_mesh_proxy_client *client; - /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */ - mtu = ble_att_mtu(conn_handle) - 3; - if (mtu > msg->om_len) { - net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); - return proxy_send(conn_handle, msg->om_data, msg->om_len, end, user_data); - } + BT_DBG("conn %d", conn_handle); - net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); - err = proxy_send(conn_handle, msg->om_data, mtu, NULL, NULL); - if (err) { - return err; - } - net_buf_simple_pull_mem(msg, mtu); + conn_count++; - while (msg->om_len) { - if (msg->om_len + 1 < mtu) { - net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); - err = proxy_send(conn_handle, msg->om_data, msg->om_len, end, user_data); - if (err) { - return err; - } - break; - } + /* Since we use ADV_OPT_ONE_TIME */ + gatt_adv_enabled = false; - net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); - err = proxy_send(conn_handle, msg->om_data, mtu, NULL, NULL); - if (err) { - return err; - } - net_buf_simple_pull_mem(msg, mtu); + /* Try to re-enable advertising in case it's possible */ + if (conn_count < CONFIG_BT_MAX_CONN) { + bt_mesh_adv_update(); } - return 0; -} - -int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, - void (*end)(uint16_t, void *), void *user_data) -{ - struct bt_mesh_proxy_client *client = find_client(conn_handle); - + client = find_client(BLE_HS_CONN_HANDLE_NONE); if (!client) { - BT_ERR("No Proxy Client found"); - return -ENOTCONN; - } - - if (client->filter_type == PROV) { - BT_ERR("Invalid PDU type for Proxy Client"); - return -EINVAL; + BT_ERR("No free Proxy Client objects"); + return; } - return proxy_segment_and_send(conn_handle, BT_MESH_PROXY_PROV, buf, end, user_data); + client->cli.conn_handle = conn_handle; + client->filter_type = NONE; + (void)memset(client->filter, 0, sizeof(client->filter)); + net_buf_simple_init(client->cli.buf, 0); } -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -static uint8_t prov_svc_data[20] = { - BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL), -}; - -static const struct bt_data prov_ad[] = { - BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, - BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)), - BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), -}; -#endif /* PB_GATT */ +static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) +{ + int i; -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) + BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason); -#define ID_TYPE_NET 0x00 -#define ID_TYPE_NODE 0x01 + conn_count--; -#define NODE_ID_LEN 19 -#define NET_ID_LEN 11 + for (i = 0; i < ARRAY_SIZE(clients); i++) { + struct bt_mesh_proxy_client *client = &clients[i]; -#define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BT_MESH_NODE_ID_TIMEOUT) + if (client->cli.conn_handle != conn_handle) { + continue; + } -static uint8_t proxy_svc_data[NODE_ID_LEN] = { - BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL), -}; + if ((MYNEWT_VAL(BLE_MESH_PB_GATT)) && + client->filter_type == PROV) { + bt_mesh_pb_gatt_close(conn_handle); + } -static const struct bt_data node_id_ad[] = { - BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, - BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)), - BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN), -}; + /* If this fails, the work handler exits early, as + * there's no active connection. + */ + (void)k_work_cancel_delayable(&client->cli.sar_timer); + client->cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; + break; + } -static const struct bt_data net_id_ad[] = { - BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, - BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)), - BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN), -}; + bt_mesh_adv_update(); +} -static int node_id_adv(struct bt_mesh_subnet *sub) +struct os_mbuf *bt_mesh_proxy_get_buf(void) { - struct ble_gap_adv_params fast_adv_param = { - ADV_OPT_PROXY - ADV_FAST_INT - }; -#if ADV_OPT_USE_NAME - const char *name = CONFIG_BT_DEVICE_NAME; - size_t name_len = strlen(name); - struct bt_data sd = { - .type = BT_DATA_NAME_COMPLETE, - .data_len = name_len, - .data = (void *)name - }; -#else - struct bt_data *sd = NULL; -#endif - uint8_t tmp[16]; - int err; - - BT_DBG(""); + struct os_mbuf *buf = clients[0].cli.buf; - proxy_svc_data[2] = ID_TYPE_NODE; - - err = bt_rand(proxy_svc_data + 11, 8); - if (err) { - return err; + if (buf != NULL) { + net_buf_simple_init(buf, 0); } - memset(tmp, 0, 6); - memcpy(tmp + 6, proxy_svc_data + 11, 8); - sys_put_be16(bt_mesh_primary_addr(), tmp + 14); - - err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp, - tmp); - if (err) { - return err; - } + return buf; +} - memcpy(proxy_svc_data + 3, tmp + 8, 8); +#if defined(CONFIG_BT_MESH_PB_GATT) +static void prov_ccc_write(uint16_t conn_handle) +{ + struct bt_mesh_proxy_client *client; - err = bt_le_adv_start(&fast_adv_param, node_id_ad, - ARRAY_SIZE(node_id_ad), sd, 0); - if (err) { - BT_WARN("Failed to advertise using Node ID (err %d)", err); - return err; - } + BT_DBG("conn_handle %d", conn_handle); - proxy_adv_enabled = true; + /* If a connection exists there must be a client */ + client = find_client(conn_handle); + __ASSERT(client, "No client for connection"); - return 0; + if (client->filter_type == NONE) { + client->filter_type = PROV; + bt_mesh_pb_gatt_open(conn_handle); + } } -static int net_id_adv(struct bt_mesh_subnet *sub) +static int +dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { - struct ble_gap_adv_params slow_adv_param = { - ADV_OPT_PROXY - ADV_SLOW_INT - }; -#if ADV_OPT_USE_NAME - const char *name = CONFIG_BT_DEVICE_NAME; - size_t name_len = strlen(name); - struct bt_data sd = { - .type = BT_DATA_NAME_COMPLETE, - .data_len = name_len, - .data = (void *)name - }; -#else - struct bt_data *sd = NULL; -#endif - int err; - - BT_DBG(""); + /* + * We should never never enter this callback - it's attached to notify-only + * characteristic which are notified directly from mbuf. And we can't pass + * NULL as access_cb because gatts will assert on init... + */ + BLE_HS_DBG_ASSERT(0); + return 0; +} - proxy_svc_data[2] = ID_TYPE_NET; +static const struct ble_gatt_svc_def svc_defs [] = { + { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), + .access_cb = gatt_recv, + .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, + }, { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), + .access_cb = dummy_access_cb, + .flags = BLE_GATT_CHR_F_NOTIFY, + }, { + 0, /* No more characteristics in this service. */ + } }, + }, { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), + .access_cb = gatt_recv, + .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, + }, { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), + .access_cb = dummy_access_cb, + .flags = BLE_GATT_CHR_F_NOTIFY, + }, { + 0, /* No more characteristics in this service. */ + } }, + }, { + 0, /* No more services. */ + }, +}; - BT_DBG("Advertising with NetId %s", - bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8)); +int bt_mesh_proxy_svcs_register(void) +{ + int rc; - memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8); - err = bt_le_adv_start(&slow_adv_param, net_id_ad, - ARRAY_SIZE(net_id_ad), sd, 0); - if (err) { - BT_WARN("Failed to advertise using Network ID (err %d)", err); - return err; - } + rc = ble_gatts_count_cfg(svc_defs); + assert(rc == 0); - proxy_adv_enabled = true; + rc = ble_gatts_add_svcs(svc_defs); + assert(rc == 0); return 0; } -static bool advertise_subnet(struct bt_mesh_subnet *sub) +int bt_mesh_proxy_prov_enable(void) { - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - return false; - } - - return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING || - bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED); -} + uint16_t handle; + int rc; + int i; -static struct bt_mesh_subnet *next_sub(void) -{ - struct bt_mesh_subnet *sub = NULL; + BT_DBG(""); - if (!beacon_sub) { - beacon_sub = bt_mesh_subnet_next(NULL); - if (!beacon_sub) { - /* No valid subnets */ - return NULL; - } + if (gatt_svc == MESH_GATT_PROV) { + return -EALREADY; } - sub = beacon_sub; - do { - if (advertise_subnet(sub)) { - beacon_sub = sub; - return sub; - } - - sub = bt_mesh_subnet_next(sub); - } while (sub != beacon_sub); - - /* No subnets to advertise on */ + if (gatt_svc != MESH_GATT_NONE) { + return -EBUSY; + } - return NULL; -} + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); + assert(rc == 0); + ble_gatts_svc_set_visibility(handle, 1); + /* FIXME: figure out end handle */ + ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); -static int sub_count_cb(struct bt_mesh_subnet *sub, void *cb_data) -{ - int *count = cb_data; + gatt_svc = MESH_GATT_PROV; + prov_fast_adv = true; - if (advertise_subnet(sub)) { - (*count)++; + for (i = 0; i < ARRAY_SIZE(clients); i++) { + if (clients[i].cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) { + clients[i].filter_type = PROV; + } } - return 0; -} - -static int sub_count(void) -{ - int count = 0; - (void)bt_mesh_subnet_find(sub_count_cb, &count); - return count; + return 0; } -static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) +int bt_mesh_proxy_prov_disable(bool disconnect) { - int32_t remaining = K_FOREVER; - int subnet_count; + uint16_t handle; + int rc; + int i; BT_DBG(""); - if (conn_count == CONFIG_BT_MAX_CONN) { - BT_DBG("Connectable advertising deferred (max connections %d)", conn_count); - return -ENOMEM; + if (gatt_svc == MESH_GATT_NONE) { + return -EALREADY; } - sub = beacon_sub ? beacon_sub : bt_mesh_subnet_next(beacon_sub); - if (!sub) { - BT_WARN("No subnets to advertise on"); - return -ENOENT; + if (gatt_svc != MESH_GATT_PROV) { + return -EBUSY; } - if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) { - uint32_t active = k_uptime_get_32() - sub->node_id_start; + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); + assert(rc == 0); + ble_gatts_svc_set_visibility(handle, 0); + /* FIXME: figure out end handle */ + ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - if (active < NODE_ID_TIMEOUT) { - remaining = NODE_ID_TIMEOUT - active; - BT_DBG("Node ID active for %u ms, %d ms remaining", - (unsigned) active, (int) remaining); - node_id_adv(sub); + gatt_svc = MESH_GATT_NONE; + + for (i = 0; i < ARRAY_SIZE(clients); i++) { + struct bt_mesh_proxy_client *client = &clients[i]; + + if (client->cli.conn_handle == BLE_HS_CONN_HANDLE_NONE + || client->filter_type != PROV) { + continue; + } + + if (disconnect) { + rc = ble_gap_terminate(client->cli.conn_handle, + BLE_ERR_REM_USER_CONN_TERM); + assert(rc == 0); } else { - bt_mesh_proxy_identity_stop(sub); - BT_DBG("Node ID stopped"); + bt_mesh_pb_gatt_close(client->cli.conn_handle); + client->filter_type = NONE; } } - if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) { - net_id_adv(sub); - } + bt_mesh_adv_update(); - subnet_count = sub_count(); - BT_DBG("sub_count %u", subnet_count); - if (subnet_count > 1) { - int32_t max_timeout; + return 0; +} - /* We use NODE_ID_TIMEOUT as a starting point since it may - * be less than 60 seconds. Divide this period into at least - * 6 slices, but make sure that a slice is at least one - * second long (to avoid excessive rotation). - */ - max_timeout = NODE_ID_TIMEOUT / max(subnet_count, 6); - max_timeout = max(max_timeout, K_SECONDS(1)); +static uint8_t prov_svc_data[20] = { + BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL), +}; - if (remaining > max_timeout || remaining < 0) { - remaining = max_timeout; - } - } +static const struct bt_data prov_ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, + BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)), + BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), +}; - BT_DBG("Advertising %d ms for net_idx 0x%04x", - (int) remaining, sub->net_idx); +int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, + void (*end)(uint16_t, void *), void *user_data) +{ + struct bt_mesh_proxy_client *client = find_client(conn_handle); - beacon_sub = bt_mesh_subnet_next(beacon_sub); + if (!client) { + BT_ERR("No Proxy Client found"); + return -ENOTCONN; + } - return remaining; + if (client->filter_type != PROV) { + BT_ERR("Invalid PDU type for Proxy Client"); + return -EINVAL; + } + + return bt_mesh_proxy_msg_send(&client->cli, BT_MESH_PROXY_PROV, buf, end, user_data); } -#endif /* GATT_PROXY */ -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) static size_t gatt_prov_adv_create(struct bt_data prov_sd[2]) { const struct bt_mesh_prov *prov = bt_mesh_prov_get(); @@ -1405,7 +1219,37 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[2]) return prov_sd_len; } -#endif /* PB_GATT */ +#endif /* CONFIG_BT_MESH_PB_GATT */ + +static int proxy_send(uint16_t conn_handle, + const void *data, uint16_t len, + void (*end)(uint16_t, void *), void *user_data) +{ + struct os_mbuf *om; + int err = 0; + + BT_DBG("%u bytes: %s", len, bt_hex(data, len)); + +#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) + if (gatt_svc == MESH_GATT_PROXY) { + om = ble_hs_mbuf_from_flat(data, len); + assert(om); + err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); + /* We do not pass cb into ble_gattc_notify_custom - execute it at the end */ + } +#endif + +#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) + if (gatt_svc == MESH_GATT_PROV) { + om = ble_hs_mbuf_from_flat(data, len); + assert(om); + err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); + } +#endif + + end(conn_handle, user_data); + return err; +} int32_t bt_mesh_proxy_adv_start(void) { @@ -1439,7 +1283,7 @@ int32_t bt_mesh_proxy_adv_start(void) if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad), prov_sd, prov_sd_len) == 0) { - proxy_adv_enabled = true; + gatt_adv_enabled = true; /* Advertise 60 seconds using fast interval */ if (prov_fast_adv) { @@ -1459,36 +1303,6 @@ int32_t bt_mesh_proxy_adv_start(void) return K_FOREVER; } -void bt_mesh_proxy_adv_stop(void) -{ - int err; - - BT_DBG("adv_enabled %u", proxy_adv_enabled); - - if (!proxy_adv_enabled) { - return; - } - - err = bt_le_adv_stop(true); - if (err) { - BT_ERR("Failed to stop advertising (err %d)", err); - } else { - proxy_adv_enabled = false; - } -} - -#if defined(CONFIG_BT_MESH_GATT_PROXY) -static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) -{ - if (evt == BT_MESH_KEY_DELETED) { - if (sub == beacon_sub) { - beacon_sub = NULL; - } - } else { - bt_mesh_proxy_beacon_send(sub); - } -} -#endif static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) { @@ -1513,7 +1327,7 @@ static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) } #else if (event->type == BLE_GAP_EVENT_CONNECT) { - proxy_connected(event->connect.conn_handle); + gatt_connected(event->connect.conn_handle); } #endif } @@ -1521,10 +1335,10 @@ static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) { if ((event->type == BLE_GAP_EVENT_CONNECT) || - (event->type == BLE_GAP_EVENT_ADV_COMPLETE)) { + (event->type == BLE_GAP_EVENT_ADV_COMPLETE)) { ble_mesh_handle_connect(event, arg); } else if (event->type == BLE_GAP_EVENT_DISCONNECT) { - proxy_disconnected(event->disconnect.conn.conn_handle, + gatt_disconnected(event->disconnect.conn.conn_handle, event->disconnect.reason); } else if (event->type == BLE_GAP_EVENT_SUBSCRIBE) { if (event->subscribe.attr_handle == svc_handles.proxy_data_out_h) { @@ -1532,7 +1346,7 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) proxy_ccc_write(event->subscribe.conn_handle); #endif } else if (event->subscribe.attr_handle == - svc_handles.prov_data_out_h) { + svc_handles.prov_data_out_h) { #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) prov_ccc_write(event->subscribe.conn_handle); #endif @@ -1542,93 +1356,89 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) return 0; } -static int -dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) + +void bt_mesh_proxy_adv_stop(void) { - /* - * We should never never enter this callback - it's attached to notify-only - * characteristic which are notified directly from mbuf. And we can't pass - * NULL as access_cb because gatts will assert on init... - */ - BLE_HS_DBG_ASSERT(0); - return 0; -} + int err; -static const struct ble_gatt_svc_def svc_defs [] = { - { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), - .access_cb = proxy_recv, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - .access_cb = proxy_recv, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, { - 0, /* No more services. */ - }, -}; + BT_DBG("adv_enabled %u", gatt_adv_enabled); -int bt_mesh_proxy_svcs_register(void) + if (!gatt_adv_enabled) { + return; + } + + err = bt_le_adv_stop(true); + if (err) { + BT_ERR("Failed to stop advertising (err %d)", err); + } else { + gatt_adv_enabled = false; + } +} + +static void resolve_svc_handles(void) { int rc; - rc = ble_gatts_count_cfg(svc_defs); + /* Either all handles are already resolved, or none of them */ + if (svc_handles.prov_data_out_h) { + return; + } + + /* + * We assert if attribute is not found since at this stage all attributes + * shall be already registered and thus shall be found. + */ + + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), + &svc_handles.proxy_h); assert(rc == 0); - rc = ble_gatts_add_svcs(svc_defs); + rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), + BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), + NULL, &svc_handles.proxy_data_out_h); assert(rc == 0); - return 0; + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + &svc_handles.prov_h); + assert(rc == 0); + + rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), + NULL, &svc_handles.prov_data_in_h); + assert(rc == 0); + + rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), + NULL, &svc_handles.prov_data_out_h); + assert(rc == 0); } + int bt_mesh_proxy_init(void) { - int i; + int i; -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - if (!bt_mesh_subnet_cb_list[4]) { - bt_mesh_subnet_cb_list[4] = subnet_evt; - } -#endif + #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) + if (!bt_mesh_subnet_cb_list[4]) { + bt_mesh_subnet_cb_list[4] = subnet_evt; + } + #endif - for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) { -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - k_work_init(&clients[i].send_beacons, proxy_send_beacons); -#endif - clients[i].buf = NET_BUF_SIMPLE(CLIENT_BUF_SIZE); - clients[i].conn_handle = BLE_HS_CONN_HANDLE_NONE; + for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) { + #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) + k_work_init(&clients[i].send_beacons, proxy_send_beacons); + #endif + clients[i].cli.buf = NET_BUF_SIMPLE(CLIENT_BUF_SIZE); + clients[i].cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; - k_work_init_delayable(&clients[i].sar_timer, proxy_sar_timeout); - k_work_add_arg_delayable(&clients[i].sar_timer, &clients[i]); - } + k_work_init_delayable(&clients[i].cli.sar_timer, proxy_sar_timeout); + k_work_add_arg_delayable(&clients[i].cli.sar_timer, &clients[i]); + } - resolve_svc_handles(); + resolve_svc_handles(); - ble_gatts_svc_set_visibility(svc_handles.proxy_h, 0); - ble_gatts_svc_set_visibility(svc_handles.prov_h, 0); + ble_gatts_svc_set_visibility(svc_handles.proxy_h, 0); + ble_gatts_svc_set_visibility(svc_handles.prov_h, 0); return 0; -} - -#endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ +} \ No newline at end of file diff --git a/nimble/host/mesh/src/proxy.h b/nimble/host/mesh/src/proxy.h index 27124901f2..2ddb834ea1 100644 --- a/nimble/host/mesh/src/proxy.h +++ b/nimble/host/mesh/src/proxy.h @@ -9,9 +9,6 @@ #ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ #define ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ -int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, - void (*end)(uint16_t, void *), void *user_data); - #define BT_MESH_PROXY_NET_PDU 0x00 #define BT_MESH_PROXY_BEACON 0x01 #define BT_MESH_PROXY_CONFIG 0x02 @@ -20,6 +17,9 @@ int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, #include "mesh/mesh.h" #include "mesh/slist.h" +int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, + void (*end)(uint16_t, void *), void *user_data); + int bt_mesh_proxy_prov_enable(void); int bt_mesh_proxy_prov_disable(bool disconnect); diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c new file mode 100644 index 0000000000..4c4d694029 --- /dev/null +++ b/nimble/host/mesh/src/proxy_msg.c @@ -0,0 +1,231 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2021 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "syscfg/syscfg.h" +#define MESH_LOG_MODULE BLE_MESH_PROXY_LOG + +#if MYNEWT_VAL(BLE_MESH_PROXY) + +#include "mesh/mesh.h" +#include "host/ble_att.h" +#include "services/gatt/ble_svc_gatt.h" +#include "../../host/src/ble_hs_priv.h" + +#include "mesh_priv.h" +#include "adv.h" +#include "net.h" +#include "rpl.h" +#include "prov.h" +#include "beacon.h" +#include "foundation.h" +#include "access.h" +#include "proxy.h" +#include "proxy_msg.h" + +#define PDU_SAR(data) (data[0] >> 6) + +#define BT_UUID_16_ENCODE(w16) \ + (((w16) >> 0) & 0xFF), \ + (((w16) >> 8) & 0xFF) +/* Mesh Profile 1.0 Section 6.6: + * "The timeout for the SAR transfer is 20 seconds. When the timeout + * expires, the Proxy Server shall disconnect." + */ +#define PROXY_SAR_TIMEOUT K_SECONDS(20) + +#define SAR_COMPLETE 0x00 +#define SAR_FIRST 0x01 +#define SAR_CONT 0x02 +#define SAR_LAST 0x03 + +#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) + + +#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) +static void proxy_cfg(struct bt_mesh_proxy_role *role) +{ + struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_NET_MAX_PDU_LEN); + struct bt_mesh_net_rx rx; + int err; + + err = bt_mesh_net_decode(role->buf, BT_MESH_NET_IF_PROXY_CFG, + &rx, buf); + if (err) { + BT_ERR("Failed to decode Proxy Configuration (err %d)", err); + goto done; + } + + rx.local_match = 1U; + + if (bt_mesh_rpl_check(&rx, NULL)) { + BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + rx.ctx.addr, rx.ctx.recv_dst, rx.seq); + goto done; + } + + /* Remove network headers */ + net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN); + + BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); + + if (buf->om_len < 1) { + BT_WARN("Too short proxy configuration PDU"); + goto done; + } + + role->cb.recv(role->conn_handle, &rx, buf); +done: + os_mbuf_free_chain(buf); +} +#endif /* GATT_PROXY */ + +static void proxy_complete_pdu(struct bt_mesh_proxy_role *role) +{ + switch (role->msg_type) { +#if defined(CONFIG_BT_MESH_PROXY) + case BT_MESH_PROXY_NET_PDU: + BT_INFO("Mesh Network PDU"); + bt_mesh_net_recv(role->buf, 0, BT_MESH_NET_IF_PROXY); + break; + case BT_MESH_PROXY_BEACON: + BT_INFO("Mesh Beacon PDU"); + bt_mesh_beacon_recv(role->buf); + break; + case BT_MESH_PROXY_CONFIG: + BT_INFO("Mesh Configuration PDU"); + proxy_cfg(role); + break; +#endif +#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) + case BT_MESH_PROXY_PROV: + BT_INFO("Mesh Provisioning PDU"); + bt_mesh_pb_gatt_recv(role->conn_handle, role->buf); + break; +#endif + default: + BT_WARN("Unhandled Message Type 0x%02x", role->msg_type); + break; + } + + net_buf_simple_init(role->buf, 0); +} + +ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, + const void *buf, uint16_t len) +{ + const uint8_t *data = buf; + + switch (PDU_SAR(data)) { + case SAR_COMPLETE: + if (role->buf->om_len) { + BT_WARN("Complete PDU while a pending incomplete one"); + return -EINVAL; + } + + role->msg_type = PDU_TYPE(data); + net_buf_simple_add_mem(role->buf, data + 1, len - 1); + proxy_complete_pdu(role); + break; + + case SAR_FIRST: + if (role->buf->om_len) { + BT_WARN("First PDU while a pending incomplete one"); + return -EINVAL; + } + + k_work_reschedule(&role->sar_timer, PROXY_SAR_TIMEOUT); + role->msg_type = PDU_TYPE(data); + net_buf_simple_add_mem(role->buf, data + 1, len - 1); + break; + + case SAR_CONT: + if (!role->buf->om_len) { + BT_WARN("Continuation with no prior data"); + return -EINVAL; + } + + if (role->msg_type != PDU_TYPE(data)) { + BT_WARN("Unexpected message type in continuation"); + return -EINVAL; + } + + k_work_reschedule(&role->sar_timer, PROXY_SAR_TIMEOUT); + net_buf_simple_add_mem(role->buf, data + 1, len - 1); + break; + + case SAR_LAST: + if (!role->buf->om_len) { + BT_WARN("Last SAR PDU with no prior data"); + return -EINVAL; + } + + if (role->msg_type != PDU_TYPE(data)) { + BT_WARN("Unexpected message type in last SAR PDU"); + return -EINVAL; + } + + /* If this fails, the work handler exits early, as there's no + * active SAR buffer. + */ + (void)k_work_cancel_delayable(&role->sar_timer); + net_buf_simple_add_mem(role->buf, data + 1, len - 1); + proxy_complete_pdu(role); + break; + } + + return len; +} + +int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, + struct os_mbuf *msg, + void (*end)(uint16_t, void *), void *user_data) +{ + int err; + uint16_t mtu; + uint16_t conn_handle = role->conn_handle; + + BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len, + bt_hex(msg->om_data, msg->om_len)); + + /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */ + mtu = ble_att_mtu(conn_handle) - 3; + if (mtu > msg->om_len) { + net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); + return role->cb.send(conn_handle, msg->om_data, msg->om_len, end, user_data); + } + + net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); + err = role->cb.send(conn_handle, msg->om_data, mtu, NULL, NULL); + if (err) { + return err; + } + net_buf_simple_pull_mem(msg, mtu); + + while (msg->om_len) { + if (msg->om_len + 1 < mtu) { + net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); + err = role->cb.send(conn_handle, msg->om_data, msg->om_len, end, user_data); + if (err) { + return err; + } + break; + } + + net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); + err = role->cb.send(conn_handle, msg->om_data, mtu, NULL, NULL); + if (err) { + return err; + } + net_buf_simple_pull_mem(msg, mtu); + } + + return 0; +} + +#endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ diff --git a/nimble/host/mesh/src/proxy_msg.h b/nimble/host/mesh/src/proxy_msg.h new file mode 100644 index 0000000000..2a9f046c99 --- /dev/null +++ b/nimble/host/mesh/src/proxy_msg.h @@ -0,0 +1,47 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2021 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_MSG_H_ +#define ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_MSG_H_ + +#define PDU_TYPE(data) (data[0] & BIT_MASK(6)) +#define CFG_FILTER_SET 0x00 +#define CFG_FILTER_ADD 0x01 +#define CFG_FILTER_REMOVE 0x02 +#define CFG_FILTER_STATUS 0x03 + +#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) + +typedef int (*proxy_send_cb_t)(uint16_t conn_handle, + const void *data, uint16_t len, + void (*end)(uint16_t, void *), void *user_data); + +typedef void (*proxy_recv_cb_t)(uint16_t conn_handle, + struct bt_mesh_net_rx *rx, struct os_mbuf *buf); + +struct bt_mesh_proxy_role { + uint16_t conn_handle; + uint8_t msg_type; + + struct { + proxy_send_cb_t send; + proxy_recv_cb_t recv; + } cb; + + struct k_work_delayable sar_timer; + struct os_mbuf *buf; +}; + +ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, + const void *buf, uint16_t len); +int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, + struct os_mbuf *msg, void (*end)(uint16_t, void *), void *user_data); +void bt_mesh_proxy_msg_init(struct bt_mesh_proxy_role *role); + +#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_MSG_H_ */ diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index dcde094443..58d227c691 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -100,11 +100,20 @@ syscfg.defs: BLE_MESH_GATT_PROXY is set. value: 0 + BLE_MESH_GATT: + value: 1 + + BLE_MESH_GATT_SERVER: + value: 1 + restrictions: BLE_MESH_GATT + BLE_MESH_PB_GATT: description: > Enable this option to allow the device to be provisioned over the GATT bearer. value: 1 + restrictions: + - '(BLE_MESH_GATT_SERVER && BLE_MESH_PROV)' BLE_MESH_GATT_PROXY: description: > @@ -112,6 +121,8 @@ syscfg.defs: i.e. the ability to act as a proxy between a Mesh GATT Client and a Mesh network. value: 1 + restrictions: + - '(BLE_MESH_GATT_SERVER && BLE_MESH_PROXY)' BLE_MESH_GATT_PROXY_ENABLED: description: > @@ -140,6 +151,7 @@ syscfg.defs: This option specifies how many Proxy Filter entries the local node supports. value: 1 + restrictions: BLE_MESH_GATT_SERVER BLE_MESH_PROXY_USE_DEVICE_NAME: description: > From 610fbc4005b0869b8ce4cee2aba9ea59b5a2c6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 13 Oct 2021 16:07:08 +0200 Subject: [PATCH 188/306] host/mesh: Add return value for opcode callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` 3.7.3.4 Message error procedure When receiving a message that is not understood by an element, it shall ignore the message. Note: A message can be falsely identified as a valid message, passing the NetMIC and TransMIC authentication using a known network key and application key even though that message was sent using different keys. The decryption of that message using the wrong keys would result in a message that is not understood by the element. The probability of such a situation occurring is small but not insignificant. A message that is not understood includes messages that have one or more of the following conditions: • The application opcode is unknown by the receiving element. • The access message size for the application opcode is incorrect. • The application parameters contain values that are currently Prohibited. Note: An element that sends an acknowledged message that is not understood by a peer node will not receive any response message. ``` This is port of b9422ea9f3f937e2d95b72ba993b9dbae901916d --- nimble/host/mesh/include/mesh/access.h | 6 +- nimble/host/mesh/src/access.c | 2 +- nimble/host/mesh/src/cfg_cli.c | 223 ++++++----- nimble/host/mesh/src/cfg_srv.c | 524 ++++++++++++++----------- nimble/host/mesh/src/health_cli.c | 40 +- nimble/host/mesh/src/health_srv.c | 94 +++-- nimble/host/mesh/src/model_cli.c | 12 +- nimble/host/mesh/src/model_srv.c | 64 +-- 8 files changed, 555 insertions(+), 410 deletions(-) diff --git a/nimble/host/mesh/include/mesh/access.h b/nimble/host/mesh/include/mesh/access.h index c3f36f43a0..de64f74f38 100644 --- a/nimble/host/mesh/include/mesh/access.h +++ b/nimble/host/mesh/include/mesh/access.h @@ -148,9 +148,9 @@ struct bt_mesh_model_op { const size_t min_len; /* Message handler for the opcode */ - void (*const func)(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf); + int (*const func)(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf); }; #define BT_MESH_MODEL_OP_1(b0) (b0) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 359d8c4e27..95e199c8dc 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -668,7 +668,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) * receive the message. */ net_buf_simple_save(buf, &state); - op->func(model, &rx->ctx, buf); + (void)op->func(model, &rx->ctx, buf); net_buf_simple_restore(buf, &state); } } diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index dc56f992d5..a1a88f0acb 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -33,9 +33,9 @@ static int32_t msg_timeout = K_SECONDS(5); static struct bt_mesh_cfg_cli *cli; -static void comp_data_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int comp_data_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct comp_data *param; size_t to_copy; @@ -46,7 +46,7 @@ static void comp_data_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_DEV_COMP_DATA_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } if (param->page) { @@ -56,12 +56,14 @@ static void comp_data_status(struct bt_mesh_model *model, net_buf_simple_add_mem(param->comp, buf->om_data, to_copy); bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } -static void state_status_u8(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf, - uint32_t expect_status) +static int state_status_u8(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf, + uint32_t expect_status) { uint8_t *status; @@ -71,40 +73,42 @@ static void state_status_u8(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, expect_status, ctx->addr, (void **)&status)) { - return; + return -ENOENT; } *status = net_buf_simple_pull_u8(buf); bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } -static void beacon_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int beacon_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { - state_status_u8(model, ctx, buf, OP_BEACON_STATUS); + return state_status_u8(model, ctx, buf, OP_BEACON_STATUS); } -static void ttl_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) +static int ttl_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf) { - state_status_u8(model, ctx, buf, OP_DEFAULT_TTL_STATUS); + return state_status_u8(model, ctx, buf, OP_DEFAULT_TTL_STATUS); } -static void friend_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) +static int friend_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf) { - state_status_u8(model, ctx, buf, OP_FRIEND_STATUS); + return state_status_u8(model, ctx, buf, OP_FRIEND_STATUS); } -static void gatt_proxy_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) +static int gatt_proxy_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf) { - state_status_u8(model, ctx, buf, OP_GATT_PROXY_STATUS); + return state_status_u8(model, ctx, buf, OP_GATT_PROXY_STATUS); } struct relay_param { @@ -112,9 +116,9 @@ struct relay_param { uint8_t *transmit; }; -static void relay_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) +static int relay_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf) { struct relay_param *param; @@ -124,18 +128,20 @@ static void relay_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_RELAY_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } *param->status = net_buf_simple_pull_u8(buf); *param->transmit = net_buf_simple_pull_u8(buf); bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } -static void net_transmit_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int net_transmit_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint8_t *status; @@ -145,12 +151,14 @@ static void net_transmit_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_TRANSMIT_STATUS, ctx->addr, (void **)&status)) { - return; + return -ENOENT; } *status = net_buf_simple_pull_u8(buf); bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } struct net_key_param { @@ -158,9 +166,9 @@ struct net_key_param { uint16_t net_idx; }; -static void net_key_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int net_key_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct net_key_param *param; uint16_t net_idx; @@ -172,7 +180,7 @@ static void net_key_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_KEY_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } status = net_buf_simple_pull_u8(buf); @@ -180,7 +188,7 @@ static void net_key_status(struct bt_mesh_model *model, if (param->net_idx != net_idx) { BT_WARN("Net Key Status key index does not match"); - return; + return -ENOENT; } if (param->status) { @@ -188,6 +196,8 @@ static void net_key_status(struct bt_mesh_model *model, } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } struct net_key_list_param { @@ -195,9 +205,9 @@ struct net_key_list_param { size_t *key_cnt; }; -static void net_key_list(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int net_key_list(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct net_key_list_param *param; int i; @@ -208,7 +218,7 @@ static void net_key_list(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_KEY_LIST, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) { @@ -222,10 +232,13 @@ static void net_key_list(struct bt_mesh_model *model, *param->key_cnt = i; bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } -static void node_reset_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) +static int node_reset_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { bool *param = NULL; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x", @@ -233,13 +246,15 @@ static void node_reset_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NODE_RESET_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } if (param) { *param = true; } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } struct app_key_param { @@ -248,9 +263,9 @@ struct app_key_param { uint16_t app_idx; }; -static void app_key_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) +static int app_key_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf) { struct app_key_param *param; uint16_t net_idx, app_idx; @@ -262,7 +277,7 @@ static void app_key_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_APP_KEY_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } status = net_buf_simple_pull_u8(buf); @@ -270,7 +285,7 @@ static void app_key_status(struct bt_mesh_model *model, if (param->net_idx != net_idx || param->app_idx != app_idx) { BT_WARN("App Key Status key indices did not match"); - return; + return -ENOENT; } if (param->status) { @@ -278,6 +293,8 @@ static void app_key_status(struct bt_mesh_model *model, } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } struct app_key_list_param { @@ -287,9 +304,9 @@ struct app_key_list_param { size_t *key_cnt; }; -static void app_key_list(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int app_key_list(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct app_key_list_param *param; uint16_t net_idx; @@ -302,7 +319,7 @@ static void app_key_list(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_APP_KEY_LIST, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } status = net_buf_simple_pull_u8(buf); @@ -310,7 +327,7 @@ static void app_key_list(struct bt_mesh_model *model, if (param->net_idx != net_idx) { BT_WARN("App Key List Net Key index did not match"); - return; + return -ENOENT; } for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) { @@ -327,6 +344,8 @@ static void app_key_list(struct bt_mesh_model *model, } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } struct mod_app_param { @@ -337,9 +356,9 @@ struct mod_app_param { uint16_t cid; }; -static void mod_app_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) +static int mod_app_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf) { uint16_t elem_addr, mod_app_idx, mod_id, cid; struct mod_app_param *param; @@ -351,7 +370,7 @@ static void mod_app_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_APP_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } status = net_buf_simple_pull_u8(buf); @@ -370,7 +389,7 @@ static void mod_app_status(struct bt_mesh_model *model, param->mod_app_idx != mod_app_idx || param->mod_id != mod_id || param->cid != cid) { BT_WARN("Model App Status parameters did not match"); - return; + return -ENOENT; } if (param->status) { @@ -378,6 +397,8 @@ static void mod_app_status(struct bt_mesh_model *model, } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } struct mod_member_list_param { @@ -389,9 +410,9 @@ struct mod_member_list_param { size_t *member_cnt; }; -static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf, bool vnd, - struct mod_member_list_param *param) +static int mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf, bool vnd, + struct mod_member_list_param *param) { uint16_t elem_addr, mod_id, cid; uint8_t status; @@ -408,12 +429,12 @@ static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, if (param->elem_addr != elem_addr || param->mod_id != mod_id || (vnd && param->cid != cid)) { BT_WARN("Model Member List parameters did not match"); - return; + return -ENOENT; } if (buf->om_len % 2) { BT_WARN("Model Member List invalid length"); - return; + return -ENOENT; } for (i = 0; i < *param->member_cnt && buf->om_len; i++) { @@ -426,9 +447,11 @@ static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } -static void mod_app_list(struct bt_mesh_model *model, +static int mod_app_list(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -440,13 +463,13 @@ static void mod_app_list(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SIG_MOD_APP_LIST, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } - mod_member_list_handle(ctx, buf, false, param); + return mod_member_list_handle(ctx, buf, false, param); } -static void mod_app_list_vnd(struct bt_mesh_model *model, +static int mod_app_list_vnd(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -458,10 +481,10 @@ static void mod_app_list_vnd(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_VND_MOD_APP_LIST, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } - mod_member_list_handle(ctx, buf, true, param); + return mod_member_list_handle(ctx, buf, true, param); } struct mod_pub_param { @@ -472,7 +495,7 @@ struct mod_pub_param { struct bt_mesh_cfg_mod_pub *pub; }; -static void mod_pub_status(struct bt_mesh_model *model, +static int mod_pub_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf*buf) { @@ -487,13 +510,13 @@ static void mod_pub_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_PUB_STATUS, ctx->addr, (void **)¶m)) { BT_WARN("Unexpected Model Pub Status message"); - return; + return -ENOENT; } if (param->cid != CID_NVAL) { if (buf->om_len < 14) { BT_WARN("Unexpected Mod Pub Status with SIG Model"); - return; + return -ENOENT; } cid = sys_get_le16(&buf->om_data[10]); @@ -501,7 +524,7 @@ static void mod_pub_status(struct bt_mesh_model *model, } else { if (buf->om_len > 12) { BT_WARN("Unexpected Mod Pub Status with Vendor Model"); - return; + return -ENOENT; } cid = CID_NVAL; @@ -510,7 +533,7 @@ static void mod_pub_status(struct bt_mesh_model *model, if (mod_id != param->mod_id || cid != param->cid) { BT_WARN("Mod Pub Model ID or Company ID mismatch"); - return; + return -ENOENT; } status = net_buf_simple_pull_u8(buf); @@ -519,7 +542,7 @@ static void mod_pub_status(struct bt_mesh_model *model, if (elem_addr != param->elem_addr) { BT_WARN("Model Pub Status for unexpected element (0x%04x)", elem_addr); - return; + return -ENOENT; } if (param->status) { @@ -537,6 +560,8 @@ static void mod_pub_status(struct bt_mesh_model *model, } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } struct mod_sub_param { @@ -548,9 +573,9 @@ struct mod_sub_param { uint16_t cid; }; -static void mod_sub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) +static int mod_sub_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf) { uint16_t elem_addr, sub_addr, mod_id, cid; struct mod_sub_param *param; @@ -562,7 +587,7 @@ static void mod_sub_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } status = net_buf_simple_pull_u8(buf); @@ -581,7 +606,7 @@ static void mod_sub_status(struct bt_mesh_model *model, (param->expect_sub && *param->expect_sub != sub_addr) || param->cid != cid) { BT_WARN("Model Subscription Status parameters did not match"); - return; + return -ENOENT; } if (param->sub_addr) { @@ -593,11 +618,13 @@ static void mod_sub_status(struct bt_mesh_model *model, } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } -static void mod_sub_list(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_list(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct mod_member_list_param *param; @@ -607,13 +634,13 @@ static void mod_sub_list(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_LIST, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } - mod_member_list_handle(ctx, buf, false, param); + return mod_member_list_handle(ctx, buf, false, param); } -static void mod_sub_list_vnd(struct bt_mesh_model *model, +static int mod_sub_list_vnd(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -625,10 +652,10 @@ static void mod_sub_list_vnd(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_LIST_VND, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } - mod_member_list_handle(ctx, buf, true,param); + return mod_member_list_handle(ctx, buf, true,param); } struct hb_sub_param { @@ -636,9 +663,9 @@ struct hb_sub_param { struct bt_mesh_cfg_hb_sub *sub; }; -static void hb_sub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) +static int hb_sub_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf*buf) { struct hb_sub_param *param; @@ -648,7 +675,7 @@ static void hb_sub_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_HEARTBEAT_SUB_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } *param->status = net_buf_simple_pull_u8(buf); @@ -661,6 +688,8 @@ static void hb_sub_status(struct bt_mesh_model *model, param->sub->max = net_buf_simple_pull_u8(buf); bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } struct hb_pub_param { @@ -668,7 +697,7 @@ struct hb_pub_param { struct bt_mesh_cfg_hb_pub *pub; }; -static void hb_pub_status(struct bt_mesh_model *model, +static int hb_pub_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -680,7 +709,7 @@ static void hb_pub_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_HEARTBEAT_PUB_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } *param->status = net_buf_simple_pull_u8(buf); @@ -695,6 +724,8 @@ static void hb_pub_status(struct bt_mesh_model *model, } bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; } const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 734faa7c8f..f5518fd12e 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -109,12 +109,13 @@ static int comp_get_page_0(struct os_mbuf *buf) return 0; } -static void dev_comp_data_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int dev_comp_data_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); uint8_t page; + int err; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -129,7 +130,8 @@ static void dev_comp_data_get(struct bt_mesh_model *model, bt_mesh_model_msg_init(sdu, OP_DEV_COMP_DATA_STATUS); net_buf_simple_add_u8(sdu, page); - if (comp_get_page_0(sdu) < 0) { + err = comp_get_page_0(sdu); + if (err) { BT_ERR("Unable to get composition page 0"); goto done; } @@ -140,6 +142,7 @@ static void dev_comp_data_get(struct bt_mesh_model *model, done: os_mbuf_free_chain(sdu); + return err; } static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, @@ -319,10 +322,10 @@ uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store) return STATUS_SUCCESS; } -static void send_app_key_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - uint8_t status, - uint16_t app_idx, uint16_t net_idx) +static int send_app_key_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + uint8_t status, + uint16_t app_idx, uint16_t net_idx) { struct os_mbuf *msg = NET_BUF_SIMPLE( BT_MESH_MODEL_BUF_LEN(OP_APP_KEY_STATUS, 4)); @@ -336,11 +339,12 @@ static void send_app_key_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -static void app_key_add(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int app_key_add(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t key_net_idx, key_app_idx; uint8_t status; @@ -351,10 +355,10 @@ static void app_key_add(struct bt_mesh_model *model, status = bt_mesh_app_key_add(key_app_idx, key_net_idx, buf->om_data); - send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); + return send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); } -static void app_key_update(struct bt_mesh_model *model, +static int app_key_update(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -367,7 +371,7 @@ static void app_key_update(struct bt_mesh_model *model, status = bt_mesh_app_key_update(key_app_idx, key_net_idx, buf->om_data); BT_DBG("status 0x%02x", status); - send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); + return send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); } static void mod_app_key_del(struct bt_mesh_model *mod, @@ -387,9 +391,9 @@ static void app_key_evt(uint16_t app_idx, uint16_t net_idx, } } -static void app_key_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int app_key_del(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t key_net_idx, key_app_idx; uint8_t status; @@ -400,15 +404,15 @@ static void app_key_del(struct bt_mesh_model *model, status = bt_mesh_app_key_del(key_app_idx, key_net_idx); - send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); + return send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); } /* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */ #define IDX_LEN(num) (((num) / 2) * 3 + ((num) % 2) * 2) -static void app_key_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int app_key_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_LIST, @@ -418,10 +422,12 @@ static void app_key_get(struct bt_mesh_model *model, uint8_t status; ssize_t count; int i; + int err = 0; get_idx = net_buf_simple_pull_le16(buf); if (get_idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", get_idx); + err = -EINVAL; goto done; } @@ -461,10 +467,11 @@ static void app_key_get(struct bt_mesh_model *model, } done: - os_mbuf_free_chain(msg); + os_mbuf_free_chain(msg); + return err; } -static void beacon_get(struct bt_mesh_model *model, +static int beacon_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -480,13 +487,16 @@ static void beacon_get(struct bt_mesh_model *model, if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send Config Beacon Status response"); } + + return 0; os_mbuf_free_chain(msg); } -static void beacon_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int beacon_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { + int err = 0; struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_BEACON_STATUS, 1); BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -495,6 +505,7 @@ static void beacon_set(struct bt_mesh_model *model, if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { BT_WARN("Invalid Config Beacon value 0x%02x", buf->om_data[0]); + err = -EINVAL; goto done; } @@ -509,12 +520,12 @@ static void beacon_set(struct bt_mesh_model *model, done: os_mbuf_free_chain(msg); - + return err; } -static void default_ttl_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int default_ttl_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1); @@ -530,12 +541,12 @@ static void default_ttl_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); - + return 0; } -static void default_ttl_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int default_ttl_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1); int err; @@ -559,9 +570,10 @@ static void default_ttl_set(struct bt_mesh_model *model, done: os_mbuf_free_chain(msg); + return err; } -static void send_gatt_proxy_status(struct bt_mesh_model *model, +static int send_gatt_proxy_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_GATT_PROXY_STATUS, 1); @@ -575,20 +587,21 @@ static void send_gatt_proxy_status(struct bt_mesh_model *model, os_mbuf_free_chain(msg); + return 0; } -static void gatt_proxy_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int gatt_proxy_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - send_gatt_proxy_status(model, ctx); + return send_gatt_proxy_status(model, ctx); } -static void gatt_proxy_set(struct bt_mesh_model *model, +static int gatt_proxy_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -598,15 +611,15 @@ static void gatt_proxy_set(struct bt_mesh_model *model, if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { BT_WARN("Invalid GATT Proxy value 0x%02x", buf->om_data[0]); - return; + return -EINVAL; } (void)bt_mesh_gatt_proxy_set(buf->om_data[0]); - send_gatt_proxy_status(model, ctx); + return send_gatt_proxy_status(model, ctx); } -static void net_transmit_get(struct bt_mesh_model *model, +static int net_transmit_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -625,11 +638,12 @@ static void net_transmit_get(struct bt_mesh_model *model, os_mbuf_free_chain(msg); + return 0; } -static void net_transmit_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int net_transmit_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1); @@ -651,9 +665,11 @@ static void net_transmit_set(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void relay_get(struct bt_mesh_model *model, +static int relay_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -673,13 +689,15 @@ static void relay_get(struct bt_mesh_model *model, os_mbuf_free_chain(msg); + return 0; } -static void relay_set(struct bt_mesh_model *model, +static int relay_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_STATUS, 2); + int err = 0; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -687,6 +705,7 @@ static void relay_set(struct bt_mesh_model *model, if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { BT_WARN("Invalid Relay value 0x%02x", buf->om_data[0]); + err = -EINVAL; goto done; } @@ -702,14 +721,14 @@ static void relay_set(struct bt_mesh_model *model, done: os_mbuf_free_chain(msg); - + return err; } -static void send_mod_pub_status(struct bt_mesh_model *cfg_mod, - struct bt_mesh_msg_ctx *ctx, - uint16_t elem_addr, uint16_t pub_addr, - bool vnd, struct bt_mesh_model *mod, - uint8_t status, uint8_t *mod_id) +static int send_mod_pub_status(struct bt_mesh_model *cfg_mod, + struct bt_mesh_msg_ctx *ctx, + uint16_t elem_addr, uint16_t pub_addr, + bool vnd, struct bt_mesh_model *mod, + uint8_t status, uint8_t *mod_id) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_STATUS, 14); @@ -743,11 +762,12 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod, } os_mbuf_free_chain(msg); + return 0; } -static void mod_pub_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_pub_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t elem_addr, pub_addr = 0; struct bt_mesh_model *mod; @@ -758,7 +778,7 @@ static void mod_pub_get(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } mod_id = buf->om_data; @@ -788,11 +808,11 @@ static void mod_pub_get(struct bt_mesh_model *model, status = STATUS_SUCCESS; send_status: - send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); + return send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, + status, mod_id); } -static void mod_pub_set(struct bt_mesh_model *model, +static int mod_pub_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -806,7 +826,7 @@ static void mod_pub_set(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } pub_addr = net_buf_simple_pull_le16(buf); @@ -817,7 +837,7 @@ static void mod_pub_set(struct bt_mesh_model *model, pub_ttl = net_buf_simple_pull_u8(buf); if (pub_ttl > BT_MESH_TTL_MAX && pub_ttl != BT_MESH_TTL_DEFAULT) { BT_ERR("Invalid TTL value 0x%02x", pub_ttl); - return; + return -EINVAL; } pub_period = net_buf_simple_pull_u8(buf); @@ -850,8 +870,8 @@ static void mod_pub_set(struct bt_mesh_model *model, pub_period, retransmit, true); send_status: - send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); + return send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, + status, mod_id); } static size_t mod_sub_list_clear(struct bt_mesh_model *mod) @@ -886,9 +906,9 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod) return clear_count; } -static void mod_pub_va_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_pub_va_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint8_t retransmit, status, pub_ttl, pub_period, cred_flag; uint16_t elem_addr, pub_addr, pub_app_idx; @@ -901,7 +921,7 @@ static void mod_pub_va_set(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } label_uuid = net_buf_simple_pull_mem(buf, 16); @@ -911,7 +931,7 @@ static void mod_pub_va_set(struct bt_mesh_model *model, pub_ttl = net_buf_simple_pull_u8(buf); if (pub_ttl > BT_MESH_TTL_MAX && pub_ttl != BT_MESH_TTL_DEFAULT) { BT_ERR("Invalid TTL value 0x%02x", pub_ttl); - return; + return -EINVAL; } pub_period = net_buf_simple_pull_u8(buf); @@ -953,14 +973,14 @@ static void mod_pub_va_set(struct bt_mesh_model *model, } send_status: - send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); + return send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, + status, mod_id); } -static void send_mod_sub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, uint8_t status, - uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id, - bool vnd) +static int send_mod_sub_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, uint8_t status, + uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id, + bool vnd) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_SUB_STATUS, 9); @@ -984,11 +1004,13 @@ static void send_mod_sub_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void mod_sub_add(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_add(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; @@ -1001,7 +1023,7 @@ static void mod_sub_add(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } sub_addr = net_buf_simple_pull_le16(buf); @@ -1055,13 +1077,13 @@ static void mod_sub_add(struct bt_mesh_model *model, send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, + mod_id, vnd); } -static void mod_sub_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_del(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; @@ -1074,7 +1096,7 @@ static void mod_sub_del(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } sub_addr = net_buf_simple_pull_le16(buf); @@ -1121,8 +1143,8 @@ static void mod_sub_del(struct bt_mesh_model *model, } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, + mod_id, vnd); } static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, @@ -1137,9 +1159,9 @@ static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, return BT_MESH_WALK_CONTINUE; } -static void mod_sub_overwrite(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_overwrite(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; @@ -1151,7 +1173,7 @@ static void mod_sub_overwrite(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } sub_addr = net_buf_simple_pull_le16(buf); @@ -1199,13 +1221,13 @@ static void mod_sub_overwrite(struct bt_mesh_model *model, send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, + return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); } -static void mod_sub_del_all(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_del_all(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct bt_mesh_model *mod; struct bt_mesh_elem *elem; @@ -1217,7 +1239,7 @@ static void mod_sub_del_all(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } BT_DBG("elem_addr 0x%04x", elem_addr); @@ -1248,8 +1270,8 @@ static void mod_sub_del_all(struct bt_mesh_model *model, status = STATUS_SUCCESS; send_status: - send_mod_sub_status(model, ctx, status, elem_addr, - BT_MESH_ADDR_UNASSIGNED, mod_id, vnd); + return send_mod_sub_status(model, ctx, status, elem_addr, + BT_MESH_ADDR_UNASSIGNED, mod_id, vnd); } struct mod_sub_list_ctx { @@ -1289,19 +1311,21 @@ static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod, return BT_MESH_WALK_CONTINUE; } -static void mod_sub_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct mod_sub_list_ctx visit_ctx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; uint16_t addr, id; + int err = 0; addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(addr)) { BT_WARN("Prohibited element address"); + err = -EINVAL; goto done; } @@ -1345,21 +1369,24 @@ static void mod_sub_get(struct bt_mesh_model *model, done: os_mbuf_free_chain(msg); + return err; } -static void mod_sub_get_vnd(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_get_vnd(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct mod_sub_list_ctx visit_ctx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; uint16_t company, addr, id; + int err = 0; addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(addr)) { BT_WARN("Prohibited element address"); + err = -EINVAL; goto done; } @@ -1407,11 +1434,12 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model, done: os_mbuf_free_chain(msg); + return err; } -static void mod_sub_va_add(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_va_add(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; @@ -1425,7 +1453,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } label_uuid = net_buf_simple_pull_mem(buf, 16); @@ -1482,13 +1510,13 @@ static void mod_sub_va_add(struct bt_mesh_model *model, status = STATUS_SUCCESS; send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, + mod_id, vnd); } -static void mod_sub_va_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_va_del(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; @@ -1502,7 +1530,7 @@ static void mod_sub_va_del(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } label_uuid = net_buf_simple_pull_mem(buf, 16); @@ -1550,13 +1578,13 @@ static void mod_sub_va_del(struct bt_mesh_model *model, } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, + mod_id, vnd); } -static void mod_sub_va_overwrite(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_sub_va_overwrite(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED; struct bt_mesh_model *mod; @@ -1569,7 +1597,7 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); - return; + return -EINVAL; } label_uuid = net_buf_simple_pull_mem(buf, 16); @@ -1612,13 +1640,13 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, } send_status: - send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); + return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, + mod_id, vnd); } -static void send_net_key_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - uint16_t idx, uint8_t status) +static int send_net_key_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + uint16_t idx, uint8_t status) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_STATUS, 3); @@ -1632,9 +1660,11 @@ static void send_net_key_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void net_key_add(struct bt_mesh_model *model, +static int net_key_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1644,18 +1674,18 @@ static void net_key_add(struct bt_mesh_model *model, idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return; + return -EINVAL; } BT_DBG("idx 0x%04x", idx); status = bt_mesh_subnet_add(idx, buf->om_data); - send_net_key_status(model, ctx, idx, status); + return send_net_key_status(model, ctx, idx, status); } -static void net_key_update(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int net_key_update(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint8_t status; uint16_t idx; @@ -1663,24 +1693,24 @@ static void net_key_update(struct bt_mesh_model *model, idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return; + return -EINVAL; } status = bt_mesh_subnet_update(idx, buf->om_data); - send_net_key_status(model, ctx, idx, status); + return send_net_key_status(model, ctx, idx, status); } -static void net_key_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int net_key_del(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint16_t del_idx; del_idx = net_buf_simple_pull_le16(buf); if (del_idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", del_idx); - return; + return -EINVAL; } BT_DBG("idx 0x%04x", del_idx); @@ -1689,19 +1719,18 @@ static void net_key_del(struct bt_mesh_model *model, * The NetKey List must contain a minimum of one NetKey. */ if (ctx->net_idx == del_idx) { - send_net_key_status(model, ctx, del_idx, + return send_net_key_status(model, ctx, del_idx, STATUS_CANNOT_REMOVE); - return; } - bt_mesh_subnet_del(del_idx); + (void)bt_mesh_subnet_del(del_idx); - send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS); + return send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS); } -static void net_key_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int net_key_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_LIST, @@ -1730,12 +1759,13 @@ static void net_key_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -static void send_node_id_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - uint8_t status, - uint16_t net_idx, uint8_t node_id) +static int send_node_id_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + uint8_t status, + uint16_t net_idx, uint8_t node_id) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4); @@ -1749,11 +1779,13 @@ static void send_node_id_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void node_identity_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int node_identity_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { enum bt_mesh_feat_state node_id; uint8_t status; @@ -1766,17 +1798,17 @@ static void node_identity_get(struct bt_mesh_model *model, idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return; + return -EINVAL; } status = bt_mesh_subnet_node_id_get(idx, &node_id); - send_node_id_status(model, ctx, status, idx, node_id); + return send_node_id_status(model, ctx, status, idx, node_id); } -static void node_identity_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int node_identity_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint8_t node_id, status; uint16_t idx; @@ -1788,30 +1820,28 @@ static void node_identity_set(struct bt_mesh_model *model, idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_WARN("Invalid NetKeyIndex 0x%04x", idx); - return; + return -EINVAL; } node_id = net_buf_simple_pull_u8(buf); if (node_id != 0x00 && node_id != 0x01) { BT_WARN("Invalid Node ID value 0x%02x", node_id); - return; + return -EINVAL; } status = bt_mesh_subnet_node_id_set(idx, node_id); if (status == STATUS_INVALID_NETKEY) { - send_node_id_status(model, ctx, status, idx, - BT_MESH_NODE_IDENTITY_STOPPED); - return; + return send_node_id_status(model, ctx, status, idx, + BT_MESH_NODE_IDENTITY_STOPPED); } if (status == STATUS_FEAT_NOT_SUPP) { /* Should return success, even if feature isn't supported: */ - send_node_id_status(model, ctx, STATUS_SUCCESS, idx, - BT_MESH_NODE_IDENTITY_NOT_SUPPORTED); - return; + return send_node_id_status(model, ctx, STATUS_SUCCESS, idx, + BT_MESH_NODE_IDENTITY_NOT_SUPPORTED); } - send_node_id_status(model, ctx, status, idx, node_id); + return send_node_id_status(model, ctx, status, idx, node_id); } static void create_mod_app_status(struct os_mbuf *msg, @@ -1832,9 +1862,9 @@ static void create_mod_app_status(struct os_mbuf *msg, } } -static void mod_app_bind(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_app_bind(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9); uint16_t elem_addr, key_app_idx; @@ -1842,10 +1872,12 @@ static void mod_app_bind(struct bt_mesh_model *model, struct bt_mesh_elem *elem; uint8_t *mod_id, status; bool vnd; + int err = 0; elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); + err = -EINVAL; goto done; } @@ -1889,13 +1921,14 @@ static void mod_app_bind(struct bt_mesh_model *model, } done: - os_mbuf_free_chain(msg); + os_mbuf_free_chain(msg); + return err; } -static void mod_app_unbind(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_app_unbind(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9); uint16_t elem_addr, key_app_idx; @@ -1903,10 +1936,12 @@ static void mod_app_unbind(struct bt_mesh_model *model, struct bt_mesh_elem *elem; uint8_t *mod_id, status; bool vnd; + int err = 0; elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); + err = -EINVAL; goto done; } @@ -1943,14 +1978,16 @@ static void mod_app_unbind(struct bt_mesh_model *model, } done: - os_mbuf_free_chain(msg); + os_mbuf_free_chain(msg); + + return err; } #define KEY_LIST_LEN (MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT) * 2) -static void mod_app_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int mod_app_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(max(BT_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST, 9 + KEY_LIST_LEN), @@ -1962,10 +1999,12 @@ static void mod_app_get(struct bt_mesh_model *model, uint8_t *mod_id, status; uint16_t elem_addr; bool vnd; + int err = 0; elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); + err = -EINVAL; goto done; } @@ -2021,6 +2060,8 @@ static void mod_app_get(struct bt_mesh_model *model, done: os_mbuf_free_chain(msg); + + return err; } static void reset_send_start(uint16_t duration, int err, void *cb_data) @@ -2036,9 +2077,9 @@ static void reset_send_end(int err, void *cb_data) bt_mesh_reset(); } -static void node_reset(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int node_reset(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { static const struct bt_mesh_send_cb reset_cb = { .start = reset_send_start, @@ -2058,10 +2099,12 @@ static void node_reset(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void send_friend_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) +static int send_friend_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_FRIEND_STATUS, 1); @@ -2071,23 +2114,26 @@ static void send_friend_status(struct bt_mesh_model *model, if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send Friend Status"); } - os_mbuf_free_chain(msg); + + os_mbuf_free_chain(msg); + + return 0; } -static void friend_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int friend_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - send_friend_status(model, ctx); + return send_friend_status(model, ctx); } -static void friend_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int friend_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -2095,22 +2141,23 @@ static void friend_set(struct bt_mesh_model *model, if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { BT_WARN("Invalid Friend value 0x%02x", buf->om_data[0]); - return; + return -EINVAL; } (void)bt_mesh_friend_set(buf->om_data[0]); - send_friend_status(model, ctx); + return send_friend_status(model, ctx); } -static void lpn_timeout_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int lpn_timeout_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_STATUS, 5); struct bt_mesh_friend *frnd; int32_t timeout_steps; uint16_t lpn_addr; + int err = 0; lpn_addr = net_buf_simple_pull_le16(buf); @@ -2120,6 +2167,7 @@ static void lpn_timeout_get(struct bt_mesh_model *model, /* check if it's the address of the Low Power Node? */ if (!BT_MESH_ADDR_IS_UNICAST(lpn_addr)) { BT_WARN("Invalid LPNAddress; ignoring msg"); + err = -EINVAL; goto done; } @@ -2149,11 +2197,13 @@ static void lpn_timeout_get(struct bt_mesh_model *model, done: os_mbuf_free_chain(msg); + + return err; } -static void send_krp_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - uint16_t idx, uint8_t phase, uint8_t status) +static int send_krp_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + uint16_t idx, uint8_t phase, uint8_t status) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_STATUS, 4); @@ -2168,10 +2218,12 @@ static void send_krp_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint8_t kr_phase, status; uint16_t idx; @@ -2179,18 +2231,18 @@ static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return; + return -EINVAL; } BT_DBG("idx 0x%04x", idx); status = bt_mesh_subnet_kr_phase_get(idx, &kr_phase); - send_krp_status(model, ctx, idx, kr_phase, status); + return send_krp_status(model, ctx, idx, kr_phase, status); } -static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint8_t phase, status; uint16_t idx; @@ -2200,16 +2252,16 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return; + return -EINVAL; } status = bt_mesh_subnet_kr_phase_set(idx, &phase); if (status == STATUS_CANNOT_UPDATE) { BT_ERR("Invalid kr phase transition 0x%02x", phase); - return; + return -EINVAL; } - send_krp_status(model, ctx, idx, phase, status); + return send_krp_status(model, ctx, idx, phase, status); } static uint8_t hb_pub_count_log(uint16_t val) @@ -2234,9 +2286,9 @@ struct hb_pub_param { uint16_t net_idx; } __packed; -static void hb_pub_send_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, uint8_t status, - const struct bt_mesh_hb_pub *pub) +static int hb_pub_send_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, uint8_t status, + const struct bt_mesh_hb_pub *pub) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_STATUS, 10); @@ -2258,9 +2310,11 @@ static void hb_pub_send_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void heartbeat_pub_get(struct bt_mesh_model *model, +static int heartbeat_pub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -2270,12 +2324,12 @@ static void heartbeat_pub_get(struct bt_mesh_model *model, bt_mesh_hb_pub_get(&pub); - hb_pub_send_status(model, ctx, STATUS_SUCCESS, &pub); + return hb_pub_send_status(model, ctx, STATUS_SUCCESS, &pub); } -static void heartbeat_pub_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int heartbeat_pub_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct hb_pub_param *param = (void *)buf->om_data; struct bt_mesh_hb_pub pub; @@ -2308,22 +2362,22 @@ static void heartbeat_pub_set(struct bt_mesh_model *model, if (param->ttl > BT_MESH_TTL_MAX && param->ttl != BT_MESH_TTL_DEFAULT) { BT_ERR("Invalid TTL value 0x%02x", param->ttl); - return; + return -EINVAL; } if (pub.net_idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", pub.net_idx); - return; + return -EINVAL; } status = bt_mesh_hb_pub_set(&pub); rsp: - hb_pub_send_status(model, ctx, status, &pub); + return hb_pub_send_status(model, ctx, status, &pub); } -static void hb_sub_send_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - const struct bt_mesh_hb_sub *sub) +static int hb_sub_send_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + const struct bt_mesh_hb_sub *sub) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_STATUS, 9); BT_DBG("src 0x%04x ", ctx->addr); @@ -2344,11 +2398,13 @@ static void hb_sub_send_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void heartbeat_sub_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int heartbeat_sub_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct bt_mesh_hb_sub sub; @@ -2356,17 +2412,18 @@ static void heartbeat_sub_get(struct bt_mesh_model *model, bt_mesh_hb_sub_get(&sub); - hb_sub_send_status(model, ctx, &sub); + return hb_sub_send_status(model, ctx, &sub); } -static void heartbeat_sub_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int heartbeat_sub_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { uint8_t period_log, status; struct bt_mesh_hb_sub sub; uint16_t sub_src, sub_dst; uint32_t period; + int err; BT_DBG("src 0x%04x", ctx->addr); @@ -2379,7 +2436,7 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, if (period_log > 0x11) { BT_WARN("Prohibited subscription period 0x%02x", period_log); - return; + return -EINVAL; } period = bt_mesh_hb_pwr2(period_log); @@ -2389,7 +2446,7 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, /* All errors are caused by invalid packets, which should be * ignored. */ - return; + return -EINVAL; } bt_mesh_hb_sub_get(&sub); @@ -2401,7 +2458,10 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, sub.min_hops = BT_MESH_TTL_MAX; } - hb_sub_send_status(model, ctx, &sub); + err = hb_sub_send_status(model, ctx, &sub); + if (err) { + return err; + } /* MESH/NODE/CFG/HBS/BV-02-C expects us to return previous * count value and then reset it to 0. @@ -2410,6 +2470,8 @@ static void heartbeat_sub_set(struct bt_mesh_model *model, sub.dst != BT_MESH_ADDR_UNASSIGNED && !period) { bt_mesh_hb_sub_reset_count(); } + + return 0; } const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = { diff --git a/nimble/host/mesh/src/health_cli.c b/nimble/host/mesh/src/health_cli.c index c6057c5643..2be41d313e 100644 --- a/nimble/host/mesh/src/health_cli.c +++ b/nimble/host/mesh/src/health_cli.c @@ -33,9 +33,9 @@ struct health_fault_param { size_t *fault_count; }; -static void health_fault_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int health_fault_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct health_fault_param *param; uint8_t test_id; @@ -47,19 +47,19 @@ static void health_fault_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_HEALTH_FAULT_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } test_id = net_buf_simple_pull_u8(buf); if (param->expect_test_id && test_id != *param->expect_test_id) { BT_WARN("Health fault with unexpected Test ID"); - return; + return -ENOENT; } cid = net_buf_simple_pull_le16(buf); if (cid != param->cid) { BT_WARN("Health fault with unexpected Company ID"); - return; + return -ENOENT; } if (param->test_id) { @@ -75,11 +75,13 @@ static void health_fault_status(struct bt_mesh_model *model, memcpy(param->faults, buf->om_data, *param->fault_count); bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); + + return 0; } -static void health_current_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int health_current_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct bt_mesh_health_cli *cli = model->user_data; uint8_t test_id; @@ -97,19 +99,21 @@ static void health_current_status(struct bt_mesh_model *model, if (!cli->current_status) { BT_WARN("No Current Status callback available"); - return; + return 0; } cli->current_status(cli, ctx->addr, test_id, cid, buf->om_data, buf->om_len); + + return 0; } struct health_period_param { uint8_t *divisor; }; -static void health_period_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int health_period_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct health_period_param *param; @@ -119,19 +123,21 @@ static void health_period_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_HEALTH_PERIOD_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } *param->divisor = net_buf_simple_pull_u8(buf); bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); + + return 0; } struct health_attention_param { uint8_t *attention; }; -static void health_attention_status(struct bt_mesh_model *model, +static int health_attention_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -143,7 +149,7 @@ static void health_attention_status(struct bt_mesh_model *model, if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_ATTENTION_STATUS, ctx->addr, (void **)¶m)) { - return; + return -ENOENT; } if (param->attention) { @@ -151,6 +157,8 @@ static void health_attention_status(struct bt_mesh_model *model, } bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); + + return 0; } const struct bt_mesh_model_op bt_mesh_health_cli_op[] = { diff --git a/nimble/host/mesh/src/health_srv.c b/nimble/host/mesh/src/health_srv.c index d7436b30a3..c1b0dd884f 100644 --- a/nimble/host/mesh/src/health_srv.c +++ b/nimble/host/mesh/src/health_srv.c @@ -67,7 +67,6 @@ static size_t health_get_current(struct bt_mesh_model *mod, uint8_t *test_id, *company_ptr; uint16_t company_id; uint8_t fault_count; - int err; bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS); @@ -77,6 +76,8 @@ static size_t health_get_current(struct bt_mesh_model *mod, if (srv->cb && srv->cb->fault_get_cur) { fault_count = net_buf_simple_tailroom(msg); + int err; + err = srv->cb->fault_get_cur(mod, test_id, &company_id, net_buf_simple_tail(msg), &fault_count); @@ -99,9 +100,9 @@ static size_t health_get_current(struct bt_mesh_model *mod, return fault_count; } -static void health_fault_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int health_fault_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); uint16_t company_id; @@ -117,11 +118,13 @@ static void health_fault_get(struct bt_mesh_model *model, } os_mbuf_free_chain(sdu); + + return 0; } -static void health_fault_clear_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int health_fault_clear_unrel(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct bt_mesh_health_srv *srv = model->user_data; uint16_t company_id; @@ -131,13 +134,15 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model, BT_DBG("company_id 0x%04x", company_id); if (srv->cb && srv->cb->fault_clear) { - srv->cb->fault_clear(model, company_id); + return srv->cb->fault_clear(model, company_id); } + + return 0; } -static void health_fault_clear(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int health_fault_clear(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_health_srv *srv = model->user_data; @@ -148,7 +153,12 @@ static void health_fault_clear(struct bt_mesh_model *model, BT_DBG("company_id 0x%04x", company_id); if (srv->cb && srv->cb->fault_clear) { - srv->cb->fault_clear(model, company_id); + int err; + + err = srv->cb->fault_clear(model, company_id); + if (err) { + return err; + } } health_get_registered(model, company_id, sdu); @@ -158,9 +168,11 @@ static void health_fault_clear(struct bt_mesh_model *model, } os_mbuf_free_chain(sdu); + + return 0; } -static void health_fault_test_unrel(struct bt_mesh_model *model, +static int health_fault_test_unrel(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -174,18 +186,21 @@ static void health_fault_test_unrel(struct bt_mesh_model *model, BT_DBG("test 0x%02x company 0x%04x", test_id, company_id); if (srv->cb && srv->cb->fault_test) { - srv->cb->fault_test(model, test_id, company_id); + return srv->cb->fault_test(model, test_id, company_id); } + + return 0; } -static void health_fault_test(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int health_fault_test(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_health_srv *srv = model->user_data; uint16_t company_id; uint8_t test_id; + int err = 0; BT_DBG(""); @@ -195,11 +210,10 @@ static void health_fault_test(struct bt_mesh_model *model, BT_DBG("test 0x%02x company 0x%04x", test_id, company_id); if (srv->cb && srv->cb->fault_test) { - int err; - err = srv->cb->fault_test(model, test_id, company_id); if (err) { BT_WARN("Running fault test failed with err %d", err); + goto done; } } @@ -212,10 +226,12 @@ static void health_fault_test(struct bt_mesh_model *model, done: os_mbuf_free_chain(sdu); + + return err; } -static void send_attention_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) +static int send_attention_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_STATUS, 1); struct bt_mesh_health_srv *srv = model->user_data; @@ -234,18 +250,20 @@ static void send_attention_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void attention_get(struct bt_mesh_model *model, +static int attention_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { BT_DBG(""); - send_attention_status(model, ctx); + return send_attention_status(model, ctx); } -static void attention_set_unrel(struct bt_mesh_model *model, +static int attention_set_unrel(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -256,20 +274,22 @@ static void attention_set_unrel(struct bt_mesh_model *model, BT_DBG("%u second%s", time, (time == 1) ? "" : "s"); bt_mesh_attention(model, time); + + return 0; } -static void attention_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) +static int attention_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) { BT_DBG(""); attention_set_unrel(model, ctx, buf); - send_attention_status(model, ctx); + return send_attention_status(model, ctx); } -static void send_health_period_status(struct bt_mesh_model *model, +static int send_health_period_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_STATUS, 1); @@ -283,18 +303,20 @@ static void send_health_period_status(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + + return 0; } -static void health_period_get(struct bt_mesh_model *model, +static int health_period_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { BT_DBG(""); - send_health_period_status(model, ctx); + return send_health_period_status(model, ctx); } -static void health_period_set_unrel(struct bt_mesh_model *model, +static int health_period_set_unrel(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -303,15 +325,17 @@ static void health_period_set_unrel(struct bt_mesh_model *model, period = net_buf_simple_pull_u8(buf); if (period > 15) { BT_WARN("Prohibited period value %u", period); - return; + return -EINVAL; } BT_DBG("period %u", period); model->pub->period_div = period; + + return 0; } -static void health_period_set(struct bt_mesh_model *model, +static int health_period_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -319,7 +343,7 @@ static void health_period_set(struct bt_mesh_model *model, health_period_set_unrel(model, ctx, buf); - send_health_period_status(model, ctx); + return send_health_period_status(model, ctx); } const struct bt_mesh_model_op bt_mesh_health_srv_op[] = { diff --git a/nimble/host/mesh/src/model_cli.c b/nimble/host/mesh/src/model_cli.c index 9755ec1fd9..fd052426a1 100644 --- a/nimble/host/mesh/src/model_cli.c +++ b/nimble/host/mesh/src/model_cli.c @@ -26,7 +26,7 @@ struct gen_level_param { int16_t *level; }; -static void gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -41,7 +41,7 @@ static void gen_onoff_status(struct bt_mesh_model *model, if (cli->op_pending != OP_GEN_ONOFF_STATUS) { BT_WARN("Unexpected Generic OnOff Status message"); - return; + return -ENOENT; } param = cli->op_param; @@ -54,9 +54,11 @@ static void gen_onoff_status(struct bt_mesh_model *model, BT_DBG("state: %d", state); k_sem_give(&cli->op_sync); + + return 0; } -static void gen_level_status(struct bt_mesh_model *model, +static int gen_level_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -71,7 +73,7 @@ static void gen_level_status(struct bt_mesh_model *model, if (cli->op_pending != OP_GEN_LEVEL_STATUS) { BT_WARN("Unexpected Generic LEVEL Status message"); - return; + return -EINVAL; } param = cli->op_param; @@ -84,6 +86,8 @@ static void gen_level_status(struct bt_mesh_model *model, BT_DBG("level: %d", level); k_sem_give(&cli->op_sync); + + return 0; } const struct bt_mesh_model_op gen_onoff_cli_op[] = { diff --git a/nimble/host/mesh/src/model_srv.c b/nimble/host/mesh/src/model_srv.c index b6f34360aa..96981cbab6 100644 --- a/nimble/host/mesh/src/model_srv.c +++ b/nimble/host/mesh/src/model_srv.c @@ -15,9 +15,10 @@ static struct bt_mesh_gen_onoff_srv *gen_onoff_srv; static struct bt_mesh_gen_level_srv *gen_level_srv; static struct bt_mesh_light_lightness_srv *light_lightness_srv; -static void gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { + int err; struct bt_mesh_gen_onoff_srv *cb = model->user_data; struct os_mbuf *msg = NET_BUF_SIMPLE(3); uint8_t *state; @@ -30,23 +31,26 @@ static void gen_onoff_status(struct bt_mesh_model *model, BT_DBG("state: %d", *state); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + err = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (err) { BT_ERR("Send status failed"); } os_mbuf_free_chain(msg); + + return err; } -static void gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { BT_DBG(""); - gen_onoff_status(model, ctx); + return gen_onoff_status(model, ctx); } -static void gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -58,23 +62,26 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model, BT_DBG("state: %d", state); if (cb && cb->set) { - cb->set(model, state); + return cb->set(model, state); } + + return 0; } -static void gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { BT_DBG(""); gen_onoff_set_unack(model, ctx, buf); - gen_onoff_status(model, ctx); + return gen_onoff_status(model, ctx); } -static void gen_level_status(struct bt_mesh_model *model, +static int gen_level_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { + int err; struct bt_mesh_gen_level_srv *cb = model->user_data; struct os_mbuf *msg = NET_BUF_SIMPLE(4); int16_t *level; @@ -87,23 +94,25 @@ static void gen_level_status(struct bt_mesh_model *model, BT_DBG("level: %d", *level); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + err = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (err) { BT_ERR("Send status failed"); } os_mbuf_free_chain(msg); + return err; } -static void gen_level_get(struct bt_mesh_model *model, +static int gen_level_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { BT_DBG(""); - gen_level_status(model, ctx); + return gen_level_status(model, ctx); } -static void gen_level_set_unack(struct bt_mesh_model *model, +static int gen_level_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct bt_mesh_gen_level_srv *cb = model->user_data; @@ -113,21 +122,24 @@ static void gen_level_set_unack(struct bt_mesh_model *model, BT_DBG("level: %d", level); if (cb && cb->set) { - cb->set(model, level); + return cb->set(model, level); } + + return 0; } -static void gen_level_set(struct bt_mesh_model *model, +static int gen_level_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { gen_level_set_unack(model, ctx, buf); - gen_level_status(model, ctx); + return gen_level_status(model, ctx); } -static void light_lightness_status(struct bt_mesh_model *model, +static int light_lightness_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { + int err; struct bt_mesh_light_lightness_srv *cb = model->user_data; struct os_mbuf *msg = NET_BUF_SIMPLE(4); int16_t *lightness; @@ -140,23 +152,25 @@ static void light_lightness_status(struct bt_mesh_model *model, BT_DBG("lightness: %d", *lightness); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + err = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (err) { BT_ERR("Send status failed"); } os_mbuf_free_chain(msg); + return err; } -static void light_lightness_get(struct bt_mesh_model *model, +static int light_lightness_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { BT_DBG(""); - light_lightness_status(model, ctx); + return light_lightness_status(model, ctx); } -static void light_lightness_set_unack(struct bt_mesh_model *model, +static int light_lightness_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct bt_mesh_light_lightness_srv *cb = model->user_data; @@ -166,16 +180,18 @@ static void light_lightness_set_unack(struct bt_mesh_model *model, BT_DBG("lightness: %d", lightness); if (cb && cb->set) { - cb->set(model, lightness); + return cb->set(model, lightness); } + + return 0; } -static void light_lightness_set(struct bt_mesh_model *model, +static int light_lightness_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { light_lightness_set_unack(model, ctx, buf); - light_lightness_status(model, ctx); + return light_lightness_status(model, ctx); } const struct bt_mesh_model_op gen_onoff_srv_op[] = { From d278a2d4433a611520fc98ade418057ddcbb2a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 13 Oct 2021 16:30:11 +0200 Subject: [PATCH 189/306] host/mesh: Add msg length check for Cfg and Health models According to spec we should ignore messages with incorrect msg size. This patch adds a check to every opcode handler. This is port of ca53e86f67c5bf0e21ec5ed6701f1a1801d8766a --- nimble/host/mesh/include/mesh/access.h | 15 ++- nimble/host/mesh/src/access.c | 6 +- nimble/host/mesh/src/cfg_cli.c | 103 +++++++++------- nimble/host/mesh/src/cfg_srv.c | 159 +++++++++++++++++-------- nimble/host/mesh/src/health_cli.c | 8 +- nimble/host/mesh/src/health_srv.c | 36 ++++-- 6 files changed, 216 insertions(+), 111 deletions(-) diff --git a/nimble/host/mesh/include/mesh/access.h b/nimble/host/mesh/include/mesh/access.h index de64f74f38..e20cf70086 100644 --- a/nimble/host/mesh/include/mesh/access.h +++ b/nimble/host/mesh/include/mesh/access.h @@ -11,6 +11,7 @@ #define __BT_MESH_ACCESS_H #include "msg.h" +#include /** * @brief Bluetooth Mesh Access Layer @@ -144,8 +145,13 @@ struct bt_mesh_model_op { /* OpCode encoded using the BT_MESH_MODEL_OP_* macros */ const uint32_t opcode; - /* Minimum required message length */ - const size_t min_len; + /** Message length. If the message has variable length then this value + * indicates minimum message length and should be positive. Handler + * function should verify precise length based on the contents of the + * message. If the message has fixed length then this value should + * be negative. Use BT_MESH_LEN_* macros when defining this value. + */ + const ssize_t len; /* Message handler for the opcode */ int (*const func)(struct bt_mesh_model *model, @@ -157,6 +163,11 @@ struct bt_mesh_model_op { #define BT_MESH_MODEL_OP_2(b0, b1) (((b0) << 8) | (b1)) #define BT_MESH_MODEL_OP_3(b0, cid) ((((b0) << 16) | 0xc00000) | (cid)) +/** Macro for encoding exact message length for fixed-length messages. */ +#define BT_MESH_LEN_EXACT(len) (-len) +/** Macro for encoding minimum message length for variable-length messages. */ +#define BT_MESH_LEN_MIN(len) (len) + #define BT_MESH_MODEL_OP_END { 0, 0, NULL } #define BT_MESH_MODEL_NO_OPS ((struct bt_mesh_model_op []) \ { BT_MESH_MODEL_OP_END }) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 95e199c8dc..c0f8632e54 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -658,9 +658,13 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) continue; } - if (buf->om_len < op->min_len) { + if ((op->len >= 0) && (buf->om_len < (size_t)op->len)) { BT_ERR("Too short message for OpCode 0x%08x", opcode); continue; + } else if ((op->len < 0) && (buf->om_len != (size_t)(-op->len))) { + BT_ERR("Invalid message size for OpCode 0x%08x", + opcode); + continue; } /* The callback will likely parse the buffer, so diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index a1a88f0acb..99a7c1685a 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -143,22 +143,7 @@ static int net_transmit_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - uint8_t *status; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_TRANSMIT_STATUS, ctx->addr, - (void **)&status)) { - return -ENOENT; - } - - *status = net_buf_simple_pull_u8(buf); - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; + return state_status_u8(model, ctx, buf, OP_NET_TRANSMIT_STATUS); } struct net_key_param { @@ -229,6 +214,11 @@ static int net_key_list(struct bt_mesh_model *model, param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff; } + if (buf->om_len > 0) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + *param->key_cnt = i; bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); @@ -241,11 +231,11 @@ static int node_reset_status(struct bt_mesh_model *model, struct os_mbuf *buf) { bool *param = NULL; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x", - ctx->net_idx, ctx->app_idx, ctx->addr); + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x", ctx->net_idx, + ctx->app_idx, ctx->addr); - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NODE_RESET_STATUS, ctx->addr, - (void **)¶m)) { + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NODE_RESET_STATUS, + ctx->addr, (void **)¶m)) { return -ENOENT; } @@ -338,6 +328,11 @@ static int app_key_list(struct bt_mesh_model *model, param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff; } + if (buf->om_len > 0U) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EINVAL; + } + *param->key_cnt = i; if (param->status) { *param->status = status; @@ -368,6 +363,11 @@ static int mod_app_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); + if ((buf->om_len != 7U) && (buf->om_len != 9U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_APP_STATUS, ctx->addr, (void **)¶m)) { return -ENOENT; @@ -418,6 +418,11 @@ static int mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, uint8_t status; int i; + if ((vnd && buf->om_len < 7U) || (buf->om_len < 5U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + status = net_buf_simple_pull_u8(buf); elem_addr = net_buf_simple_pull_le16(buf); if (vnd) { @@ -432,9 +437,9 @@ static int mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, return -ENOENT; } - if (buf->om_len % 2) { - BT_WARN("Model Member List invalid length"); - return -ENOENT; + if (buf->om_len % 2U) { + BT_ERR("Model Member List invalid length"); + return -EMSGSIZE; } for (i = 0; i < *param->member_cnt && buf->om_len; i++) { @@ -507,6 +512,11 @@ static int mod_pub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); + if ((buf->om_len != 12U) && (buf->om_len != 14U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EINVAL; + } + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_PUB_STATUS, ctx->addr, (void **)¶m)) { BT_WARN("Unexpected Model Pub Status message"); @@ -585,6 +595,11 @@ static int mod_sub_status(struct bt_mesh_model *model, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); + if ((buf->om_len != 7U) && (buf->om_len != 9U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EINVAL; + } + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_STATUS, ctx->addr, (void **)¶m)) { return -ENOENT; @@ -729,27 +744,27 @@ static int hb_pub_status(struct bt_mesh_model *model, } const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { - { OP_DEV_COMP_DATA_STATUS, 15, comp_data_status }, - { OP_BEACON_STATUS, 1, beacon_status }, - { OP_DEFAULT_TTL_STATUS, 1, ttl_status }, - { OP_FRIEND_STATUS, 1, friend_status }, - { OP_GATT_PROXY_STATUS, 1, gatt_proxy_status }, - { OP_RELAY_STATUS, 2, relay_status }, - { OP_NET_TRANSMIT_STATUS, 1, net_transmit_status }, - { OP_NET_KEY_STATUS, 3, net_key_status }, - { OP_NET_KEY_LIST, 0, net_key_list }, - { OP_APP_KEY_STATUS, 4, app_key_status }, - { OP_APP_KEY_LIST, 3, app_key_list }, - { OP_MOD_APP_STATUS, 7, mod_app_status }, - { OP_SIG_MOD_APP_LIST, 5, mod_app_list}, - { OP_VND_MOD_APP_LIST, 7, mod_app_list_vnd}, - { OP_MOD_PUB_STATUS, 12, mod_pub_status }, - { OP_MOD_SUB_STATUS, 7, mod_sub_status }, - { OP_MOD_SUB_LIST, 5, mod_sub_list}, - { OP_MOD_SUB_LIST_VND, 7, mod_sub_list_vnd}, - { OP_HEARTBEAT_SUB_STATUS, 9, hb_sub_status }, - { OP_HEARTBEAT_PUB_STATUS, 10, hb_pub_status }, - { OP_NODE_RESET_STATUS, 0, node_reset_status}, + { OP_DEV_COMP_DATA_STATUS, BT_MESH_LEN_MIN(15), comp_data_status }, + { OP_BEACON_STATUS, BT_MESH_LEN_EXACT(1), beacon_status }, + { OP_DEFAULT_TTL_STATUS, BT_MESH_LEN_EXACT(1), ttl_status }, + { OP_FRIEND_STATUS, BT_MESH_LEN_EXACT(1), friend_status }, + { OP_GATT_PROXY_STATUS, BT_MESH_LEN_EXACT(1), gatt_proxy_status }, + { OP_RELAY_STATUS, BT_MESH_LEN_EXACT(2), relay_status }, + { OP_NET_TRANSMIT_STATUS, BT_MESH_LEN_EXACT(1), net_transmit_status }, + { OP_NET_KEY_STATUS, BT_MESH_LEN_EXACT(3), net_key_status }, + { OP_NET_KEY_LIST, BT_MESH_LEN_MIN(0), net_key_list }, + { OP_APP_KEY_STATUS, BT_MESH_LEN_EXACT(4), app_key_status }, + { OP_APP_KEY_LIST, BT_MESH_LEN_MIN(3), app_key_list }, + { OP_MOD_APP_STATUS, BT_MESH_LEN_MIN(7), mod_app_status }, + { OP_SIG_MOD_APP_LIST, BT_MESH_LEN_MIN(5), mod_app_list }, + { OP_VND_MOD_APP_LIST, BT_MESH_LEN_MIN(7), mod_app_list_vnd }, + { OP_MOD_PUB_STATUS, BT_MESH_LEN_MIN(12), mod_pub_status }, + { OP_MOD_SUB_STATUS, BT_MESH_LEN_MIN(7), mod_sub_status }, + { OP_MOD_SUB_LIST, BT_MESH_LEN_MIN(5), mod_sub_list }, + { OP_MOD_SUB_LIST_VND, BT_MESH_LEN_MIN(7), mod_sub_list_vnd }, + { OP_HEARTBEAT_SUB_STATUS, BT_MESH_LEN_EXACT(9), hb_sub_status }, + { OP_HEARTBEAT_PUB_STATUS, BT_MESH_LEN_EXACT(10), hb_pub_status }, + { OP_NODE_RESET_STATUS, BT_MESH_LEN_EXACT(0), node_reset_status }, BT_MESH_MODEL_OP_END, }; diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index f5518fd12e..4a63be7e70 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -775,6 +775,11 @@ static int mod_pub_get(struct bt_mesh_model *model, uint8_t *mod_id, status; bool vnd; + if ((buf->om_len != 4U) && (buf->om_len != 6U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -823,6 +828,11 @@ static int mod_pub_set(struct bt_mesh_model *model, uint8_t *mod_id; bool vnd; + if ((buf->om_len != 11U) && (buf->om_len != 13U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -918,6 +928,11 @@ static int mod_pub_va_set(struct bt_mesh_model *model, uint8_t *mod_id; bool vnd; + if ((buf->om_len != 25U) && (buf->om_len != 27U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1020,6 +1035,11 @@ static int mod_sub_add(struct bt_mesh_model *model, uint16_t *entry; bool vnd; + if ((buf->om_len != 6U) && (buf->om_len != 8U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1093,6 +1113,11 @@ static int mod_sub_del(struct bt_mesh_model *model, uint8_t status; bool vnd; + if ((buf->om_len != 6U) && (buf->om_len != 8U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1170,6 +1195,11 @@ static int mod_sub_overwrite(struct bt_mesh_model *model, uint8_t status; bool vnd; + if ((buf->om_len != 6U) && (buf->om_len != 8U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1236,6 +1266,11 @@ static int mod_sub_del_all(struct bt_mesh_model *model, uint8_t status; bool vnd; + if ((buf->om_len != 4U) && (buf->om_len != 6U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1450,6 +1485,11 @@ static int mod_sub_va_add(struct bt_mesh_model *model, uint8_t status; bool vnd; + if ((buf->om_len != 20U) && (buf->om_len != 22U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1527,6 +1567,11 @@ static int mod_sub_va_del(struct bt_mesh_model *model, uint8_t status; bool vnd; + if ((buf->om_len != 20U) && (buf->om_len != 22U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1594,6 +1639,11 @@ static int mod_sub_va_overwrite(struct bt_mesh_model *model, uint8_t status; bool vnd; + if ((buf->om_len != 20U) && (buf->om_len != 22U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1874,6 +1924,11 @@ static int mod_app_bind(struct bt_mesh_model *model, bool vnd; int err = 0; + if ((buf->om_len != 6U) && (buf->om_len != 8U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -1938,6 +1993,11 @@ static int mod_app_unbind(struct bt_mesh_model *model, bool vnd; int err = 0; + if ((buf->om_len != 6U) && (buf->om_len != 8U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -2001,6 +2061,11 @@ static int mod_app_get(struct bt_mesh_model *model, bool vnd; int err = 0; + if ((buf->om_len != 4U) && (buf->om_len != 6U)) { + BT_ERR("The message size for the application opcode is incorrect."); + return -EMSGSIZE; + } + elem_addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { BT_WARN("Prohibited element address"); @@ -2475,53 +2540,53 @@ static int heartbeat_sub_set(struct bt_mesh_model *model, } const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = { - { OP_DEV_COMP_DATA_GET, 1, dev_comp_data_get }, - { OP_APP_KEY_ADD, 19, app_key_add }, - { OP_APP_KEY_UPDATE, 19, app_key_update }, - { OP_APP_KEY_DEL, 3, app_key_del }, - { OP_APP_KEY_GET, 2, app_key_get }, - { OP_BEACON_GET, 0, beacon_get }, - { OP_BEACON_SET, 1, beacon_set }, - { OP_DEFAULT_TTL_GET, 0, default_ttl_get }, - { OP_DEFAULT_TTL_SET, 1, default_ttl_set }, - { OP_GATT_PROXY_GET, 0, gatt_proxy_get }, - { OP_GATT_PROXY_SET, 1, gatt_proxy_set }, - { OP_NET_TRANSMIT_GET, 0, net_transmit_get }, - { OP_NET_TRANSMIT_SET, 1, net_transmit_set }, - { OP_RELAY_GET, 0, relay_get }, - { OP_RELAY_SET, 2, relay_set }, - { OP_MOD_PUB_GET, 4, mod_pub_get }, - { OP_MOD_PUB_SET, 11, mod_pub_set }, - { OP_MOD_PUB_VA_SET, 24, mod_pub_va_set }, - { OP_MOD_SUB_ADD, 6, mod_sub_add }, - { OP_MOD_SUB_VA_ADD, 20, mod_sub_va_add }, - { OP_MOD_SUB_DEL, 6, mod_sub_del }, - { OP_MOD_SUB_VA_DEL, 20, mod_sub_va_del }, - { OP_MOD_SUB_OVERWRITE, 6, mod_sub_overwrite }, - { OP_MOD_SUB_VA_OVERWRITE, 20, mod_sub_va_overwrite }, - { OP_MOD_SUB_DEL_ALL, 4, mod_sub_del_all }, - { OP_MOD_SUB_GET, 4, mod_sub_get }, - { OP_MOD_SUB_GET_VND, 6, mod_sub_get_vnd }, - { OP_NET_KEY_ADD, 18, net_key_add }, - { OP_NET_KEY_UPDATE, 18, net_key_update }, - { OP_NET_KEY_DEL, 2, net_key_del }, - { OP_NET_KEY_GET, 0, net_key_get }, - { OP_NODE_IDENTITY_GET, 2, node_identity_get }, - { OP_NODE_IDENTITY_SET, 3, node_identity_set }, - { OP_MOD_APP_BIND, 6, mod_app_bind }, - { OP_MOD_APP_UNBIND, 6, mod_app_unbind }, - { OP_SIG_MOD_APP_GET, 4, mod_app_get }, - { OP_VND_MOD_APP_GET, 6, mod_app_get }, - { OP_NODE_RESET, 0, node_reset }, - { OP_FRIEND_GET, 0, friend_get }, - { OP_FRIEND_SET, 1, friend_set }, - { OP_LPN_TIMEOUT_GET, 2, lpn_timeout_get }, - { OP_KRP_GET, 2, krp_get }, - { OP_KRP_SET, 3, krp_set }, - { OP_HEARTBEAT_PUB_GET, 0, heartbeat_pub_get }, - { OP_HEARTBEAT_PUB_SET, 9, heartbeat_pub_set }, - { OP_HEARTBEAT_SUB_GET, 0, heartbeat_sub_get }, - { OP_HEARTBEAT_SUB_SET, 5, heartbeat_sub_set }, + { OP_DEV_COMP_DATA_GET, BT_MESH_LEN_EXACT(1), dev_comp_data_get }, + { OP_APP_KEY_ADD, BT_MESH_LEN_EXACT(19), app_key_add }, + { OP_APP_KEY_UPDATE, BT_MESH_LEN_EXACT(19), app_key_update }, + { OP_APP_KEY_DEL, BT_MESH_LEN_EXACT(3), app_key_del }, + { OP_APP_KEY_GET, BT_MESH_LEN_EXACT(2), app_key_get }, + { OP_BEACON_GET, BT_MESH_LEN_EXACT(0), beacon_get }, + { OP_BEACON_SET, BT_MESH_LEN_EXACT(1), beacon_set }, + { OP_DEFAULT_TTL_GET, BT_MESH_LEN_EXACT(0), default_ttl_get }, + { OP_DEFAULT_TTL_SET, BT_MESH_LEN_EXACT(1), default_ttl_set }, + { OP_GATT_PROXY_GET, BT_MESH_LEN_EXACT(0), gatt_proxy_get }, + { OP_GATT_PROXY_SET, BT_MESH_LEN_EXACT(1), gatt_proxy_set }, + { OP_NET_TRANSMIT_GET, BT_MESH_LEN_EXACT(0), net_transmit_get }, + { OP_NET_TRANSMIT_SET, BT_MESH_LEN_EXACT(1), net_transmit_set }, + { OP_RELAY_GET, BT_MESH_LEN_EXACT(0), relay_get }, + { OP_RELAY_SET, BT_MESH_LEN_EXACT(2), relay_set }, + { OP_MOD_PUB_GET, BT_MESH_LEN_MIN(4), mod_pub_get }, + { OP_MOD_PUB_SET, BT_MESH_LEN_MIN(11), mod_pub_set }, + { OP_MOD_PUB_VA_SET, BT_MESH_LEN_MIN(25), mod_pub_va_set }, + { OP_MOD_SUB_ADD, BT_MESH_LEN_MIN(6), mod_sub_add }, + { OP_MOD_SUB_VA_ADD, BT_MESH_LEN_MIN(20), mod_sub_va_add }, + { OP_MOD_SUB_DEL, BT_MESH_LEN_MIN(6), mod_sub_del }, + { OP_MOD_SUB_VA_DEL, BT_MESH_LEN_MIN(20), mod_sub_va_del }, + { OP_MOD_SUB_OVERWRITE, BT_MESH_LEN_MIN(6), mod_sub_overwrite }, + { OP_MOD_SUB_VA_OVERWRITE, BT_MESH_LEN_MIN(20), mod_sub_va_overwrite }, + { OP_MOD_SUB_DEL_ALL, BT_MESH_LEN_MIN(4), mod_sub_del_all }, + { OP_MOD_SUB_GET, BT_MESH_LEN_EXACT(4), mod_sub_get }, + { OP_MOD_SUB_GET_VND, BT_MESH_LEN_EXACT(6), mod_sub_get_vnd }, + { OP_NET_KEY_ADD, BT_MESH_LEN_EXACT(18), net_key_add }, + { OP_NET_KEY_UPDATE, BT_MESH_LEN_EXACT(18), net_key_update }, + { OP_NET_KEY_DEL, BT_MESH_LEN_EXACT(2), net_key_del }, + { OP_NET_KEY_GET, BT_MESH_LEN_EXACT(0), net_key_get }, + { OP_NODE_IDENTITY_GET, BT_MESH_LEN_EXACT(2), node_identity_get }, + { OP_NODE_IDENTITY_SET, BT_MESH_LEN_EXACT(3), node_identity_set }, + { OP_MOD_APP_BIND, BT_MESH_LEN_MIN(6), mod_app_bind }, + { OP_MOD_APP_UNBIND, BT_MESH_LEN_MIN(6), mod_app_unbind }, + { OP_SIG_MOD_APP_GET, BT_MESH_LEN_MIN(4), mod_app_get }, + { OP_VND_MOD_APP_GET, BT_MESH_LEN_MIN(6), mod_app_get }, + { OP_NODE_RESET, BT_MESH_LEN_EXACT(0), node_reset }, + { OP_FRIEND_GET, BT_MESH_LEN_EXACT(0), friend_get }, + { OP_FRIEND_SET, BT_MESH_LEN_EXACT(1), friend_set }, + { OP_LPN_TIMEOUT_GET, BT_MESH_LEN_EXACT(2), lpn_timeout_get }, + { OP_KRP_GET, BT_MESH_LEN_EXACT(2), krp_get }, + { OP_KRP_SET, BT_MESH_LEN_EXACT(3), krp_set }, + { OP_HEARTBEAT_PUB_GET, BT_MESH_LEN_EXACT(0), heartbeat_pub_get }, + { OP_HEARTBEAT_PUB_SET, BT_MESH_LEN_EXACT(9), heartbeat_pub_set }, + { OP_HEARTBEAT_SUB_GET, BT_MESH_LEN_EXACT(0), heartbeat_sub_get }, + { OP_HEARTBEAT_SUB_SET, BT_MESH_LEN_EXACT(5), heartbeat_sub_set }, BT_MESH_MODEL_OP_END, }; diff --git a/nimble/host/mesh/src/health_cli.c b/nimble/host/mesh/src/health_cli.c index 2be41d313e..8424e4200d 100644 --- a/nimble/host/mesh/src/health_cli.c +++ b/nimble/host/mesh/src/health_cli.c @@ -162,10 +162,10 @@ static int health_attention_status(struct bt_mesh_model *model, } const struct bt_mesh_model_op bt_mesh_health_cli_op[] = { - { OP_HEALTH_FAULT_STATUS, 3, health_fault_status }, - { OP_HEALTH_CURRENT_STATUS, 3, health_current_status }, - { OP_HEALTH_PERIOD_STATUS, 1, health_period_status }, - { OP_ATTENTION_STATUS, 1, health_attention_status }, + { OP_HEALTH_FAULT_STATUS, BT_MESH_LEN_MIN(3), health_fault_status }, + { OP_HEALTH_CURRENT_STATUS, BT_MESH_LEN_MIN(3), health_current_status }, + { OP_HEALTH_PERIOD_STATUS, BT_MESH_LEN_EXACT(1), health_period_status }, + { OP_ATTENTION_STATUS, BT_MESH_LEN_EXACT(1), health_attention_status }, BT_MESH_MODEL_OP_END, }; diff --git a/nimble/host/mesh/src/health_srv.c b/nimble/host/mesh/src/health_srv.c index c1b0dd884f..4065d24f83 100644 --- a/nimble/host/mesh/src/health_srv.c +++ b/nimble/host/mesh/src/health_srv.c @@ -282,9 +282,14 @@ static int attention_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + int err; + BT_DBG(""); - attention_set_unrel(model, ctx, buf); + err = attention_set_unrel(model, ctx, buf); + if (err) { + return err; + } return send_attention_status(model, ctx); } @@ -339,25 +344,30 @@ static int health_period_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + int err; + BT_DBG(""); - health_period_set_unrel(model, ctx, buf); + err = health_period_set_unrel(model, ctx, buf); + if (err) { + return err; + } return send_health_period_status(model, ctx); } const struct bt_mesh_model_op bt_mesh_health_srv_op[] = { - { OP_HEALTH_FAULT_GET, 2, health_fault_get }, - { OP_HEALTH_FAULT_CLEAR, 2, health_fault_clear }, - { OP_HEALTH_FAULT_CLEAR_UNREL, 2, health_fault_clear_unrel }, - { OP_HEALTH_FAULT_TEST, 3, health_fault_test }, - { OP_HEALTH_FAULT_TEST_UNREL, 3, health_fault_test_unrel }, - { OP_HEALTH_PERIOD_GET, 0, health_period_get }, - { OP_HEALTH_PERIOD_SET, 1, health_period_set }, - { OP_HEALTH_PERIOD_SET_UNREL, 1, health_period_set_unrel }, - { OP_ATTENTION_GET, 0, attention_get }, - { OP_ATTENTION_SET, 1, attention_set }, - { OP_ATTENTION_SET_UNREL, 1, attention_set_unrel }, + { OP_HEALTH_FAULT_GET, BT_MESH_LEN_EXACT(2), health_fault_get }, + { OP_HEALTH_FAULT_CLEAR, BT_MESH_LEN_EXACT(2), health_fault_clear }, + { OP_HEALTH_FAULT_CLEAR_UNREL, BT_MESH_LEN_EXACT(2), health_fault_clear_unrel }, + { OP_HEALTH_FAULT_TEST, BT_MESH_LEN_EXACT(3), health_fault_test }, + { OP_HEALTH_FAULT_TEST_UNREL, BT_MESH_LEN_EXACT(3), health_fault_test_unrel }, + { OP_HEALTH_PERIOD_GET, BT_MESH_LEN_EXACT(0), health_period_get }, + { OP_HEALTH_PERIOD_SET, BT_MESH_LEN_EXACT(1), health_period_set }, + { OP_HEALTH_PERIOD_SET_UNREL, BT_MESH_LEN_EXACT(1), health_period_set_unrel }, + { OP_ATTENTION_GET, BT_MESH_LEN_EXACT(0), attention_get }, + { OP_ATTENTION_SET, BT_MESH_LEN_EXACT(1), attention_set }, + { OP_ATTENTION_SET_UNREL, BT_MESH_LEN_EXACT(1), attention_set_unrel }, BT_MESH_MODEL_OP_END, }; From 1aedcf177779e4faf69d0883f42097a71c19a4ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 08:13:07 +0200 Subject: [PATCH 190/306] host/mesh: Provisioning PDU length defines Adds length defines for all provisioning PDUs and uses them to split prov_link.conf_inputs into separate fields. This is port of abcbfed6c3ef857626724674cd524ed58da9ef5b --- nimble/host/mesh/include/mesh/glue.h | 2 +- nimble/host/mesh/src/prov.c | 26 +++++++++------- nimble/host/mesh/src/prov.h | 24 +++++++++++++-- nimble/host/mesh/src/prov_device.c | 42 +++++++++++++------------- nimble/host/mesh/src/provisioner.c | 44 ++++++++++++++-------------- 5 files changed, 82 insertions(+), 56 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index ec0e609a0b..2261504a01 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -538,7 +538,7 @@ settings_load(void) #endif /* MYNEWT_VAL(MYNEWT_VAL_BLE_MESH_SETTINGS) */ -#define BUILD_ASSERT(cond) _Static_assert(cond, "") +#define BUILD_ASSERT(cond, msg) _Static_assert(cond, msg) /* Memory slabs/blocks */ diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c index d44d8ec030..1f5a9eaf7e 100644 --- a/nimble/host/mesh/src/prov.c +++ b/nimble/host/mesh/src/prov.c @@ -25,6 +25,10 @@ struct bt_mesh_prov_link bt_mesh_prov_link; const struct bt_mesh_prov *bt_mesh_prov; +/* Verify specification defined length: */ +BUILD_ASSERT(sizeof(bt_mesh_prov_link.conf_inputs) == 145, + "Confirmation inputs shall be 145 bytes"); + static void pub_key_ready(const uint8_t *pkey) { if (!pkey) { @@ -45,7 +49,7 @@ int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64])) pub_key_cb.func = func ? func : pub_key_ready; /* Disable Attention Timer if it was set */ - if (bt_mesh_prov_link.conf_inputs[0]) { + if (bt_mesh_prov_link.conf_inputs.invite[0]) { bt_mesh_attention(NULL, 0); } @@ -252,16 +256,16 @@ static void prov_recv(const struct prov_bearer *bearer, void *cb_data, struct os_mbuf *buf) { static const uint8_t op_len[10] = { - [PROV_INVITE] = 1, - [PROV_CAPABILITIES] = 11, - [PROV_START] = 5, - [PROV_PUB_KEY] = 64, - [PROV_INPUT_COMPLETE] = 0, - [PROV_CONFIRM] = 16, - [PROV_RANDOM] = 16, - [PROV_DATA] = 33, - [PROV_COMPLETE] = 0, - [PROV_FAILED] = 1, + [PROV_INVITE] = PDU_LEN_INVITE, + [PROV_CAPABILITIES] = PDU_LEN_CAPABILITIES, + [PROV_START] = PDU_LEN_START, + [PROV_PUB_KEY] = PDU_LEN_PUB_KEY, + [PROV_INPUT_COMPLETE] = PDU_LEN_INPUT_COMPLETE, + [PROV_CONFIRM] = PDU_LEN_CONFIRM, + [PROV_RANDOM] = PDU_LEN_RANDOM, + [PROV_DATA] = PDU_LEN_DATA, + [PROV_COMPLETE] = PDU_LEN_COMPLETE, + [PROV_FAILED] = PDU_LEN_FAILED, }; uint8_t type = buf->om_data[0]; diff --git a/nimble/host/mesh/src/prov.h b/nimble/host/mesh/src/prov.h index d300b1d5c6..5c42528c6d 100644 --- a/nimble/host/mesh/src/prov.h +++ b/nimble/host/mesh/src/prov.h @@ -56,10 +56,23 @@ #define PROV_NO_PDU 0xff +#define PDU_LEN_INVITE 1 +#define PDU_LEN_CAPABILITIES 11 +#define PDU_LEN_START 5 +#define PDU_LEN_PUB_KEY 64 +#define PDU_LEN_INPUT_COMPLETE 0 +#define PDU_LEN_CONFIRM 16 +#define PDU_LEN_RANDOM 16 +#define PDU_LEN_DATA 33 +#define PDU_LEN_COMPLETE 0 +#define PDU_LEN_FAILED 1 + +#define PDU_OP_LEN 1 + #define PROV_ALG_P256 0x00 #define PROV_BUF(len) \ - NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + len) + NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + PDU_OP_LEN + len) enum { WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */ @@ -111,7 +124,14 @@ struct bt_mesh_prov_link { uint8_t conf_salt[16]; /* ConfirmationSalt */ uint8_t conf_key[16]; /* ConfirmationKey */ - uint8_t conf_inputs[145]; /* ConfirmationInputs */ + /* ConfirmationInput fields: */ + struct { + uint8_t invite[PDU_LEN_INVITE]; + uint8_t capabilities[PDU_LEN_CAPABILITIES]; + uint8_t start[PDU_LEN_START]; + uint8_t pub_key_provisioner[PDU_LEN_PUB_KEY]; /* big-endian */ + uint8_t pub_key_device[PDU_LEN_PUB_KEY]; /* big-endian */ + } conf_inputs; uint8_t prov_salt[16]; /* Provisioning Salt */ }; diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index b7828fa311..737e216cb2 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -32,7 +32,7 @@ static int reset_state(void) static void prov_send_fail_msg(uint8_t err) { - struct os_mbuf *buf = PROV_BUF(2); + struct os_mbuf *buf = PROV_BUF(PDU_LEN_FAILED); BT_DBG("%u", err); @@ -58,7 +58,7 @@ static void prov_fail(uint8_t reason) static void prov_invite(const uint8_t *data) { - struct os_mbuf *buf = PROV_BUF(12); + struct os_mbuf *buf = PROV_BUF(PDU_LEN_CAPABILITIES); BT_DBG("Attention Duration: %u seconds", data[0]); @@ -66,7 +66,7 @@ static void prov_invite(const uint8_t *data) bt_mesh_attention(NULL, data[0]); } - bt_mesh_prov_link.conf_inputs[0] = data[0]; + memcpy(bt_mesh_prov_link.conf_inputs.invite, data, PDU_LEN_INVITE); bt_mesh_prov_buf_init(buf, PROV_CAPABILITIES); @@ -95,7 +95,7 @@ static void prov_invite(const uint8_t *data) /* Input OOB Action */ net_buf_simple_add_be16(buf, bt_mesh_prov->input_actions); - memcpy(&bt_mesh_prov_link.conf_inputs[1], &buf->om_data[1], 11); + memcpy(bt_mesh_prov_link.conf_inputs.capabilities, &buf->om_data[1], PDU_LEN_CAPABILITIES); if (bt_mesh_prov_send(buf, NULL)) { BT_ERR("Failed to send capabilities"); @@ -129,7 +129,7 @@ static void prov_start(const uint8_t *data) atomic_set_bit_to(bt_mesh_prov_link.flags, OOB_PUB_KEY, data[1] == PUB_KEY_OOB); - memcpy(&bt_mesh_prov_link.conf_inputs[12], data, 5); + memcpy(bt_mesh_prov_link.conf_inputs.start, data, PDU_LEN_START); bt_mesh_prov_link.expect = PROV_PUB_KEY; @@ -150,14 +150,15 @@ static void prov_start(const uint8_t *data) static void send_confirm(void) { - struct os_mbuf *cfm = PROV_BUF(17); + struct os_mbuf *cfm = PROV_BUF(PDU_LEN_CONFIRM); - BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64)); - BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64)); - BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17)); + uint8_t *inputs = (uint8_t *)&bt_mesh_prov_link.conf_inputs; - if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs, - bt_mesh_prov_link.conf_salt)) { + BT_DBG("ConfInputs[0] %s", bt_hex(inputs, 64)); + BT_DBG("ConfInputs[64] %s", bt_hex(&inputs[64], 64)); + BT_DBG("ConfInputs[128] %s", bt_hex(&inputs[128], 17)); + + if (bt_mesh_prov_conf_salt(inputs, bt_mesh_prov_link.conf_salt)) { BT_ERR("Unable to generate confirmation salt"); prov_fail(PROV_ERR_UNEXP_ERR); return; @@ -202,7 +203,7 @@ static void send_confirm(void) static void send_input_complete(void) { - struct os_mbuf *buf = PROV_BUF(1); + struct os_mbuf *buf = PROV_BUF(PDU_LEN_INPUT_COMPLETE); bt_mesh_prov_buf_init(buf, PROV_INPUT_COMPLETE); if (bt_mesh_prov_send(buf, NULL)) { @@ -233,7 +234,7 @@ static void start_auth(void) static void send_pub_key(void) { - struct os_mbuf *buf = PROV_BUF(65); + struct os_mbuf *buf = PROV_BUF(PDU_LEN_PUB_KEY); const uint8_t *key; key = bt_pub_key_get(); @@ -251,8 +252,8 @@ static void send_pub_key(void) sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32); sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32); - /* PublicKeyRemote */ - memcpy(&bt_mesh_prov_link.conf_inputs[81], &buf->om_data[1], 64); + /* PublicKeyDevice */ + memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, &buf->om_data[1], PDU_LEN_PUB_KEY); if (bt_mesh_prov_send(buf, public_key_sent)) { BT_ERR("Failed to send Public Key"); @@ -294,7 +295,7 @@ static void prov_dh_key_gen(void) const uint8_t *remote_pk; uint8_t remote_pk_le[64]; - remote_pk = &bt_mesh_prov_link.conf_inputs[17]; + remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner; if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { if (uECC_valid_public_key(remote_pk, &curve_secp256r1)) { @@ -330,7 +331,7 @@ static void prov_pub_key(const uint8_t *data) BT_DBG("Remote Public Key: %s", bt_hex(data, 64)); /* PublicKeyProvisioner */ - memcpy(&bt_mesh_prov_link.conf_inputs[17], data, 64); + memcpy(bt_mesh_prov_link.conf_inputs.pub_key_provisioner, data, PDU_LEN_PUB_KEY); if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { @@ -341,7 +342,8 @@ static void prov_pub_key(const uint8_t *data) } /* No swap needed since user provides public key in big-endian */ - memcpy(&bt_mesh_prov_link.conf_inputs[81], bt_mesh_prov->public_key_be, 64); + memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, bt_mesh_prov->public_key_be, + PDU_LEN_PUB_KEY); atomic_set_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY); @@ -382,7 +384,7 @@ static void notify_input_complete(void) static void send_random(void) { - struct os_mbuf *rnd = PROV_BUF(17); + struct os_mbuf *rnd = PROV_BUF(PDU_LEN_RANDOM); bt_mesh_prov_buf_init(rnd, PROV_RANDOM); net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16); @@ -454,7 +456,7 @@ static inline bool is_pb_gatt(void) static void prov_data(const uint8_t *data) { - struct os_mbuf *msg = PROV_BUF(1); + struct os_mbuf *msg = PROV_BUF(PDU_LEN_COMPLETE); uint8_t session_key[16]; uint8_t nonce[13]; uint8_t dev_key[16]; diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index 7a8c40d8f6..bbf5eb658d 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -65,14 +65,15 @@ static void prov_fail(uint8_t reason) static void send_invite(void) { - struct os_mbuf *inv = PROV_BUF(2); + struct os_mbuf *inv = PROV_BUF(PDU_LEN_INVITE); BT_DBG(""); bt_mesh_prov_buf_init(inv, PROV_INVITE); net_buf_simple_add_u8(inv, prov_device.attention_duration); - bt_mesh_prov_link.conf_inputs[0] = prov_device.attention_duration; + memcpy(bt_mesh_prov_link.conf_inputs.invite, &prov_device.attention_duration, + PDU_LEN_INVITE); if (bt_mesh_prov_send(inv, NULL)) { BT_ERR("Failed to send invite"); @@ -96,15 +97,14 @@ static void send_start(void) { BT_DBG(""); uint8_t method, action; - struct os_mbuf *start = PROV_BUF(6); + struct os_mbuf *start = PROV_BUF(PDU_LEN_START); - const uint8_t *data = &bt_mesh_prov_link.conf_inputs[1 + 3]; + bool oob_pub_key = bt_mesh_prov_link.conf_inputs.capabilities[3] == PUB_KEY_OOB; bt_mesh_prov_buf_init(start, PROV_START); net_buf_simple_add_u8(start, PROV_ALG_P256); - if (atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY) && - *data == PUB_KEY_OOB) { + if (atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY) && oob_pub_key) { net_buf_simple_add_u8(start, PUB_KEY_OOB); atomic_set_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY); } else { @@ -137,7 +137,7 @@ static void send_start(void) net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_size); - memcpy(&bt_mesh_prov_link.conf_inputs[12], &start->om_data[1], 5); + memcpy(bt_mesh_prov_link.conf_inputs.invite, &start->om_data[1], PDU_LEN_INVITE); if (bt_mesh_prov_auth(method, action, bt_mesh_prov_link.oob_size) < 0) { BT_ERR("Invalid authentication method: 0x%02x; " @@ -251,7 +251,7 @@ static void prov_capabilities(const uint8_t *data) return; } #endif - memcpy(&bt_mesh_prov_link.conf_inputs[1], data, 11); + memcpy(bt_mesh_prov_link.conf_inputs.capabilities, data, PDU_LEN_CAPABILITIES); if (bt_mesh_prov->capabilities) { bt_mesh_prov->capabilities(&caps); @@ -267,14 +267,14 @@ static void prov_capabilities(const uint8_t *data) static void send_confirm(void) { - struct os_mbuf *cfm = PROV_BUF(17); + struct os_mbuf *cfm = PROV_BUF(PDU_LEN_CONFIRM); + uint8_t *inputs = (uint8_t *)&bt_mesh_prov_link.conf_inputs; - BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64)); - BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64)); - BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17)); + BT_DBG("ConfInputs[0] %s", bt_hex(inputs, 64)); + BT_DBG("ConfInputs[64] %s", bt_hex(&inputs[64], 64)); + BT_DBG("ConfInputs[128] %s", bt_hex(&inputs[128], 17)); - if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs, - bt_mesh_prov_link.conf_salt)) { + if (bt_mesh_prov_conf_salt(inputs, bt_mesh_prov_link.conf_salt)) { BT_ERR("Unable to generate confirmation salt"); prov_fail(PROV_ERR_UNEXP_ERR); return; @@ -330,7 +330,7 @@ static void public_key_sent(int err, void *cb_data) static void send_pub_key(void) { - struct os_mbuf *buf = PROV_BUF(65); + struct os_mbuf *buf = PROV_BUF(PDU_LEN_PUB_KEY); const uint8_t *key; key = bt_pub_key_get(); @@ -349,7 +349,7 @@ static void send_pub_key(void) sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32); /* PublicKeyProvisioner */ - memcpy(&bt_mesh_prov_link.conf_inputs[17], &buf->om_data[1], 64); + memcpy(bt_mesh_prov_link.conf_inputs.pub_key_provisioner, &buf->om_data[1], PDU_LEN_PUB_KEY); if (bt_mesh_prov_send(buf, public_key_sent)) { BT_ERR("Failed to send Public Key"); @@ -389,8 +389,8 @@ static void prov_dh_key_gen(void) const uint8_t *remote_pk; const uint8_t *local_pk; - local_pk = &bt_mesh_prov_link.conf_inputs[17]; - remote_pk = &bt_mesh_prov_link.conf_inputs[81]; + local_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner; + remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_device; /* Copy remote key in little-endian for bt_dh_key_gen(). * X and Y halves are swapped independently. The bt_dh_key_gen() @@ -422,7 +422,7 @@ static void prov_pub_key(const uint8_t *data) atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY); /* PublicKeyDevice */ - memcpy(&bt_mesh_prov_link.conf_inputs[81], data, 64); + memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, data, 64); bt_mesh_prov_link.bearer->clear_tx(); prov_dh_key_gen(); @@ -464,7 +464,7 @@ static void prov_input_complete(const uint8_t *data) static void send_prov_data(void) { - struct os_mbuf *pdu = PROV_BUF(34); + struct os_mbuf *pdu = PROV_BUF(PDU_LEN_DATA); #if MYNEWT_VAL(BLE_MESH_CDB) struct bt_mesh_cdb_subnet *sub; #endif @@ -565,7 +565,7 @@ static void prov_complete(const uint8_t *data) static void send_random(void) { - struct os_mbuf *rnd = PROV_BUF(17); + struct os_mbuf *rnd = PROV_BUF(PDU_LEN_RANDOM); bt_mesh_prov_buf_init(rnd, PROV_RANDOM); net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16); @@ -724,7 +724,7 @@ int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]) } /* Swap X and Y halves independently to big-endian */ - memcpy(&bt_mesh_prov_link.conf_inputs[81], public_key, 64); + memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, public_key, PDU_LEN_PUB_KEY); return 0; } From db0bd740f36870390b28944370db88dcc9c829e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 09:12:05 +0200 Subject: [PATCH 191/306] host/mesh: Update advertising duration calculation Zephyr Bluetooth Low Energy Controller for mesh stack uses pre-emptible continuous scanning, allowing advertising events to be transmitted without delay when advertising is enabled. No need to compensate with scan window duration. Zephyr Bluetooth Low Energy Controller built for nRF51x SoCs use CONFIG_BT_CTLR_LOW_LAT=y, and continuous scanning cannot be pre-empted, hence, scanning will block advertising events from being transmitted. Increase the advertising duration by the amount of scan window duration to compensate for the blocked advertising events. This is port of 52db419e7a35b18b054182efe0671c90fef5cad3 --- nimble/host/mesh/src/adv.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/adv.c b/nimble/host/mesh/src/adv.c index a9afb42fd8..b3d6290819 100644 --- a/nimble/host/mesh/src/adv.c +++ b/nimble/host/mesh/src/adv.c @@ -96,9 +96,28 @@ static inline void adv_send(struct os_mbuf *buf) duration = ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * (adv_int + 10)); #else - duration = (MESH_SCAN_WINDOW_MS + + /* Zephyr Bluetooth Low Energy Controller for mesh stack uses + * pre-emptible continuous scanning, allowing advertising events to be + * transmitted without delay when advertising is enabled. No need to + * compensate with scan window duration. + * An advertising event could be delayed by upto one interval when + * advertising is stopped and started in quick succession, hence add + * advertising interval to the total advertising duration. + */ + duration = (adv_int + ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * (adv_int + 10))); + + /* Zephyr Bluetooth Low Energy Controller built for nRF51x SoCs use + * CONFIG_BT_CTLR_LOW_LAT=y, and continuous scanning cannot be + * pre-empted, hence, scanning will block advertising events from + * being transmitted. Increase the advertising duration by the + * amount of scan window duration to compensate for the blocked + * advertising events. + */ + if (MYNEWT_VAL(BSP_NRF51)) { + duration += BT_MESH_SCAN_WINDOW_MS; + } #endif BT_DBG("type %u om_len %u: %s", BT_MESH_ADV(buf)->type, From 1828e5cbd69f751290b0b1a2c172300f1f20a403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 09:17:41 +0200 Subject: [PATCH 192/306] host/mesh: Provisioning Start Fix Resolves provisioning start process This is port of 6b67a568c9ee2d0cc6da7d7e518ebf2933c57077 --- nimble/host/mesh/src/provisioner.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index bbf5eb658d..54cc1f0d94 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -3,6 +3,7 @@ /* * Copyright (c) 2017 Intel Corporation * Copyright (c) 2020 Lingao Meng + * Copyright (c) 2021 Manulytica Limited * * SPDX-License-Identifier: Apache-2.0 */ @@ -104,6 +105,8 @@ static void send_start(void) bt_mesh_prov_buf_init(start, PROV_START); net_buf_simple_add_u8(start, PROV_ALG_P256); + memcpy(bt_mesh_prov_link.conf_inputs.start, &start->om_data[1], PDU_LEN_START); + if (atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY) && oob_pub_key) { net_buf_simple_add_u8(start, PUB_KEY_OOB); atomic_set_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY); From 7b0d31393a8be7e5712341a9e37574bf01e4c915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 09:33:44 +0200 Subject: [PATCH 193/306] host/mesh: Added support for application access to mesh messages Added bt_mesh_msg_send() which can be used by the application to directly send model layer messages without local instantiation of related models. Also added bt_mesh_msg_cb_set() which allows the application to recieve mesh model layer messages without local instantiation of related models. Added bt_mesh_has_addr() which returns a bool. For unicast addresses, this returns whether or not bt_mesh_elem_find() was successfull. If the above mentioned bt_mesh_msg_cb_set() has been used by the application to set a message callback, this returns true so that the stack attempts to push every model message up to the application via the callback. If no callback has been set, group addresses are searched to see if the stack should pass the message up the stack to an instantiated model. These changes allow applications that do not or can not instantiate models to interface with models in a mesh network. This is applicable to applications which act as a Bluetooth mesh gateway, sniffer, debugger, network monitoring, non-mesh relay/extender, etc. In app_keys.c friend.c net.c bt_mesh_elem_find() is used only to determine the existance of an address. The full return value of bt_mesh_elem_find() is unecessary and so was replaced by the above mentioned bt_mesh_has_addr() function in these instances. Simplified bt_mesh_elem_find() by removing the search through group address. Since the above mentioned bt_mesh_has_addr() function handles instances where group addresses must be searched, it was no longer necessary to preform this search in this function. This is port of 7a2b248b9804cc59a62b3b7dcdf00f9475ef64e1 --- nimble/host/mesh/src/access.c | 84 +++++++++++++++++++++++---------- nimble/host/mesh/src/access.h | 28 ++++++++++- nimble/host/mesh/src/app_keys.c | 2 +- nimble/host/mesh/src/friend.c | 6 +-- nimble/host/mesh/src/net.c | 6 +-- nimble/host/mesh/syscfg.yml | 7 +++ 6 files changed, 100 insertions(+), 33 deletions(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index c0f8632e54..42a5185e44 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -48,6 +48,7 @@ struct mod_pub_val { static const struct bt_mesh_comp *dev_comp; static uint16_t dev_primary_addr; +static void (*msg_cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf); void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, @@ -485,24 +486,67 @@ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr) { uint16_t index; + if (!BT_MESH_ADDR_IS_UNICAST(addr)) { + return NULL; + } + + index = addr - dev_comp->elem[0].addr; + if (index >= dev_comp->elem_count) { + return NULL; + } + + return &dev_comp->elem[index]; +} + +bool bt_mesh_has_addr(uint16_t addr) +{ + uint16_t index; + if (BT_MESH_ADDR_IS_UNICAST(addr)) { - index = (addr - dev_comp->elem[0].addr); - if (index < dev_comp->elem_count) { - return &dev_comp->elem[index]; - } else { - return NULL; - } + return bt_mesh_elem_find(addr) != NULL; + } + + if (MYNEWT_VAL(BLE_MESH_ACCESS_LAYER_MSG) && msg_cb) { + return true; } for (index = 0; index < dev_comp->elem_count; index++) { struct bt_mesh_elem *elem = &dev_comp->elem[index]; if (bt_mesh_elem_find_group(elem, addr)) { - return elem; + return true; } } - return NULL; + return false; +} + +#if MYNEWT_VAL(BLE_MESH_ACCESS_LAYER_MSG) +void bt_mesh_msg_cb_set(void (*cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf)) +{ + msg_cb = cb; +} +#endif + +int bt_mesh_msg_send(struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf, uint16_t src_addr, + const struct bt_mesh_send_cb *cb, void *cb_data) +{ + struct bt_mesh_net_tx tx = { + .ctx = ctx, + .src = src_addr, + }; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx.ctx->net_idx, + tx.ctx->app_idx, tx.ctx->addr); + BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); + + if (!bt_mesh_is_provisioned()) { + BT_ERR("Local node is not yet provisioned"); + return -EAGAIN; + } + + return bt_mesh_trans_send(&tx, buf, cb, cb_data); } uint8_t bt_mesh_elem_count(void) @@ -675,32 +719,22 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) (void)op->func(model, &rx->ctx, buf); net_buf_simple_restore(buf, &state); } + + if (MYNEWT_VAL(BLE_MESH_ACCESS_LAYER_MSG) && msg_cb) { + msg_cb(opcode, &rx->ctx, buf); + } } int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *msg, const struct bt_mesh_send_cb *cb, void *cb_data) { - struct bt_mesh_net_tx tx = { - .ctx = ctx, - .src = bt_mesh_model_elem(model)->addr, - }; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx.ctx->net_idx, - tx.ctx->app_idx, tx.ctx->addr); - BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len)); - - if (!bt_mesh_is_provisioned()) { - BT_ERR("Local node is not yet provisioned"); - return -EAGAIN; - } - - if (!model_has_key(model, tx.ctx->app_idx)) { - BT_ERR("Model not bound to AppKey 0x%04x", tx.ctx->app_idx); + if (!model_has_key(model, ctx->app_idx)) { + BT_ERR("Model not bound to AppKey 0x%04x", ctx->app_idx); return -EINVAL; } - return bt_mesh_trans_send(&tx, msg, cb, cb_data); + return bt_mesh_msg_send(ctx, msg, bt_mesh_model_elem(model)->addr, cb, cb_data); } int bt_mesh_model_publish(struct bt_mesh_model *model) diff --git a/nimble/host/mesh/src/access.h b/nimble/host/mesh/src/access.h index 0bb183c172..033fe9f937 100644 --- a/nimble/host/mesh/src/access.h +++ b/nimble/host/mesh/src/access.h @@ -21,9 +21,11 @@ void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count); uint8_t bt_mesh_elem_count(void); -/* Find local element based on unicast or group address */ +/* Find local element based on unicast address */ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); +bool bt_mesh_has_addr(uint16_t addr); + struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod); void bt_mesh_model_tree_walk(struct bt_mesh_model *root, enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, @@ -59,5 +61,29 @@ void bt_mesh_model_bind_store(struct bt_mesh_model *mod); void bt_mesh_model_sub_store(struct bt_mesh_model *mod); void bt_mesh_model_pub_store(struct bt_mesh_model *mod); void bt_mesh_model_settings_commit(void); + +/** @brief Register a callback function hook for mesh model messages. + * + * Register a callback function to act as a hook for recieving mesh model layer messages + * directly to the application without having instantiated the relevant models. + * + * @param cb A pointer to the callback function. + */ +void bt_mesh_msg_cb_set(void (*cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf)); + +/** @brief Send a mesh model message. + * + * Send a mesh model layer message out into the mesh network without having instantiated + * the relevant mesh models. + * + * @param ctx The Bluetooth mesh message context. + * @param buf The message payload. + * + * @return 0 on success or negative error code on failure. + */ +int bt_mesh_msg_send(struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf, uint16_t src_addr, + const struct bt_mesh_send_cb *cb, void *cb_data); + void bt_mesh_access_init(void); #endif diff --git a/nimble/host/mesh/src/app_keys.c b/nimble/host/mesh/src/app_keys.c index 16236009d3..4a0aebc062 100644 --- a/nimble/host/mesh/src/app_keys.c +++ b/nimble/host/mesh/src/app_keys.c @@ -502,7 +502,7 @@ int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx, } if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE && - !bt_mesh_elem_find(ctx->addr)) { + !bt_mesh_has_addr(ctx->addr)) { struct bt_mesh_cdb_node *node; if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) { diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 13ce285d51..685e26f54c 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -489,7 +489,7 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf, src = sys_get_be16(&buf->om_data[5]); - if (bt_mesh_elem_find(src)) { + if (bt_mesh_has_addr(src)) { uint32_t seq; if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) { @@ -1043,7 +1043,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) (unsigned) frnd->poll_to); if (BT_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) && - !bt_mesh_elem_find(frnd->clear.frnd)) { + !bt_mesh_has_addr(frnd->clear.frnd)) { clear_procedure_start(frnd); } @@ -1424,7 +1424,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, * this rx function. These packets have already been added to the * queue, and should be ignored. */ - if (bt_mesh_elem_find(rx->ctx.addr)) { + if (bt_mesh_has_addr(rx->ctx.addr)) { return; } diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 865747b048..62fcc41e33 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -506,7 +506,7 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, /* Deliver to local network interface if necessary */ if (bt_mesh_fixed_group_match(tx->ctx->addr) || - bt_mesh_elem_find(tx->ctx->addr)) { + bt_mesh_has_addr(tx->ctx->addr)) { err = loopback(tx, buf->om_data, buf->om_len); /* Local unicast messages should not go out to network */ @@ -604,7 +604,7 @@ static bool net_decrypt(struct bt_mesh_net_rx *rx, struct os_mbuf *in, return false; } - if (bt_mesh_elem_find(rx->ctx.addr)) { + if (bt_mesh_has_addr(rx->ctx.addr)) { BT_DBG("Dropping locally originated packet"); return false; } @@ -815,7 +815,7 @@ void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi, net_buf_simple_save(buf, &state); rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) || - bt_mesh_elem_find(rx.ctx.recv_dst)); + bt_mesh_has_addr(rx.ctx.recv_dst)); if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY)) && net_if == BT_MESH_NET_IF_PROXY) { diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index 58d227c691..3677791a0d 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -153,6 +153,13 @@ syscfg.defs: value: 1 restrictions: BLE_MESH_GATT_SERVER + BLE_MESH_ACCESS_LAYER_MSG: + descryption: > + This option allows the applicaiton to directly access + Bluetooth access layer messages without the need to + instantiate Bluetooth mesh models. + value: 1 + BLE_MESH_PROXY_USE_DEVICE_NAME: description: > Include Bluetooth device name in scan response From 94a721301ac77c03fa304f82fe00d255aa18033e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 10:37:38 +0200 Subject: [PATCH 194/306] host/mesh: Add missing Configuration Client API Add missing API: - Delete all group addresses in a SIG model's subscription list - Update a network key - Update an application key - Get/Set Node Identity parameters - Set virtual addtess for a SIG model - Get/Set Key Refresh Procedures This is port of 22aafd422cea80ba2426b8be7cb59806278ebdd9 --- nimble/host/mesh/include/mesh/cfg_cli.h | 32 +- nimble/host/mesh/include/mesh/glue.h | 1 + nimble/host/mesh/src/cfg_cli.c | 519 +++++++++++++++++++++++- nimble/host/mesh/src/glue.c | 14 + 4 files changed, 560 insertions(+), 6 deletions(-) diff --git a/nimble/host/mesh/include/mesh/cfg_cli.h b/nimble/host/mesh/include/mesh/cfg_cli.h index c117066d27..0bf7cdd70d 100644 --- a/nimble/host/mesh/include/mesh/cfg_cli.h +++ b/nimble/host/mesh/include/mesh/cfg_cli.h @@ -41,6 +41,12 @@ int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status); +int bt_mesh_cfg_krp_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, + uint8_t *status, uint8_t *phase); + +int bt_mesh_cfg_krp_set(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, + uint8_t transition, uint8_t *status, uint8_t *phase); + int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status); int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl); @@ -153,7 +159,8 @@ int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_a #define BT_MESH_PUB_PERIOD_10MIN(steps) (((steps) & BIT_MASK(6)) | (3 << 6)) struct bt_mesh_cfg_mod_pub { - uint16_t addr; + uint16_t addr; + const uint8_t *uuid; uint16_t app_idx; bool cred_flag; uint8_t ttl; @@ -262,6 +269,29 @@ int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr, int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr, struct bt_mesh_cfg_hb_pub *pub, uint8_t *status); +int bt_mesh_cfg_mod_sub_del_all(uint16_t net_idx, uint16_t addr, + uint16_t elem_addr, uint16_t mod_id, + uint8_t *status); + +int bt_mesh_cfg_net_key_update(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, const uint8_t net_key[16], + uint8_t *status); + +int bt_mesh_cfg_app_key_update(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, uint16_t key_app_idx, + const uint8_t app_key[16], uint8_t *status); + +int bt_mesh_cfg_node_identity_set(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, uint8_t new_identity, + uint8_t *status, uint8_t *identity); + +int bt_mesh_cfg_node_identity_get(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, uint8_t *status, + uint8_t *identity); + +int bt_mesh_cfg_lpn_timeout_get(uint16_t net_idx, uint16_t addr, + uint16_t unicast_addr, int32_t *polltimeout); + int32_t bt_mesh_cfg_cli_timeout_get(void); void bt_mesh_cfg_cli_timeout_set(int32_t timeout); diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 2261504a01..955aeb38ed 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -250,6 +250,7 @@ void * net_buf_ref(struct os_mbuf *om); void net_buf_unref(struct os_mbuf *om); uint16_t net_buf_simple_pull_le16(struct os_mbuf *om); uint16_t net_buf_simple_pull_be16(struct os_mbuf *om); +uint32_t net_buf_simple_pull_le24(struct os_mbuf *om); uint32_t net_buf_simple_pull_be32(struct os_mbuf *om); uint32_t net_buf_simple_pull_le32(struct os_mbuf *om); uint8_t net_buf_simple_pull_u8(struct os_mbuf *om); diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index 99a7c1685a..c3d5fbcf59 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -111,6 +111,55 @@ static int gatt_proxy_status(struct bt_mesh_model *model, return state_status_u8(model, ctx, buf, OP_GATT_PROXY_STATUS); } +static int transmit_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + return state_status_u8(model, ctx, buf, OP_NET_TRANSMIT_STATUS); +} + + struct krp_param { + uint8_t *status; + uint16_t net_idx; + uint8_t *phase; +}; + +static int krp_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + struct krp_param *param; + uint16_t net_idx; + uint8_t status, phase; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_KRP_STATUS, ctx->addr, + (void **)¶m)) { + return -ENOENT; + } + + status = net_buf_simple_pull_u8(buf); + net_idx = net_buf_simple_pull_le16(buf) & 0xfff; + phase = net_buf_simple_pull_u8(buf); + + if (param->net_idx != net_idx) { + return -ENOENT; + } + + if (param && param->status) { + *param->status = status; + } + + if (param && param->phase) { + *param->phase = phase; + } + + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; +} + struct relay_param { uint8_t *status; uint8_t *transmit; @@ -743,6 +792,87 @@ static int hb_pub_status(struct bt_mesh_model *model, return 0; } +struct node_idt_param { + uint8_t *status; + uint16_t net_idx; + uint8_t *identity; +}; + +static int node_identity_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + struct node_idt_param *param; + uint16_t net_idx, identity; + uint8_t status; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NODE_IDENTITY_STATUS, + ctx->addr, (void **)¶m)) { + return -ENOENT; + } + + status = net_buf_simple_pull_u8(buf); + net_idx = net_buf_simple_pull_le16(buf) & 0xfff; + identity = net_buf_simple_pull_u8(buf); + + if (param && param->status) { + *param->status = status; + } + + if (param->net_idx != net_idx) { + return -ENOENT; + } + + if (param && param->identity) { + *param->identity = identity; + } + + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; +} + +struct lpn_timeout_param { + uint16_t unicast_addr; + int32_t *polltimeout; +}; + +static int lpn_timeout_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + struct lpn_timeout_param *param; + uint16_t unicast_addr; + int32_t polltimeout; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_LPN_TIMEOUT_STATUS, ctx->addr, + (void **)¶m)) { + return -ENOENT; + } + + unicast_addr = net_buf_simple_pull_le16(buf); + polltimeout = net_buf_simple_pull_le24(buf); + + if (param->unicast_addr != unicast_addr) { + return -ENOENT; + } + + if (param && param->polltimeout) { + *param->polltimeout = polltimeout; + } + + bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); + + return 0; +} + const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { { OP_DEV_COMP_DATA_STATUS, BT_MESH_LEN_MIN(15), comp_data_status }, { OP_BEACON_STATUS, BT_MESH_LEN_EXACT(1), beacon_status }, @@ -765,6 +895,10 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { { OP_HEARTBEAT_SUB_STATUS, BT_MESH_LEN_EXACT(9), hb_sub_status }, { OP_HEARTBEAT_PUB_STATUS, BT_MESH_LEN_EXACT(10), hb_pub_status }, { OP_NODE_RESET_STATUS, BT_MESH_LEN_EXACT(0), node_reset_status }, + { OP_NODE_IDENTITY_STATUS, BT_MESH_LEN_EXACT(4), node_identity_status}, + { OP_LPN_TIMEOUT_STATUS, BT_MESH_LEN_EXACT(5), lpn_timeout_status }, + { OP_NET_TRANSMIT_STATUS, BT_MESH_LEN_EXACT(1), transmit_status}, + { OP_KRP_STATUS, BT_MESH_LEN_EXACT(4), krp_status}, BT_MESH_MODEL_OP_END, }; @@ -918,6 +1052,75 @@ int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status) status); } +int bt_mesh_cfg_krp_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, + uint8_t *status, uint8_t *phase) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_GET, 2); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct krp_param param = { + .status = status, + .phase = phase, + }; + int err; + + err = cli_prepare(¶m, OP_KRP_STATUS, addr); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_KRP_GET); + net_buf_simple_add_le16(msg, key_net_idx); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + +int bt_mesh_cfg_krp_set(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, + uint8_t transition, uint8_t *status, uint8_t *phase) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_SET, 3); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct krp_param param = { + .status = status, + .phase = phase, + }; + int err; + + err = cli_prepare(¶m, OP_KRP_STATUS, addr); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_KRP_SET); + net_buf_simple_add_le16(msg, key_net_idx); + net_buf_simple_add_u8(msg, transition); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status) { return set_state_u8(net_idx, addr, OP_BEACON_SET, OP_BEACON_STATUS, @@ -1092,6 +1295,47 @@ int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_id return err; } +int bt_mesh_cfg_net_key_update(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, const uint8_t net_key[16], + uint8_t *status) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_UPDATE, 18); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct net_key_param param = { + .status = status, + .net_idx = key_net_idx, + }; + int err; + + err = cli_prepare(¶m, OP_NET_KEY_STATUS, addr); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_NET_KEY_UPDATE); + net_buf_simple_add_le16(msg, key_net_idx); + net_buf_simple_add_mem(msg, net_key, 16); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + if (!status) { + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return 0; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys, size_t *key_cnt) { @@ -1213,6 +1457,48 @@ int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_id return err; } +int bt_mesh_cfg_app_key_update(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, uint16_t key_app_idx, + const uint8_t app_key[16], uint8_t *status) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_UPDATE, 19); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct app_key_param param = { + .status = status, + .net_idx = key_net_idx, + .app_idx = key_app_idx, + }; + int err; + + err = cli_prepare(¶m, OP_APP_KEY_STATUS, addr); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_APP_KEY_UPDATE); + key_idx_pack(msg, key_net_idx, key_app_idx); + net_buf_simple_add_mem(msg, app_key, 16); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + if (!status) { + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return 0; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET, 0); @@ -1644,6 +1930,49 @@ int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, mod_id, CID_NVAL, status); } +int bt_mesh_cfg_mod_sub_del_all(uint16_t net_idx, uint16_t addr, + uint16_t elem_addr, uint16_t mod_id, + uint8_t *status) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_SUB_DEL_ALL, 6); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct mod_sub_param param = { + .status = status, + .elem_addr = elem_addr, + .mod_id = mod_id, + .cid = CID_NVAL, + }; + int err; + + err = cli_prepare(¶m, OP_MOD_SUB_STATUS, addr); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_MOD_SUB_DEL_ALL); + net_buf_simple_add_le16(msg, elem_addr); + net_buf_simple_add_le16(msg, mod_id); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + if (!status) { + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return 0; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint16_t cid, uint8_t *status) @@ -1946,23 +2275,86 @@ static int mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, return err; } +static int mod_pub_va_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, + uint16_t mod_id, uint16_t cid, + struct bt_mesh_cfg_mod_pub *pub, uint8_t *status) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_VA_SET, 27); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct mod_pub_param param = { + .mod_id = mod_id, + .cid = cid, + .elem_addr = elem_addr, + .status = status, + .pub = pub, + }; + int err; + + err = cli_prepare(¶m, OP_MOD_PUB_STATUS, addr); + if (err) { + return err; + } + BT_DBG("app_idx 0x%04x", pub->app_idx); + bt_mesh_model_msg_init(msg, OP_MOD_PUB_VA_SET); + + net_buf_simple_add_le16(msg, elem_addr); + net_buf_simple_add_mem(msg, pub->uuid, 16); + net_buf_simple_add_le16(msg, (pub->app_idx | (pub->cred_flag << 12))); + net_buf_simple_add_u8(msg, pub->ttl); + net_buf_simple_add_u8(msg, pub->period); + net_buf_simple_add_u8(msg, pub->transmit); + + if (cid != CID_NVAL) { + net_buf_simple_add_le16(msg, cid); + } + + net_buf_simple_add_le16(msg, mod_id); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + if (!status) { + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return 0; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + + int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub, uint8_t *status) { - return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL, - pub, status); + if (pub->uuid) { + return mod_pub_va_set(net_idx, addr, elem_addr, mod_id, CID_NVAL, pub, status); + } else { + return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL, pub, status); + } } int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, - uint16_t mod_id, uint16_t cid, - struct bt_mesh_cfg_mod_pub *pub, uint8_t *status) + uint16_t mod_id, uint16_t cid, struct bt_mesh_cfg_mod_pub *pub, + uint8_t *status) { if (cid == CID_NVAL) { return -EINVAL; } - return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status); + if (pub->uuid) { + return mod_pub_va_set(net_idx, addr, elem_addr, mod_id, cid, pub, status); + } else { + return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status); + } } int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr, @@ -2137,6 +2529,123 @@ int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr, return err; } +int bt_mesh_cfg_node_identity_set(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, uint8_t new_identity, + uint8_t *status, uint8_t *identity) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_SET, 4); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct node_idt_param param = { + .status = status, + .net_idx = key_net_idx, + .identity = identity, + }; + int err; + + err = cli_prepare(¶m, OP_NODE_IDENTITY_STATUS, addr); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_SET); + net_buf_simple_add_le16(msg, key_net_idx); + net_buf_simple_add_u8(msg, new_identity); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + if (!status) { + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return 0; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + +int bt_mesh_cfg_node_identity_get(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, uint8_t *status, + uint8_t *identity) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_GET, 2); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct node_idt_param param = { + .status = status, + .net_idx = key_net_idx, + .identity = identity, + }; + int err; + + err = cli_prepare(¶m, OP_NODE_IDENTITY_STATUS, addr); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_GET); + net_buf_simple_add_le16(msg, key_net_idx); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + if (!status) { + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return 0; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + +int bt_mesh_cfg_lpn_timeout_get(uint16_t net_idx, uint16_t addr, + uint16_t unicast_addr, int32_t *polltimeout) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_GET, 2); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct lpn_timeout_param param = { + .unicast_addr = unicast_addr, + .polltimeout = polltimeout, + }; + int err; + + err = cli_prepare(¶m, OP_LPN_TIMEOUT_STATUS, addr); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_LPN_TIMEOUT_GET); + net_buf_simple_add_le16(msg, unicast_addr); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); + return err; + } + + return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); +} + int32_t bt_mesh_cfg_cli_timeout_get(void) { return msg_timeout; diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index 2059e2a6f4..e79c43b284 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -142,6 +142,20 @@ net_buf_simple_pull_le16(struct os_mbuf *om) return val; } +uint32_t +net_buf_simple_pull_le24(struct os_mbuf *om) +{ + uint16_t val; + struct os_mbuf *old = om; + + om = os_mbuf_pullup(om, sizeof(val)); + assert(om == old); + val = get_le24(om->om_data); + os_mbuf_adj(om, sizeof(val)); + + return val; +} + uint16_t net_buf_simple_pull_be16(struct os_mbuf *om) { From 842153b06ec61022911e31f82b40997e45df0324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 10:39:18 +0200 Subject: [PATCH 195/306] host/mesh: Fix Health Client Model Assigning a value to the msg_timeout parameter. This is port of a279ff3958aca2d2d665710d0b4f35a1cc8417b3 --- nimble/host/mesh/src/health_cli.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nimble/host/mesh/src/health_cli.c b/nimble/host/mesh/src/health_cli.c index 8424e4200d..caa70215b7 100644 --- a/nimble/host/mesh/src/health_cli.c +++ b/nimble/host/mesh/src/health_cli.c @@ -509,6 +509,7 @@ static int health_cli_init(struct bt_mesh_model *model) cli = model->user_data; cli->model = model; + msg_timeout = 2 * MSEC_PER_SEC; /* Set the default health client pointer */ if (!health_cli) { From 1939344ab78a4a1a358bdf01dfab53483b889001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 10:44:10 +0200 Subject: [PATCH 196/306] host/mesh: fix label logging in mod_sub_va --- nimble/host/mesh/src/cfg_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index c3d5fbcf59..f0f2ba8426 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -2030,7 +2030,7 @@ static int mod_sub_va(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t ele } BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x label %s", - net_idx, addr, elem_addr, label); + net_idx, addr, elem_addr, bt_hex(label, 16)); BT_DBG("mod_id 0x%04x cid 0x%04x", mod_id, cid); bt_mesh_model_msg_init(msg, op); From 623c14de1c650e81406525ac287a838279ef5f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 10:46:18 +0200 Subject: [PATCH 197/306] host/mesh: Add pointer conversion for prov->uri `prov_sd[0].data` and `prov->uri` have different point type. This is port of 9042f76b8b8abd349ada9daf7cfd3272491055db --- nimble/host/mesh/src/gatt_services.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/gatt_services.c b/nimble/host/mesh/src/gatt_services.c index 38f5ee1147..b74e596fe5 100644 --- a/nimble/host/mesh/src/gatt_services.c +++ b/nimble/host/mesh/src/gatt_services.c @@ -1196,7 +1196,7 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[2]) } else { prov_sd[0].type = BT_DATA_URI; prov_sd[0].data_len = uri_len; - prov_sd[0].data = (void *)prov->uri; + prov_sd[0].data = (const uint8_t *)prov->uri; sd_space -= 2 + uri_len; prov_sd_len++; } From df601cfcbdab6bfa5546c70d46ba914181333b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 11:06:09 +0200 Subject: [PATCH 198/306] host/mesh: Refactor Mesh Model Extensions The existing extension tree does not support all the features that are defined by the specification (e.g. multiple parents). This patch approaches this problem by defining a circular single-linked list of extension models. So for a given model, all models that are on the same list as that model are in some extension relationship with that model. All models on a list represent a single connected component of an extension graph but without defining specific relationships between each pair of models. This list is used to manage a shared subscription list as per the Mesh Profile Specification: ```4.2.4 Subscription List Within an element, each model has a separate instance of a Subscription List, unless the model extends another model on that element. Instances of models that extend other models (i.e., all models within an extension relation tree) shall share a single instance of a Subscription List per element. ``` This is port of e167ca653907ff0979e38636009913bce8cd7374 --- nimble/host/mesh/include/mesh/access.h | 29 ++++--- nimble/host/mesh/src/access.c | 112 ++++++++++++------------- nimble/host/mesh/src/access.h | 10 +-- nimble/host/mesh/src/cfg_srv.c | 21 ++--- 4 files changed, 80 insertions(+), 92 deletions(-) diff --git a/nimble/host/mesh/include/mesh/access.h b/nimble/host/mesh/include/mesh/access.h index e20cf70086..6c7c542690 100644 --- a/nimble/host/mesh/include/mesh/access.h +++ b/nimble/host/mesh/include/mesh/access.h @@ -467,11 +467,10 @@ struct bt_mesh_model { const struct bt_mesh_model_cb * const cb; #if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS) - /* Pointer to the next model in a model extension tree. */ + /* Pointer to the next model in a model extension list. */ struct bt_mesh_model *next; - /* Pointer to the first model this model extends. */ - struct bt_mesh_model *extends; #endif + /* Model-specific user data */ void *user_data; }; @@ -581,25 +580,31 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, * Mesh models may be extended to reuse their functionality, forming a more * complex model. A Mesh model may extend any number of models, in any element. * The extensions may also be nested, ie a model that extends another may itself - * be extended. Extensions may not be cyclical, and a model can only be extended - * by one other model. + * be extended. * - * A set of models that extend each other form a model extension tree. + * A set of models that extend each other form a model extension list. * - * All models in an extension tree share one subscription list per element. The + * All models in an extension list share one subscription list per element. The * access layer will utilize the combined subscription list of all models in an - * extension tree and element, giving the models extended subscription list + * extension list and element, giving the models extended subscription list * capacity. * - * @param[in] mod Mesh model. - * @param[in] base_mod The model being extended. + * @param extending_mod Mesh model that is extending the base model. + * @param base_mod The model being extended. * * @retval 0 Successfully extended the base_mod model. - * @retval -EALREADY The base_mod model is already extended. */ -int bt_mesh_model_extend(struct bt_mesh_model *mod, +int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_model *base_mod); +/** @brief Check if model is extended by another model. + * + * @param model The model to check. + * + * @retval true If model is extended by another model, otherwise false + */ +bool bt_mesh_model_is_extended(struct bt_mesh_model *model); + /** Node Composition */ struct bt_mesh_comp { uint16_t cid; diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 42a5185e44..f528e4878a 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -32,7 +32,7 @@ enum { BT_MESH_MOD_BIND_PENDING = BIT(0), BT_MESH_MOD_SUB_PENDING = BIT(1), BT_MESH_MOD_PUB_PENDING = BIT(2), - BT_MESH_MOD_NEXT_IS_PARENT = BIT(3), + BT_MESH_MOD_EXTENDED = BIT(3), }; /* Model publication information for persistent storage. */ @@ -421,8 +421,7 @@ struct find_group_visitor_ctx { uint16_t addr; }; -static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod, - uint32_t depth, void *user_data) +static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod, void *user_data) { struct find_group_visitor_ctx *ctx = user_data; @@ -447,8 +446,7 @@ uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr) .addr = addr, }; - bt_mesh_model_tree_walk(bt_mesh_model_root(*mod), - find_group_mod_visitor, &ctx); + bt_mesh_model_extensions_walk(*mod, find_group_mod_visitor, &ctx); *mod = ctx.mod; return ctx.entry; @@ -810,73 +808,62 @@ const struct bt_mesh_comp *bt_mesh_comp_get(void) return dev_comp; } -struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod) +void bt_mesh_model_extensions_walk(struct bt_mesh_model *model, + enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, + void *user_data), + void *user_data) { -#ifdef CONFIG_BT_MESH_MODEL_EXTENSIONS - while (mod->next) { - mod = mod->next; +#ifndef CONFIG_BT_MESH_MODEL_EXTENSIONS + (void)cb(model, user_data); + return; +#else + struct bt_mesh_model *it; + + if (model->next == NULL) { + (void)cb(model, user_data); + return; } -#endif - return mod; -} - -void bt_mesh_model_tree_walk(struct bt_mesh_model *root, - enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, - uint32_t depth, - void *user_data), - void *user_data) -{ - struct bt_mesh_model *m = root; - int depth = 0; - /* 'skip' is set to true when we ascend from child to parent node. - * In that case, we want to skip calling the callback on the parent - * node and we don't want to descend onto a child node as those - * nodes have already been visited. - */ - bool skip = false; - - do { - if (!skip && - cb(m, (uint32_t)depth, user_data) == BT_MESH_WALK_STOP) { + for (it = model; (it != NULL) && (it->next != model); it = it->next) { + if (cb(it, user_data) == BT_MESH_WALK_STOP) { return; } -#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS) - if (!skip && m->extends) { - m = m->extends; - depth++; - } else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) { - m = m->next; - depth--; - skip = true; - } else { - m = m->next; - skip = false; - } + } #endif - } while (m && depth > 0); } #if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS) -int bt_mesh_model_extend(struct bt_mesh_model *mod, - struct bt_mesh_model *base_mod) +int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_model *base_mod) { - /* Form a cyclical LCRS tree: - * The extends-pointer points to the first child, and the next-pointer - * points to the next sibling. The last sibling is marked by the - * BT_MESH_MOD_NEXT_IS_PARENT flag, and its next-pointer points back to - * the parent. This way, the whole tree is accessible from any node. - * - * We add children (extend them) by inserting them as the first child. - */ - if (base_mod->next) { - return -EALREADY; + struct bt_mesh_model *a = extending_mod; + struct bt_mesh_model *b = base_mod; + struct bt_mesh_model *a_next = a->next; + struct bt_mesh_model *b_next = b->next; + struct bt_mesh_model *it; + + base_mod->flags |= BT_MESH_MOD_EXTENDED; + + if (a == b) { + return 0; + } + + /* Check if a's list contains b */ + for (it = a; (it != NULL) && (it->next != a); it = it->next) { + if (it == b) { + return 0; + } } - if (mod->extends) { - base_mod->next = mod->extends; + /* Merge lists */ + if (a_next) { + b->next = a_next; } else { - base_mod->next = mod; - base_mod->flags |= BT_MESH_MOD_NEXT_IS_PARENT; + b->next = a; + } + + if (b_next) { + a->next = b_next; + } else { + a->next = b; } mod->extends = base_mod; @@ -884,6 +871,11 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod, } #endif +bool bt_mesh_model_is_extended(struct bt_mesh_model *model) +{ + return model->flags & BT_MESH_MOD_EXTENDED; +} + static int mod_set_bind(struct bt_mesh_model *mod, char *val) { int len, err, i; diff --git a/nimble/host/mesh/src/access.h b/nimble/host/mesh/src/access.h index 033fe9f937..34ac248792 100644 --- a/nimble/host/mesh/src/access.h +++ b/nimble/host/mesh/src/access.h @@ -26,12 +26,10 @@ struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); bool bt_mesh_has_addr(uint16_t addr); -struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod); -void bt_mesh_model_tree_walk(struct bt_mesh_model *root, - enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, - uint32_t depth, - void *user_data), - void *user_data); +void bt_mesh_model_extensions_walk(struct bt_mesh_model *root, + enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, + void *user_data), + void *user_data); uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr); diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 4a63be7e70..11a1e4dffc 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -1172,8 +1172,7 @@ static int mod_sub_del(struct bt_mesh_model *model, mod_id, vnd); } -static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, - uint32_t depth, void *user_data) +static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, void *user_data) { if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups)); @@ -1232,8 +1231,7 @@ static int mod_sub_overwrite(struct bt_mesh_model *model, } if (ARRAY_SIZE(mod->groups) > 0) { - bt_mesh_model_tree_walk(bt_mesh_model_root(mod), - mod_sub_clear_visitor, NULL); + bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL); mod->groups[0] = sub_addr; status = STATUS_SUCCESS; @@ -1295,8 +1293,7 @@ static int mod_sub_del_all(struct bt_mesh_model *model, goto send_status; } - bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_clear_visitor, - NULL); + bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL); if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_model_sub_store(mod); @@ -1314,8 +1311,7 @@ struct mod_sub_list_ctx { struct os_mbuf *msg; }; -static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod, - uint32_t depth, void *ctx) +static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod, void *ctx) { struct mod_sub_list_ctx *visit = ctx; int count = 0; @@ -1393,8 +1389,7 @@ static int mod_sub_get(struct bt_mesh_model *model, visit_ctx.msg = msg; visit_ctx.elem_idx = mod->elem_idx; - bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor, - &visit_ctx); + bt_mesh_model_extensions_walk(mod, mod_sub_list_visitor, &visit_ctx); send_list: if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { @@ -1458,8 +1453,7 @@ static int mod_sub_get_vnd(struct bt_mesh_model *model, visit_ctx.msg = msg; visit_ctx.elem_idx = mod->elem_idx; - bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor, - &visit_ctx); + bt_mesh_model_extensions_walk(mod, mod_sub_list_visitor, &visit_ctx); send_list: if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { @@ -1673,8 +1667,7 @@ static int mod_sub_va_overwrite(struct bt_mesh_model *model, if (ARRAY_SIZE(mod->groups) > 0) { status = bt_mesh_va_add(label_uuid, &sub_addr); if (status == STATUS_SUCCESS) { - bt_mesh_model_tree_walk(bt_mesh_model_root(mod), - mod_sub_clear_visitor, NULL); + bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL); mod->groups[0] = sub_addr; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { From c7ce0fff207a01ef9750e3a6ad41ce662fbf2191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 11:07:13 +0200 Subject: [PATCH 199/306] host/mesh: Mark as internal function Marks funcs:`show_faults` as internal, avoiding conflict. This is port of 3911ce8d40be50649a77465b641de28119219b7e --- nimble/host/mesh/src/shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index 61f1db69e0..b0a1b4d2a1 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -169,7 +169,7 @@ static struct bt_mesh_cfg_cli cfg_cli = { #endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */ #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI) -void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count) +static void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count) { size_t i; From 28a82ad50adef5b82ea4a876ecb0d656cf737a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 12:31:01 +0200 Subject: [PATCH 200/306] host/mesh: Add defines for ECC key lengths Adds defines for ECC public keys, private keys, DH keys and key coordinates. Replaces raw numbers throughout. This is port of 8ab219cde5a2d7a87e8d7704a92ffa838cd7473a --- nimble/host/mesh/include/mesh/glue.h | 17 ++++++++++++++--- nimble/host/mesh/include/mesh/main.h | 2 +- nimble/host/mesh/src/prov.c | 2 +- nimble/host/mesh/src/prov.h | 4 ++-- nimble/host/mesh/src/prov_device.c | 21 +++++++++++---------- nimble/host/mesh/src/provisioner.c | 28 +++++++++++++++------------- 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 955aeb38ed..944402f725 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -51,6 +51,17 @@ extern "C" { #endif +/** Key size used in Bluetooth's ECC domain. */ +#define BT_ECC_KEY_SIZE 32 + /** Length of a Bluetooth ECC public key coordinate. */ +#define BT_PUB_KEY_COORD_LEN (BT_ECC_KEY_SIZE) + /** Length of a Bluetooth ECC public key. */ +#define BT_PUB_KEY_LEN (2 * (BT_PUB_KEY_COORD_LEN)) + /** Length of a Bluetooth ECC private key. */ +#define BT_PRIV_KEY_LEN (BT_ECC_KEY_SIZE) + /** Length of a Bluetooth Diffie-Hellman key. */ +#define BT_DH_KEY_LEN (BT_ECC_KEY_SIZE) + /** @brief Helper to declare elements of bt_data arrays * * This macro is mainly for creating an array of struct bt_data @@ -310,13 +321,13 @@ struct bt_pub_key_cb { * * @param key The local public key, or NULL in case of no key. */ - void (*func)(const uint8_t key[64]); + void (*func)(const uint8_t key[BT_PUB_KEY_LEN]); struct bt_pub_key_cb *_next; }; -typedef void (*bt_dh_key_cb_t)(const uint8_t key[32]); -int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb); +typedef void (*bt_dh_key_cb_t)(const uint8_t key[BT_DH_KEY_LEN]); +int bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN], bt_dh_key_cb_t cb); int bt_pub_key_gen(struct bt_pub_key_cb *new_cb); uint8_t *bt_pub_key_get(void); int bt_rand(void *buf, size_t len); diff --git a/nimble/host/mesh/include/mesh/main.h b/nimble/host/mesh/include/mesh/main.h index d196522dea..6e9d2e629d 100644 --- a/nimble/host/mesh/include/mesh/main.h +++ b/nimble/host/mesh/include/mesh/main.h @@ -291,7 +291,7 @@ int bt_mesh_input_number(uint32_t num); * * @return Zero on success or (negative) error code otherwise. */ -int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]); +int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[BT_PUB_KEY_LEN]); /** @brief Use Input OOB authentication. * diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c index 1f5a9eaf7e..64ad656c41 100644 --- a/nimble/host/mesh/src/prov.c +++ b/nimble/host/mesh/src/prov.c @@ -38,7 +38,7 @@ static void pub_key_ready(const uint8_t *pkey) BT_DBG("Local public key ready"); } -int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64])) +int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[BT_PUB_KEY_LEN])) { BT_DBG("bt_mesh_prov_reset_state"); diff --git a/nimble/host/mesh/src/prov.h b/nimble/host/mesh/src/prov.h index 5c42528c6d..9202275fbd 100644 --- a/nimble/host/mesh/src/prov.h +++ b/nimble/host/mesh/src/prov.h @@ -117,7 +117,7 @@ struct bt_mesh_prov_link { uint8_t oob_size; /* Authen size */ uint8_t auth[16]; /* Authen value */ - uint8_t dhkey[32]; /* Calculated DHKey */ + uint8_t dhkey[BT_DH_KEY_LEN]; /* Calculated DHKey */ uint8_t expect; /* Next expected PDU */ uint8_t conf[16]; /* Remote Confirmation */ uint8_t rand[16]; /* Local Random */ @@ -150,7 +150,7 @@ static inline void bt_mesh_prov_buf_init(struct os_mbuf *buf, uint8_t type) net_buf_simple_add_u8(buf, type); } -int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64])); +int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[BT_PUB_KEY_LEN])); bool bt_mesh_prov_active(void); diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index 737e216cb2..1562860c5e 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -244,13 +244,13 @@ static void send_pub_key(void) return; } - BT_DBG("Local Public Key: %s", bt_hex(key, 64)); + BT_DBG("Local Public Key: %s", bt_hex(key, BT_PUB_KEY_LEN)); bt_mesh_prov_buf_init(buf, PROV_PUB_KEY); /* Swap X and Y halves independently to big-endian */ - sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32); - sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32); + sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), key, BT_PUB_KEY_COORD_LEN); + sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), &key[BT_PUB_KEY_COORD_LEN], 32); /* PublicKeyDevice */ memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, &buf->om_data[1], PDU_LEN_PUB_KEY); @@ -265,7 +265,7 @@ static void send_pub_key(void) static void dh_key_gen_complete(void) { - BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32)); + BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, BT_DH_KEY_LEN)); if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY) && atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { @@ -275,7 +275,7 @@ static void dh_key_gen_complete(void) } } -static void prov_dh_key_cb(const uint8_t dhkey[32]) +static void prov_dh_key_cb(const uint8_t dhkey[BT_DH_KEY_LEN]) { BT_DBG("%p", dhkey); @@ -285,7 +285,7 @@ static void prov_dh_key_cb(const uint8_t dhkey[32]) return; } - sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32); + sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, BT_DH_KEY_LEN); dh_key_gen_complete(); } @@ -293,7 +293,7 @@ static void prov_dh_key_cb(const uint8_t dhkey[32]) static void prov_dh_key_gen(void) { const uint8_t *remote_pk; - uint8_t remote_pk_le[64]; + uint8_t remote_pk_le[BT_PUB_KEY_LEN]; remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner; if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && @@ -317,8 +317,9 @@ static void prov_dh_key_gen(void) * X and Y halves are swapped independently. The bt_dh_key_gen() * will also take care of validating the remote public key. */ - sys_memcpy_swap(remote_pk_le, remote_pk, 32); - sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32); + sys_memcpy_swap(remote_pk_le, remote_pk, BT_PUB_KEY_COORD_LEN); + sys_memcpy_swap(&remote_pk_le[BT_PUB_KEY_COORD_LEN], &remote_pk[BT_PUB_KEY_COORD_LEN], + BT_PUB_KEY_COORD_LEN); if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) { BT_ERR("Failed to generate DHKey"); @@ -328,7 +329,7 @@ static void prov_dh_key_gen(void) static void prov_pub_key(const uint8_t *data) { - BT_DBG("Remote Public Key: %s", bt_hex(data, 64)); + BT_DBG("Remote Public Key: %s", bt_hex(data, BT_PUB_KEY_LEN)); /* PublicKeyProvisioner */ memcpy(bt_mesh_prov_link.conf_inputs.pub_key_provisioner, data, PDU_LEN_PUB_KEY); diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index 54cc1f0d94..edc9bbe03f 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -343,13 +343,14 @@ static void send_pub_key(void) return; } - BT_DBG("Local Public Key: %s", bt_hex(key, 64)); + BT_DBG("Local Public Key: %s", bt_hex(key, BT_PUB_KEY_LEN)); bt_mesh_prov_buf_init(buf, PROV_PUB_KEY); /* Swap X and Y halves independently to big-endian */ - sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32); - sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32); + sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), key, BT_PUB_KEY_COORD_LEN); + sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), &key[BT_PUB_KEY_COORD_LEN], + BT_PUB_KEY_COORD_LEN); /* PublicKeyProvisioner */ memcpy(bt_mesh_prov_link.conf_inputs.pub_key_provisioner, &buf->om_data[1], PDU_LEN_PUB_KEY); @@ -362,7 +363,7 @@ static void send_pub_key(void) bt_mesh_prov_link.expect = PROV_PUB_KEY; } -static void prov_dh_key_cb(const uint8_t dhkey[32]) +static void prov_dh_key_cb(const uint8_t dhkey[BT_DH_KEY_LEN]) { BT_DBG("%p", dhkey); @@ -372,9 +373,9 @@ static void prov_dh_key_cb(const uint8_t dhkey[32]) return; } - sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32); + sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, BT_DH_KEY_LEN); - BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32)); + BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, BT_DH_KEY_LEN)); if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING) || atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) || @@ -388,7 +389,7 @@ static void prov_dh_key_cb(const uint8_t dhkey[32]) static void prov_dh_key_gen(void) { - uint8_t remote_pk_le[64]; + uint8_t remote_pk_le[BT_PUB_KEY_LEN]; const uint8_t *remote_pk; const uint8_t *local_pk; @@ -399,10 +400,11 @@ static void prov_dh_key_gen(void) * X and Y halves are swapped independently. The bt_dh_key_gen() * will also take care of validating the remote public key. */ - sys_memcpy_swap(remote_pk_le, remote_pk, 32); - sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32); + sys_memcpy_swap(remote_pk_le, remote_pk, BT_PUB_KEY_COORD_LEN); + sys_memcpy_swap(&remote_pk_le[BT_PUB_KEY_COORD_LEN], &remote_pk[BT_PUB_KEY_COORD_LEN], + BT_PUB_KEY_COORD_LEN); - if (!memcmp(local_pk, remote_pk, 64)) { + if (!memcmp(local_pk, remote_pk, BT_PUB_KEY_LEN)) { BT_ERR("Public keys are identical"); prov_fail(PROV_ERR_NVAL_FMT); return; @@ -420,12 +422,12 @@ static void prov_dh_key_gen(void) static void prov_pub_key(const uint8_t *data) { - BT_DBG("Remote Public Key: %s", bt_hex(data, 64)); + BT_DBG("Remote Public Key: %s", bt_hex(data, BT_PUB_KEY_LEN)); atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY); /* PublicKeyDevice */ - memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, data, 64); + memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, data, BT_PUB_KEY_LEN); bt_mesh_prov_link.bearer->clear_tx(); prov_dh_key_gen(); @@ -716,7 +718,7 @@ int bt_mesh_auth_method_set_none(void) return 0; } -int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]) +int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[BT_PUB_KEY_LEN]) { if (public_key == NULL) { return -EINVAL; From 00a5f55713f095a2fc3e871ac51294410eaf171d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 12:32:04 +0200 Subject: [PATCH 201/306] host/mesh: Fixes Same appkey add to multi netkey The latest MESH.TS 1.0.1.2 4.15.10 Appkey List Procedures MESH/NODE/CFG/AKL/BI-04-C Verify that the IUT can respond to an Config AppKey Add message with NetKeyIndex and AppKeyIndex already stored. 6. Repeat step 1 with the same AppKey, the same AppKeyIndex, but NetKeyIndex field set to 0x001. 7. The Lower Tester expects the IUT to respond with an Config AppKey Status message with the Status field set to 0x04 (Invalid NetKey) and the NetKeyIndex and AppKeyIndex values equal to those sent in step 5. This is port of 6bf35fa7491f3240e7097dc735392cb12df4bf7c --- nimble/host/mesh/src/app_keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/app_keys.c b/nimble/host/mesh/src/app_keys.c index 4a0aebc062..e13245af8a 100644 --- a/nimble/host/mesh/src/app_keys.c +++ b/nimble/host/mesh/src/app_keys.c @@ -291,7 +291,7 @@ uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx, if (app->app_idx == app_idx) { if (app->net_idx != net_idx) { - return STATUS_INVALID_BINDING; + return STATUS_INVALID_NETKEY; } if (memcmp(key, app->keys[0].val, 16)) { From f4dfb41f500a66b86ee83ea4ec3a74cb6ec75cd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 12:37:53 +0200 Subject: [PATCH 202/306] host/mesh: Clarify name length in bt_mesh_model_data_store Name length can't be longer than 8 bytes. This needs to be clarified in the bt_mesh_model_data_store() documentation. This is port of 538f97f73711c73f8a6e6478d461978e3cf2c295 --- nimble/host/mesh/include/mesh/access.h | 12 +++++++----- nimble/host/mesh/include/mesh/glue.h | 2 ++ nimble/host/mesh/src/access.c | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/nimble/host/mesh/include/mesh/access.h b/nimble/host/mesh/include/mesh/access.h index 6c7c542690..f552b584c2 100644 --- a/nimble/host/mesh/include/mesh/access.h +++ b/nimble/host/mesh/include/mesh/access.h @@ -564,16 +564,18 @@ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod) /** @brief Immediately store the model's user data in persistent storage. * - * @param mod Mesh model. - * @param vnd This is a vendor model. - * @param name Name/key of the settings item. - * @param data Model data to store, or NULL to delete any model data. + * @param mod Mesh model. + * @param vnd This is a vendor model. + * @param name Name/key of the settings item. Only + * @ref SETTINGS_MAX_DIR_DEPTH bytes will be used at most. + * @param data Model data to store, or NULL to delete any model data. * @param data_len Length of the model data. * * @return 0 on success, or (negative) error code on failure. */ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, - const char *name, const void *data, size_t data_len); + const char *name, const void *data, + size_t data_len); /** @brief Let a model extend another. * diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 944402f725..a54bdbff35 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -51,6 +51,8 @@ extern "C" { #endif +#define SETTINGS_MAX_DIR_DEPTH 8 /* max depth of settings tree */ + /** Key size used in Bluetooth's ECC domain. */ #define BT_ECC_KEY_SIZE 32 /** Length of a Bluetooth ECC public key coordinate. */ diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index f528e4878a..95af908d77 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -1226,7 +1226,7 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, encode_mod_path(mod, vnd, "data", path, sizeof(path)); if (name) { strcat(path, "/"); - strncat(path, name, 8); + strncat(path, name, SETTINGS_MAX_DIR_DEPTH); } if (data_len) { From a88ee9256edca0a4e14fc2346ba99b4213122520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 12:42:17 +0200 Subject: [PATCH 203/306] host/mesh: Add API to discard subscription in vendor model This commit adds missing API that allows to discard the Subscription List of a vendor model. This is port of 0e9d66897062b0de41a0522b5a836e2ec5b008bc --- nimble/host/mesh/include/mesh/cfg_cli.h | 4 ++ nimble/host/mesh/src/cfg_cli.c | 74 +++++++++++-------------- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/nimble/host/mesh/include/mesh/cfg_cli.h b/nimble/host/mesh/include/mesh/cfg_cli.h index 0bf7cdd70d..86716f3162 100644 --- a/nimble/host/mesh/include/mesh/cfg_cli.h +++ b/nimble/host/mesh/include/mesh/cfg_cli.h @@ -273,6 +273,10 @@ int bt_mesh_cfg_mod_sub_del_all(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t mod_id, uint8_t *status); +int bt_mesh_cfg_mod_sub_del_all_vnd(uint16_t net_idx, uint16_t addr, + uint16_t elem_addr, uint16_t mod_id, + uint16_t cid, uint8_t *status); + int bt_mesh_cfg_net_key_update(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, const uint8_t net_key[16], uint8_t *status); diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index f0f2ba8426..d8d335fe3d 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -1877,7 +1877,10 @@ static int mod_sub(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_a bt_mesh_model_msg_init(msg, op); net_buf_simple_add_le16(msg, elem_addr); - net_buf_simple_add_le16(msg, sub_addr); + + if (sub_addr != BT_MESH_ADDR_UNASSIGNED) { + net_buf_simple_add_le16(msg, sub_addr); + } if (cid != CID_NVAL) { net_buf_simple_add_le16(msg, cid); @@ -1907,6 +1910,10 @@ static int mod_sub(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_a int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint8_t *status) { + if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { + return -EINVAL; + } + return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr, mod_id, CID_NVAL, status); } @@ -1915,7 +1922,7 @@ int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_a uint16_t sub_addr, uint16_t mod_id, uint16_t cid, uint8_t *status) { - if (cid == CID_NVAL) { + if (!BT_MESH_ADDR_IS_GROUP(sub_addr) || cid == CID_NVAL) { return -EINVAL; } @@ -1926,6 +1933,10 @@ int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_a int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint8_t *status) { + if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { + return -EINVAL; + } + return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr, mod_id, CID_NVAL, status); } @@ -1934,50 +1945,15 @@ int bt_mesh_cfg_mod_sub_del_all(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t mod_id, uint8_t *status) { - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_SUB_DEL_ALL, 6); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct mod_sub_param param = { - .status = status, - .elem_addr = elem_addr, - .mod_id = mod_id, - .cid = CID_NVAL, - }; - int err; - - err = cli_prepare(¶m, OP_MOD_SUB_STATUS, addr); - if (err) { - return err; - } - - bt_mesh_model_msg_init(msg, OP_MOD_SUB_DEL_ALL); - net_buf_simple_add_le16(msg, elem_addr); - net_buf_simple_add_le16(msg, mod_id); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return 0; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); + return mod_sub(OP_MOD_SUB_DEL_ALL, net_idx, addr, elem_addr, + BT_MESH_ADDR_UNASSIGNED, mod_id, CID_NVAL, status); } int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint16_t cid, uint8_t *status) { - if (cid == CID_NVAL) { + if (!BT_MESH_ADDR_IS_GROUP(sub_addr) || cid == CID_NVAL) { return -EINVAL; } @@ -1985,9 +1961,25 @@ int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_a mod_id, cid, status); } +int bt_mesh_cfg_mod_sub_del_all_vnd(uint16_t net_idx, uint16_t addr, + uint16_t elem_addr, uint16_t mod_id, + uint16_t cid, uint8_t *status) +{ + if (cid == CID_NVAL) { + return -EINVAL; + } + + return mod_sub(OP_MOD_SUB_DEL_ALL, net_idx, addr, elem_addr, + BT_MESH_ADDR_UNASSIGNED, mod_id, cid, status); +} + int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint8_t *status) { + if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { + return -EINVAL; + } + return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr, sub_addr, mod_id, CID_NVAL, status); } @@ -1996,7 +1988,7 @@ int bt_mesh_cfg_mod_sub_overwrite_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, uint16_t sub_addr, uint16_t mod_id, uint16_t cid, uint8_t *status) { - if (cid == CID_NVAL) { + if (!BT_MESH_ADDR_IS_GROUP(sub_addr) || cid == CID_NVAL) { return -EINVAL; } From 1942a4ea3289518bd374cb068e0e8b3e19ca72cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 12:44:36 +0200 Subject: [PATCH 204/306] host/mesh: Fix IVU duration counter update When device is first provisioned with IV Update flag is set to 0, it should wait for minimum of 96 hours before going into IV Update In Progress state. Such limit does not apply, if device is provisioned with IV Update flag is set to 1. This is port of f868ca3497227c290a8bfea1c64130eb26dcb287 --- nimble/host/mesh/src/mesh.c | 1 + nimble/host/mesh/src/net.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index 3dfba16763..0d9c21e668 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -164,6 +164,7 @@ void bt_mesh_reset(void) } bt_mesh.iv_index = 0U; + bt_mesh.ivu_duration = 0; bt_mesh.seq = 0U; memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags)); diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 62fcc41e33..50f36a3e3a 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -184,11 +184,13 @@ int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, BT_MESH_IV_UPDATE(flags)); - /* Set minimum required hours, since the 96-hour minimum requirement - * doesn't apply straight after provisioning (since we can't know how - * long has actually passed since the network changed its state). + /* If IV Update is already in progress, set minimum required hours, + * since the 96-hour minimum requirement doesn't apply in this case straight + * after provisioning. */ - bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS; + if (BT_MESH_IV_UPDATE(flags)) { + bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS; + } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { BT_DBG("Storing network information persistently"); From 83e1654263e20e60f71315d335877ac6fcec7c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 13:20:52 +0200 Subject: [PATCH 205/306] host/mesh: Use separate net_bufs for bt_mesh_app_decrypt in friend unseg_app_sdu_decrypt decrypts messages in place using a single net_buf. While this is safe in terms of data access, the buffer state is manipulated with the assumption that they're two different buffers, and the output buffer's length field is increased at the end. When assertions are enabled and the pdu length is 11 or 12 bytes, this triggers the net_buf length assert, as the decrypt function attempts to add the pdu length to the out buffer, with the assumption that it was reset before decryption was started. Create a separate output buffer with len = 0 to avoid triggering the assert. Improve readability of the unseg_app_sdu functions to highlight the need for the additional buffer. This is port of 69fcaaa5927e475e5749bf4a1e035ad18de0f796 --- nimble/host/mesh/include/mesh/glue.h | 2 ++ nimble/host/mesh/src/friend.c | 21 ++++++++++++++------- nimble/host/mesh/src/glue.c | 8 ++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index a54bdbff35..1e7f842202 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -373,6 +373,8 @@ static inline void net_buf_simple_save(struct os_mbuf *buf, state->len = buf->om_len; } +void net_buf_simple_clone(const struct os_mbuf *original, struct os_mbuf *clone); + static inline void net_buf_simple_restore(struct os_mbuf *buf, struct net_buf_simple_state *state) { diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 685e26f54c..e614e74974 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -390,15 +390,21 @@ static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd, const struct unseg_app_sdu_meta *meta) { struct net_buf_simple_state state; + struct os_mbuf *in = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); + struct os_mbuf *out = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); int err; - BT_DBG(""); - net_buf_simple_save(buf, &state); - net_buf_simple_pull_mem(buf, 10); - buf->om_len -= 4; + /* Direct the input buffer at the Upper Transport Access PDU, accounting for + * the network header and the 1 byte lower transport header + */ + net_buf_simple_clone(buf, in); + net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN); + net_buf_simple_pull(buf, 1); + in->om_len -= BT_MESH_MIC_SHORT;; - err = bt_mesh_app_decrypt(meta->key, &meta->crypto, buf, buf); + net_buf_simple_clone(in, out); + err = bt_mesh_app_decrypt(meta->key, &meta->crypto, in, out); net_buf_simple_restore(buf, &state); net_buf_unref(buf); @@ -415,8 +421,9 @@ static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd, BT_DBG(""); net_buf_simple_save(buf, &state); - net_buf_simple_pull_mem(buf, 10); - buf->om_len -= 4; + net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN); + net_buf_simple_pull_mem(buf, 1); + buf->om_len -= BT_MESH_MIC_SHORT; err = bt_mesh_app_encrypt(meta->key, &meta->crypto, buf); diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index e79c43b284..4e4715f2f0 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -112,6 +112,14 @@ net_buf_unref(struct os_mbuf *om) os_mbuf_free_chain(om); } + +void net_buf_simple_clone(const struct os_mbuf *original, + struct os_mbuf *clone) +{ + memcpy(clone, original, sizeof(struct os_mbuf)); +} + + int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data) { From 344e1c269f1805ac3fd0a873e12910854a15860a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 13:26:16 +0200 Subject: [PATCH 206/306] host/mesh: Verify that all stored mesh entries removed This ensures that all mesh settings were removed from persistent storage after node reset. This is port of cd294c12c3ea604cc706c22414f798a7eafac859 --- nimble/host/mesh/src/net.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 50f36a3e3a..521a9859ed 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -1161,20 +1161,29 @@ void bt_mesh_net_pending_seq_store(void) struct seq_val seq; int err; - sys_put_le24(bt_mesh.seq, seq.val); + if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + sys_put_le24(bt_mesh.seq, seq.val); - str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Network as value"); - return; - } + str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode Network as value"); + return; + } - BT_DBG("Saving Network as value %s", str); - err = settings_save_one("bt_mesh/Seq", str); - if (err) { - BT_ERR("Failed to stor Seq value"); + BT_DBG("Saving Network as value %s", str); + err = settings_save_one("bt_mesh/Seq", str); + if (err) { + BT_ERR("Failed to stor Seq value"); + } else { + BT_DBG("Stored Seq value"); + } } else { - BT_DBG("Stored Seq value"); + err = settings_save_one("bt_mesh/Seq", NULL); + if (err) { + BT_ERR("Failed to clear Seq value"); + } else { + BT_DBG("Cleared Seq value"); + } } } @@ -1183,6 +1192,7 @@ void bt_mesh_net_clear(void) bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_NET_PENDING); bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_IV_PENDING); bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); + bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); } void bt_mesh_net_settings_commit(void) From 0904bcb6f2f6e66b30154616b86e930c9f6aba55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 13:30:21 +0200 Subject: [PATCH 207/306] host/mesh: Remove krp param check param can never be NULL, so this check is redundant. Coverity complains about this, as the param variable is accessed before the check, which would be wrong if param could be NULL. This is port of fd6f51c4104e02f16c23ca1eee3ab747ab7143ef --- nimble/host/mesh/src/cfg_cli.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index d8d335fe3d..3560052b4c 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -134,8 +134,7 @@ static int krp_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_KRP_STATUS, ctx->addr, - (void **)¶m)) { + if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_KRP_STATUS, ctx->addr, (void **)¶m)) { return -ENOENT; } @@ -147,11 +146,11 @@ static int krp_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return -ENOENT; } - if (param && param->status) { + if (param->status) { *param->status = status; } - if (param && param->phase) { + if (param->phase) { *param->phase = phase; } From 7f54ce9d01a637063eda19cb2c9f48fbea088dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 13:31:33 +0200 Subject: [PATCH 208/306] host/mesh: Remove lpn timeout param check param can never be NULL here, so the check is redundant. Coverity is complaining because param is accessed before the NULL check. This is port of 4eb047d1afdbb159527b821552be6d79e84fb1e4 --- nimble/host/mesh/src/cfg_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index 3560052b4c..773bafa709 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -863,7 +863,7 @@ static int lpn_timeout_status(struct bt_mesh_model *model, struct bt_mesh_msg_ct return -ENOENT; } - if (param && param->polltimeout) { + if (param->polltimeout) { *param->polltimeout = polltimeout; } From fea8bf015e2275e8cacef160bb7a828a02b284d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 13:32:39 +0200 Subject: [PATCH 209/306] host/mesh: Initialize UUID in shell's mod_pub_set PR #35774 introduced a uuid field in the bt_mesh_cfg_mod_pub structure. The shell does not initialize this pointer before passing it to the access layer. Add a line to initialize this pointer. This is port of c5757ca4a104c8207cfa6244c4a128cef2bda9b5 --- nimble/host/mesh/src/shell.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index b0a1b4d2a1..95b1907f79 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -2002,6 +2002,7 @@ static int mod_pub_set(uint16_t addr, uint16_t mod_id, uint16_t cid, char *argv[ int err; pub.addr = strtoul(argv[0], NULL, 0); + pub.uuid = NULL; pub.app_idx = strtoul(argv[1], NULL, 0); pub.cred_flag = str2bool(argv[2]); pub.ttl = strtoul(argv[3], NULL, 0); From 6b22633683a132773ae120992fffd81f5066473e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 13:38:38 +0200 Subject: [PATCH 210/306] host/mesh: Fail provisioning when RFU values are used When Public Key field is set to RFU value then we should send Provisioning Fail with Invalid Format error. This is port of f51cf9ab869b194f040435fa171f0e9b4f33de98 --- nimble/host/mesh/src/prov_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index 1562860c5e..ab387c3681 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -119,9 +119,9 @@ static void prov_start(const uint8_t *data) return; } - if (data[1] == PUB_KEY_OOB && - !(MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && - bt_mesh_prov->public_key_be)) { + if (data[1] > PUB_KEY_OOB || + (data[1] == PUB_KEY_OOB && + (!MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) || !bt_mesh_prov->public_key_be))) { BT_ERR("Invalid public key type: 0x%02x", data[1]); prov_fail(PROV_ERR_NVAL_FMT); return; From 3d2eb2677cd4f1634902b62f0652d53792c9c707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 14:11:37 +0200 Subject: [PATCH 211/306] host/mesh: Fix friend buf send end not called. As frnd->last will keep reference, so that net buffer destructor function will not be call. This is port of ecc7ca1b698bd2d3b7f043c945980b909cc3e4a7 --- nimble/host/mesh/src/friend.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index e614e74974..dc7d78425f 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -42,8 +42,6 @@ static struct os_mempool friend_buf_mempool; #define NET_BUF_FRAGS BIT(0) -#define FRIEND_ADV(buf) CONTAINER_OF(BT_MESH_ADV(buf), struct friend_adv, adv) - /* PDUs from Friend to the LPN should only be transmitted once with the * smallest possible interval (20ms). */ @@ -62,14 +60,15 @@ struct friend_pdu_info { }; static struct friend_adv { - struct bt_mesh_adv adv; uint16_t app_idx; } adv_pool[FRIEND_BUF_COUNT]; -static struct bt_mesh_adv *adv_alloc(int id) +#define FRIEND_ADV(buf) (*(struct friend_adv **)net_buf_user_data(buf)) + +static struct friend_adv *adv_alloc(int id) { adv_pool[id].app_idx = BT_MESH_KEY_UNUSED; - return &adv_pool[id].adv; + return &adv_pool[id]; } static bool friend_is_allocated(const struct bt_mesh_friend *frnd) @@ -161,11 +160,6 @@ static void friend_clear(struct bt_mesh_friend *frnd) memset(frnd->cred, 0, sizeof(frnd->cred)); if (frnd->last) { - /* Cancel the sending if necessary */ - if (frnd->pending_buf) { - BT_MESH_ADV(frnd->last)->busy = 0; - } - net_buf_unref(frnd->last); frnd->last = NULL; } @@ -314,13 +308,13 @@ static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd, { struct os_mbuf *buf; - buf = bt_mesh_adv_create_from_pool(&friend_os_mbuf_pool, adv_alloc, - BT_MESH_ADV_DATA, - FRIEND_XMIT, K_NO_WAIT); + buf = os_mbuf_get_pkthdr(&friend_os_mbuf_pool, BT_MESH_ADV_USER_DATA_SIZE); if (!buf) { return NULL; } + FRIEND_ADV(buf) = adv_alloc(net_buf_id(buf)); + net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */ if (info->ctl) { @@ -1222,7 +1216,7 @@ static void friend_timeout(struct ble_npl_event *work) .start = buf_send_start, .end = buf_send_end, }; - + struct os_mbuf *buf; uint8_t md; if (!friend_is_allocated(frnd)) { @@ -1271,9 +1265,17 @@ static void friend_timeout(struct ble_npl_event *work) frnd->queue_size--; send_last: + buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, FRIEND_XMIT, K_NO_WAIT); + if (!buf) { + BT_ERR("Unable to allocate friend adv buffer"); + return; + } + + net_buf_add_mem(buf, frnd->last->om_data, frnd->last->om_len); frnd->pending_req = 0; frnd->pending_buf = 1; - bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd); + bt_mesh_adv_send(buf, &buf_sent_cb, frnd); + net_buf_unref(buf); } static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) From c3ec6128e05b174009c4e29dbbbb2ffd9ff5e524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 14:17:12 +0200 Subject: [PATCH 212/306] host/mesh: Check if app key is bound in Model Publication Set Th Configuration Server should respond with and Invalid AppKey Index status code when the AppKey identified by AppKeyIndex is not known to the node or is not bound to the model identified by the ModelIdentifier. This is port of 343c0bd2d38e70bb627f5dff3db8a37360f112f9 --- nimble/host/mesh/src/access.c | 6 +++--- nimble/host/mesh/src/access.h | 1 + nimble/host/mesh/src/cfg_srv.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 95af908d77..33169a7501 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -552,7 +552,7 @@ uint8_t bt_mesh_elem_count(void) return dev_comp->elem_count; } -static bool model_has_key(struct bt_mesh_model *mod, uint16_t key) +bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key) { int i; @@ -692,7 +692,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) continue; } - if (!model_has_key(model, rx->ctx.app_idx)) { + if (!bt_mesh_model_has_key(model, rx->ctx.app_idx)) { continue; } @@ -727,7 +727,7 @@ int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *msg, const struct bt_mesh_send_cb *cb, void *cb_data) { - if (!model_has_key(model, ctx->app_idx)) { + if (!bt_mesh_model_has_key(model, ctx->app_idx)) { BT_ERR("Model not bound to AppKey 0x%04x", ctx->app_idx); return -EINVAL; } diff --git a/nimble/host/mesh/src/access.h b/nimble/host/mesh/src/access.h index 34ac248792..217f4abe0f 100644 --- a/nimble/host/mesh/src/access.h +++ b/nimble/host/mesh/src/access.h @@ -25,6 +25,7 @@ uint8_t bt_mesh_elem_count(void); struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); bool bt_mesh_has_addr(uint16_t addr); +bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key); void bt_mesh_model_extensions_walk(struct bt_mesh_model *root, enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, diff --git a/nimble/host/mesh/src/cfg_srv.c b/nimble/host/mesh/src/cfg_srv.c index 11a1e4dffc..2af24370e3 100644 --- a/nimble/host/mesh/src/cfg_srv.c +++ b/nimble/host/mesh/src/cfg_srv.c @@ -216,7 +216,7 @@ static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, return STATUS_SUCCESS; } - if (!bt_mesh_app_key_exists(app_idx)) { + if (!bt_mesh_app_key_exists(app_idx) || !bt_mesh_model_has_key(model, app_idx)) { return STATUS_INVALID_APPKEY; } From 0d6e6c4040ae4460f0ae9852ee4c26b5fb24570c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 14:19:22 +0200 Subject: [PATCH 213/306] host/mesh: Verify if Remote confirmation is not identical MESH/PVNR/PROV/BI-18-C verifies that the IUT rejects invalid Confirmation Value. This is port of 88b60f31c74aa2a35d4869bc4ec463c52fc1f451 --- nimble/host/mesh/src/prov.h | 2 +- nimble/host/mesh/src/provisioner.c | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/prov.h b/nimble/host/mesh/src/prov.h index 9202275fbd..b287fb2a00 100644 --- a/nimble/host/mesh/src/prov.h +++ b/nimble/host/mesh/src/prov.h @@ -119,7 +119,7 @@ struct bt_mesh_prov_link { uint8_t dhkey[BT_DH_KEY_LEN]; /* Calculated DHKey */ uint8_t expect; /* Next expected PDU */ - uint8_t conf[16]; /* Remote Confirmation */ + uint8_t conf[16]; /* Local/Remote Confirmation */ uint8_t rand[16]; /* Local Random */ uint8_t conf_salt[16]; /* ConfirmationSalt */ diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index edc9bbe03f..e5cb22ffaa 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -306,12 +306,14 @@ static void send_confirm(void) if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, bt_mesh_prov_link.rand, bt_mesh_prov_link.auth, - net_buf_simple_add(cfm, 16))) { + bt_mesh_prov_link.conf)) { BT_ERR("Unable to generate confirmation value"); prov_fail(PROV_ERR_UNEXP_ERR); return; } + net_buf_simple_add_mem(cfm, bt_mesh_prov_link.conf, 16); + if (bt_mesh_prov_send(cfm, NULL)) { BT_ERR("Failed to send Provisioning Confirm"); return; @@ -625,6 +627,12 @@ static void prov_confirm(const uint8_t *data) { BT_DBG("Remote Confirm: %s", bt_hex(data, 16)); + if (!memcmp(data, bt_mesh_prov_link.conf, 16)) { + BT_ERR("Confirm value is identical to ours, rejecting."); + prov_fail(PROV_ERR_CFM_FAILED); + return; + } + memcpy(bt_mesh_prov_link.conf, data, 16); send_random(); From c1b087a4c5ecae8195827771b3d482510858ea47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 14:23:28 +0200 Subject: [PATCH 214/306] host/mesh: Inclusive terminology Implements the Bluetooth appropriate language mapping for the Bluetooth mesh subsystem. Changes the following terms: - Master security credentials -> Flooding security credentials - Whitelist filter -> Accept filter - Blacklist filter -> Reject filter - Removes CDB's NODE_BLACKLISTED, which was not in use. This is port of 035d877967cbaa43d8d8d73344450a1a9ed5d1f8 --- nimble/host/mesh/include/mesh/cdb.h | 1 - nimble/host/mesh/src/friend.c | 4 ++-- nimble/host/mesh/src/gatt_services.c | 26 +++++++++++++------------- nimble/host/mesh/src/lpn.c | 2 +- nimble/host/mesh/src/net.c | 2 +- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/nimble/host/mesh/include/mesh/cdb.h b/nimble/host/mesh/include/mesh/cdb.h index 440390cd62..444fb5d295 100644 --- a/nimble/host/mesh/include/mesh/cdb.h +++ b/nimble/host/mesh/include/mesh/cdb.h @@ -22,7 +22,6 @@ enum { BT_MESH_CDB_NODE_CONFIGURED, - BT_MESH_CDB_NODE_BLACKLISTED, BT_MESH_CDB_NODE_FLAG_COUNT }; diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index dc7d78425f..475fbd54e4 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -474,14 +474,14 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, } static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf, - bool master_cred) + bool flooding_cred) { const struct bt_mesh_net_cred *cred; uint32_t iv_index; uint16_t src; int err; - if (master_cred) { + if (flooding_cred) { cred = &frnd->subnet->keys[SUBNET_KEY_TX_IDX(frnd->subnet)] .msg; } else { diff --git a/nimble/host/mesh/src/gatt_services.c b/nimble/host/mesh/src/gatt_services.c index b74e596fe5..40b2165c76 100644 --- a/nimble/host/mesh/src/gatt_services.c +++ b/nimble/host/mesh/src/gatt_services.c @@ -134,8 +134,8 @@ static struct bt_mesh_proxy_client { uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)]; enum __packed { NONE, - WHITELIST, - BLACKLIST, + ACCEPT, + REJECT, PROV, } filter_type; #if MYNEWT_VAL(BLE_MESH_GATT_PROXY) @@ -226,11 +226,11 @@ static int filter_set(struct bt_mesh_proxy_client *client, switch (type) { case 0x00: (void)memset(client->filter, 0, sizeof(client->filter)); - client->filter_type = WHITELIST; + client->filter_type = ACCEPT; break; case 0x01: (void)memset(client->filter, 0, sizeof(client->filter)); - client->filter_type = BLACKLIST; + client->filter_type = REJECT; break; default: BT_WARN("Prohibited Filter Type 0x%02x", type); @@ -301,7 +301,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, net_buf_simple_add_u8(buf, CFG_FILTER_STATUS); - if (client->filter_type == WHITELIST) { + if (client->filter_type == ACCEPT) { net_buf_simple_add_u8(buf, 0x00); } else { net_buf_simple_add_u8(buf, 0x01); @@ -707,7 +707,7 @@ static void proxy_ccc_write(uint16_t conn_handle) __ASSERT(client, "No client for connection"); if (client->filter_type == NONE) { - client->filter_type = WHITELIST; + client->filter_type = ACCEPT; k_work_add_arg(&client->send_beacons, client); k_work_submit(&client->send_beacons); } @@ -739,7 +739,7 @@ int bt_mesh_proxy_gatt_enable(void) for (i = 0; i < ARRAY_SIZE(clients); i++) { if (clients[i].cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) { - clients[i].filter_type = WHITELIST; + clients[i].filter_type = ACCEPT; } } return 0; @@ -756,8 +756,8 @@ void bt_mesh_proxy_gatt_disconnect(void) struct bt_mesh_proxy_client *client = &clients[i]; if ((client->cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) && - (client->filter_type == WHITELIST || - client->filter_type == BLACKLIST)) { + (client->filter_type == ACCEPT || + client->filter_type == REJECT)) { client->filter_type = NONE; rc = ble_gap_terminate(client->cli.conn_handle, BLE_ERR_REM_USER_CONN_TERM); @@ -799,9 +799,9 @@ void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr) BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); - if (client->filter_type == WHITELIST) { + if (client->filter_type == ACCEPT) { filter_add(client, addr); - } else if (client->filter_type == BLACKLIST) { + } else if (client->filter_type == REJECT) { filter_remove(client, addr); } } @@ -813,7 +813,7 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); - if (client->filter_type == BLACKLIST) { + if (client->filter_type == REJECT) { for (i = 0; i < ARRAY_SIZE(client->filter); i++) { if (client->filter[i] == addr) { return false; @@ -827,7 +827,7 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, return true; } - if (client->filter_type == WHITELIST) { + if (client->filter_type == ACCEPT) { for (i = 0; i < ARRAY_SIZE(client->filter); i++) { if (client->filter[i] == addr) { return true; diff --git a/nimble/host/mesh/src/lpn.c b/nimble/host/mesh/src/lpn.c index ad6cfe4d25..1d2f229e6b 100644 --- a/nimble/host/mesh/src/lpn.c +++ b/nimble/host/mesh/src/lpn.c @@ -980,7 +980,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, if (!lpn->established) { /* This is normally checked on the transport layer, however - * in this state we're also still accepting master + * in this state we're also still accepting flooding * credentials so we need to ensure the right ones (Friend * Credentials) were used for this message. */ diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index 521a9859ed..e5391bf21c 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -704,7 +704,7 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf, bt_hex(buf->om_data, buf->om_len)); /* When the Friend node relays message for lpn, the message will be - * retransmitted using the managed master security credentials and + * retransmitted using the managed flooding security credentials and * the Network PDU shall be retransmitted to all network interfaces. */ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && From 15c0ff03daab703eedf1fbb67c7a0d5325920d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 14:28:41 +0200 Subject: [PATCH 215/306] host/mesh: Return ETIMEDOUT if k_sem_take call times out EAGAIN is used in some other places in the code, e.g. if node is not provisioned when a model tries to send a message. This change helps to differentiated if the acknowledged message timed out from other failers. This is port of e40998a4e48bd792843043bbcfa7849c9ce78358 --- nimble/host/mesh/src/msg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/msg.c b/nimble/host/mesh/src/msg.c index 853a0f43dc..230a2ab434 100644 --- a/nimble/host/mesh/src/msg.c +++ b/nimble/host/mesh/src/msg.c @@ -65,9 +65,13 @@ int bt_mesh_msg_ack_ctx_wait(struct bt_mesh_msg_ack_ctx *ack, int32_t timeout) err = k_sem_take(&ack->sem, timeout); bt_mesh_msg_ack_ctx_clear(ack); - return err; + if (err == -EAGAIN) { + return -ETIMEDOUT; } + return err; +} + bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, uint32_t op, uint16_t addr, void **user_data) { From 58c2a94ffb207ca33bb6a70e75359e530bd9d9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 15:02:57 +0200 Subject: [PATCH 216/306] host/mesh: Refactoring provisioning to make all OOB auth working The current implementation has hidden dependencies that break OOB authentication if provisioner does not have the configured input or output fields used for device capabilities. It didn't allow to pass several OOB authentication cases. After refactoring provisioner behavior is independent to provisionee settings. This is port of 6f2516d9a7bdb4537d044f7776e524b3e95101d0 --- nimble/host/mesh/src/prov.c | 201 +++++++++++++++++++---------- nimble/host/mesh/src/prov.h | 4 +- nimble/host/mesh/src/prov_device.c | 5 +- nimble/host/mesh/src/provisioner.c | 32 +---- 4 files changed, 147 insertions(+), 95 deletions(-) diff --git a/nimble/host/mesh/src/prov.c b/nimble/host/mesh/src/prov.c index 64ad656c41..cdadbb45ba 100644 --- a/nimble/host/mesh/src/prov.c +++ b/nimble/host/mesh/src/prov.c @@ -99,10 +99,98 @@ static bt_mesh_input_action_t input_action(uint8_t action) } } -int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size) +static int check_output_auth(bt_mesh_output_action_t output, uint8_t size) +{ + if (!output) { + return -EINVAL; + } + + if (!(bt_mesh_prov->output_actions & output)) { + return -EINVAL; + } + + if (size > bt_mesh_prov->output_size) { + return -EINVAL; + } + + return 0; +} + +static int check_input_auth(bt_mesh_input_action_t input, uint8_t size) +{ + if (!input) { + return -EINVAL; + } + + if (!(bt_mesh_prov->input_actions & input)) { + return -EINVAL; + } + + if (size > bt_mesh_prov->input_size) { + return -EINVAL; + } + + return 0; +} + +static void get_auth_string(char *str, uint8_t size) +{ + uint64_t value; + + bt_rand(&value, sizeof(value)); + + static const char characters[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + for (int i = 0; i < size; i++) { + /* pull base-36 digits: */ + int idx = value % 36; + + value = value / 36; + str[i] = characters[idx]; + } + + str[size] = '\0'; + + memcpy(bt_mesh_prov_link.auth, str, size); + memset(bt_mesh_prov_link.auth + size, 0, + sizeof(bt_mesh_prov_link.auth) - size); +} + +static uint32_t get_auth_number(bt_mesh_output_action_t output, + bt_mesh_input_action_t input, uint8_t size) + { + const uint32_t divider[PROV_IO_OOB_SIZE_MAX] = { 10, 100, 1000, 10000, + 100000, 1000000, 10000000, 100000000 }; + uint32_t num = 0; + + bt_rand(&num, sizeof(num)); + + if (output == BT_MESH_BLINK || + output == BT_MESH_BEEP || + output == BT_MESH_VIBRATE || + input == BT_MESH_PUSH || + input == BT_MESH_TWIST) { + /* According to the Bluetooth Mesh Profile + * Specification Section 5.4.2.4, blink, beep + * vibrate, push and twist should be a random integer + * between 0 and 10^size, *exclusive*: + */ + num = (num % (divider[size - 1] - 1)) + 1; + } else { + num %= divider[size - 1]; + } + + sys_put_be32(num, &bt_mesh_prov_link.auth[12]); + memset(bt_mesh_prov_link.auth, 0, 12); + + return num; + } + +int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8_t size) { bt_mesh_output_action_t output; bt_mesh_input_action_t input; + int err; switch (method) { case AUTH_METHOD_NO_OOB: @@ -123,89 +211,63 @@ int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size) case AUTH_METHOD_OUTPUT: output = output_action(action); - if (!output) { - return -EINVAL; - } + if (is_provisioner) { + if (output == BT_MESH_DISPLAY_STRING) { + input = BT_MESH_ENTER_STRING; + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING); + } else { + input = BT_MESH_ENTER_NUMBER; + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER); + } - if (!(bt_mesh_prov->output_actions & output)) { - return -EINVAL; + return bt_mesh_prov->input(input, size); } - if (size > bt_mesh_prov->output_size) { - return -EINVAL; + err = check_output_auth(output, size); + if (err) { + return err; } - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - if (output == BT_MESH_DISPLAY_STRING) { - unsigned char str[9]; - uint8_t i; - - bt_rand(str, size); - - /* Normalize to '0' .. '9' & 'A' .. 'Z' */ - for (i = 0; i < size; i++) { - str[i] %= 36; - if (str[i] < 10) { - str[i] += '0'; - } else { - str[i] += 'A' - 10; - } - } - str[size] = '\0'; - - memcpy(bt_mesh_prov_link.auth, str, size); - memset(bt_mesh_prov_link.auth + size, 0, - sizeof(bt_mesh_prov_link.auth) - size); - - return bt_mesh_prov->output_string((char *)str); - } else { - uint32_t div[8] = { 10, 100, 1000, 10000, 100000, - 1000000, 10000000, 100000000 }; - uint32_t num; - - bt_rand(&num, sizeof(num)); - - if (output == BT_MESH_BLINK || - output == BT_MESH_BEEP || - output == BT_MESH_VIBRATE) { - /* According to the Bluetooth Mesh Profile - * Specification Section 5.4.2.4, blink, beep - * and vibrate should be a random integer - * between 0 and 10^size, *exclusive*: - */ - num = (num % (div[size - 1] - 1)) + 1; - } else { - num %= div[size - 1]; - } + char str[9]; - sys_put_be32(num, &bt_mesh_prov_link.auth[12]); - memset(bt_mesh_prov_link.auth, 0, 12); - - return bt_mesh_prov->output_number(output, num); + atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); + get_auth_string(str, size); + return bt_mesh_prov->output_string(str); } + atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); + return bt_mesh_prov->output_number(output, + get_auth_number(output, BT_MESH_NO_INPUT, size)); case AUTH_METHOD_INPUT: input = input_action(action); - if (!input) { - return -EINVAL; - } + if (!is_provisioner) { + err = check_input_auth(input, size); + if (err) { + return err; + } - if (!(bt_mesh_prov->input_actions & input)) { - return -EINVAL; - } + if (input == BT_MESH_ENTER_STRING) { + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING); + } else { + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER); + } - if (size > bt_mesh_prov->input_size) { - return -EINVAL; + return bt_mesh_prov->input(input, size); } if (input == BT_MESH_ENTER_STRING) { - atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING); - } else { - atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER); + char str[9]; + + atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); + get_auth_string(str, size); + return bt_mesh_prov->output_string(str); } - return bt_mesh_prov->input(input, size); + atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); + output = BT_MESH_DISPLAY_NUMBER; + return bt_mesh_prov->output_number(output, + get_auth_number(BT_MESH_NO_OUTPUT, input, size)); default: return -EINVAL; @@ -231,11 +293,16 @@ int bt_mesh_input_string(const char *str) { BT_DBG("%s", str); + if (strlen(str) > PROV_IO_OOB_SIZE_MAX || + strlen(str) > bt_mesh_prov_link.oob_size) { + return -ENOTSUP; + } + if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_STRING)) { return -EINVAL; } - strncpy((char *)bt_mesh_prov_link.auth, str, bt_mesh_prov->input_size); + strcpy((char *)bt_mesh_prov_link.auth, str); bt_mesh_prov_link.role->input_complete(); diff --git a/nimble/host/mesh/src/prov.h b/nimble/host/mesh/src/prov.h index b287fb2a00..d18ee0ebb7 100644 --- a/nimble/host/mesh/src/prov.h +++ b/nimble/host/mesh/src/prov.h @@ -71,6 +71,8 @@ #define PROV_ALG_P256 0x00 +#define PROV_IO_OOB_SIZE_MAX 8 /* in bytes */ + #define PROV_BUF(len) \ NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + PDU_OP_LEN + len) @@ -154,7 +156,7 @@ int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[BT_PUB_KEY_LEN])); bool bt_mesh_prov_active(void); -int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size); +int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8_t size); int bt_mesh_pb_gatt_open(uint16_t conn_handle); int bt_mesh_pb_gatt_close(uint16_t conn_handle); diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index ab387c3681..5931444348 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -132,8 +132,11 @@ static void prov_start(const uint8_t *data) memcpy(bt_mesh_prov_link.conf_inputs.start, data, PDU_LEN_START); bt_mesh_prov_link.expect = PROV_PUB_KEY; + bt_mesh_prov_link.oob_method = data[2]; + bt_mesh_prov_link.oob_action = data[3]; + bt_mesh_prov_link.oob_size = data[4]; - if (bt_mesh_prov_auth(data[2], data[3], data[4]) < 0) { + if (bt_mesh_prov_auth(false, data[2], data[3], data[4]) < 0) { BT_ERR("Invalid authentication method: 0x%02x; " "action: 0x%02x; size: 0x%02x", data[2], data[3], data[4]); diff --git a/nimble/host/mesh/src/provisioner.c b/nimble/host/mesh/src/provisioner.c index e5cb22ffaa..f4278e110b 100644 --- a/nimble/host/mesh/src/provisioner.c +++ b/nimble/host/mesh/src/provisioner.c @@ -97,7 +97,6 @@ static void start_sent(int err, void *cb_data) static void send_start(void) { BT_DBG(""); - uint8_t method, action; struct os_mbuf *start = PROV_BUF(PDU_LEN_START); bool oob_pub_key = bt_mesh_prov_link.conf_inputs.capabilities[3] == PUB_KEY_OOB; @@ -114,26 +113,6 @@ static void send_start(void) net_buf_simple_add_u8(start, PUB_KEY_NO_OOB); } - if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) { - method = AUTH_METHOD_OUTPUT; - if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) { - action = OUTPUT_OOB_STRING; - } else { - action = OUTPUT_OOB_NUMBER; - } - - } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) { - method = AUTH_METHOD_INPUT; - if (bt_mesh_prov_link.oob_action == OUTPUT_OOB_STRING) { - action = INPUT_OOB_STRING; - } else { - action = INPUT_OOB_NUMBER; - } - } else { - method = bt_mesh_prov_link.oob_method; - action = 0x00; - } - net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_method); net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_action); @@ -142,10 +121,11 @@ static void send_start(void) memcpy(bt_mesh_prov_link.conf_inputs.invite, &start->om_data[1], PDU_LEN_INVITE); - if (bt_mesh_prov_auth(method, action, bt_mesh_prov_link.oob_size) < 0) { + if (bt_mesh_prov_auth(true, bt_mesh_prov_link.oob_method, + bt_mesh_prov_link.oob_action, bt_mesh_prov_link.oob_size) < 0) { BT_ERR("Invalid authentication method: 0x%02x; " - "action: 0x%02x; size: 0x%02x", method, - action, bt_mesh_prov_link.oob_size); + "action: 0x%02x; size: 0x%02x", bt_mesh_prov_link.oob_method, + bt_mesh_prov_link.oob_action, bt_mesh_prov_link.oob_size); return; } @@ -686,7 +666,7 @@ static void prov_set_method(uint8_t method, uint8_t action, uint8_t size) int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size) { - if (!action || !size || size > 8) { + if (!action || !size || size > PROV_IO_OOB_SIZE_MAX) { return -EINVAL; } @@ -696,7 +676,7 @@ int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size) int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size) { - if (!action || !size || size > 8) { + if (!action || !size || size > PROV_IO_OOB_SIZE_MAX) { return -EINVAL; } From 16450e8603d1da37e5c0690dd77e80ba65bd7ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 14 Oct 2021 15:11:01 +0200 Subject: [PATCH 217/306] host/mesh: Delete bt_mesh_proxy_prov_disable parameter. we will no longer need the additional `disconnect` parameter, such as we only process gatt database from disconnect handler. This is port of 412e7da951db24768a17c46c51661714bfc17d00 --- nimble/host/mesh/src/gatt_services.c | 57 ++++++++++------------------ nimble/host/mesh/src/mesh.c | 32 ++++++---------- nimble/host/mesh/src/prov_device.c | 6 ++- nimble/host/mesh/src/proxy.h | 2 +- nimble/host/mesh/src/settings.c | 2 +- 5 files changed, 39 insertions(+), 60 deletions(-) diff --git a/nimble/host/mesh/src/gatt_services.c b/nimble/host/mesh/src/gatt_services.c index 40b2165c76..600946eeeb 100644 --- a/nimble/host/mesh/src/gatt_services.c +++ b/nimble/host/mesh/src/gatt_services.c @@ -948,32 +948,34 @@ static void gatt_connected(uint16_t conn_handle) static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) { - int i; - BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason); + struct bt_mesh_proxy_client *client; conn_count--; - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; + client = find_client(conn_handle); + if (!client) { + BT_WARN("No Gatt Client found"); + return; + } - if (client->cli.conn_handle != conn_handle) { - continue; - } + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && client->filter_type == PROV) { + bt_mesh_pb_gatt_close(conn_handle); + client->filter_type = NONE; - if ((MYNEWT_VAL(BLE_MESH_PB_GATT)) && - client->filter_type == PROV) { - bt_mesh_pb_gatt_close(conn_handle); + if (bt_mesh_is_provisioned() && + IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && + bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) { + (void)bt_mesh_proxy_gatt_enable(); } - - /* If this fails, the work handler exits early, as - * there's no active connection. - */ - (void)k_work_cancel_delayable(&client->cli.sar_timer); - client->cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; - break; } + /* If this fails, the work handler exits early, as + * there's no active connection. + */ + (void)k_work_cancel_delayable(&client->cli.sar_timer); + client->cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; + bt_mesh_adv_update(); } @@ -1100,11 +1102,10 @@ int bt_mesh_proxy_prov_enable(void) return 0; } -int bt_mesh_proxy_prov_disable(bool disconnect) +int bt_mesh_proxy_prov_disable(void) { uint16_t handle; int rc; - int i; BT_DBG(""); @@ -1124,24 +1125,6 @@ int bt_mesh_proxy_prov_disable(bool disconnect) gatt_svc = MESH_GATT_NONE; - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; - - if (client->cli.conn_handle == BLE_HS_CONN_HANDLE_NONE - || client->filter_type != PROV) { - continue; - } - - if (disconnect) { - rc = ble_gap_terminate(client->cli.conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); - } else { - bt_mesh_pb_gatt_close(client->cli.conn_handle); - client->filter_type = NONE; - } - } - bt_mesh_adv_update(); return 0; diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index 0d9c21e668..b4d658f71d 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -44,7 +44,6 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, uint8_t flags, uint32_t iv_index, uint16_t addr, const uint8_t dev_key[16]) { - bool pb_gatt_enabled; int err; BT_INFO("Primary Element: 0x%04x", addr); @@ -55,16 +54,6 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, return -EALREADY; } - if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) { - if (bt_mesh_proxy_prov_disable(false) == 0) { - pb_gatt_enabled = true; - } else { - pb_gatt_enabled = false; - } - } else { - pb_gatt_enabled = false; - } - /* * FIXME: * Should net_key and iv_index be over-ridden? @@ -110,10 +99,6 @@ int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, if (err) { atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); - if (MYNEWT_VAL(BLE_MESH_PB_GATT) && pb_gatt_enabled) { - (void)bt_mesh_proxy_prov_enable(); - } - return err; } @@ -194,7 +179,7 @@ void bt_mesh_reset(void) } if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) { - bt_mesh_proxy_gatt_disable(); + (void)bt_mesh_proxy_gatt_disable(); } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { @@ -385,10 +370,17 @@ int bt_mesh_start(void) bt_mesh_beacon_disable(); } - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) { - bt_mesh_proxy_gatt_enable(); - bt_mesh_adv_update(); + /* For PB-GATT provision, will enable in le disconnect handler. */ + if (bt_mesh_prov_link.bearer->type == BT_MESH_PROV_ADV) { + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { + (void)bt_mesh_proxy_prov_disable(); + } + + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && + bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) { + (void)bt_mesh_proxy_gatt_enable(); + bt_mesh_adv_update(); + } } if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index 5931444348..312ecc514b 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -614,6 +614,10 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers) return -EALREADY; } + if (bt_mesh_prov_active()) { + return -EBUSY; + } + if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && (bearers & BT_MESH_PROV_ADV)) { bt_mesh_beacon_disable(); @@ -622,7 +626,7 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers) if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && (bearers & BT_MESH_PROV_GATT)) { - bt_mesh_proxy_prov_disable(true); + (void)bt_mesh_proxy_prov_disable(); } return 0; diff --git a/nimble/host/mesh/src/proxy.h b/nimble/host/mesh/src/proxy.h index 2ddb834ea1..7a79cef5e1 100644 --- a/nimble/host/mesh/src/proxy.h +++ b/nimble/host/mesh/src/proxy.h @@ -21,7 +21,7 @@ int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, void (*end)(uint16_t, void *), void *user_data); int bt_mesh_proxy_prov_enable(void); -int bt_mesh_proxy_prov_disable(bool disconnect); +int bt_mesh_proxy_prov_disable(void); int bt_mesh_proxy_gatt_enable(void); int bt_mesh_proxy_gatt_disable(void); diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index 5ec6d71e9e..cc9fd630f5 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -70,7 +70,7 @@ static int mesh_commit(void) } if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - bt_mesh_proxy_prov_disable(true); + (void)bt_mesh_proxy_prov_disable(); } bt_mesh_net_settings_commit(); From 2d7536ef6042602705ab704d7ddf82ca26772c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 20 Oct 2021 07:08:22 +0200 Subject: [PATCH 218/306] host/mesh: Extended advertising support Adds support for extended advertiser commands in the mesh. This doubles throughput for common packet sending, and significantly improves timing accuracy for the Friend and Low Power features. The proxy module's advertisement control has been moved inside the adv module to abstract away the different advertiser modes. The extended advertiser mode does not need an advertising thread to operate, and ends up with a net reduction in RAM usage. This is port of 81bf99145ab712997d4b8db6ba37538f9de3bc46 --- nimble/host/mesh/include/mesh/glue.h | 80 +++++- nimble/host/mesh/src/adv.c | 226 +---------------- nimble/host/mesh/src/adv.h | 32 +++ nimble/host/mesh/src/adv_ext.c | 354 +++++++++++++++++++++++++++ nimble/host/mesh/src/adv_legacy.c | 240 ++++++++++++++++++ nimble/host/mesh/src/gatt_services.c | 117 ++++----- nimble/host/mesh/src/glue.c | 37 ++- nimble/host/mesh/src/mesh.c | 8 + nimble/host/mesh/src/pb_adv.c | 16 ++ nimble/host/mesh/src/proxy.h | 3 +- nimble/host/mesh/syscfg.yml | 31 +++ 11 files changed, 836 insertions(+), 308 deletions(-) create mode 100644 nimble/host/mesh/src/adv_ext.c create mode 100644 nimble/host/mesh/src/adv_legacy.c diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 1e7f842202..422f2b8018 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -258,6 +258,12 @@ static inline void net_buf_simple_reset(struct os_mbuf *om) net_buf_simple_init(om, 0); } +struct bt_le_ext_adv_start_param { + uint16_t timeout; + + uint8_t num_events; +}; + void net_buf_put(struct ble_npl_eventq *fifo, struct os_mbuf *buf); void * net_buf_ref(struct os_mbuf *om); void net_buf_unref(struct os_mbuf *om); @@ -328,6 +334,74 @@ struct bt_pub_key_cb { struct bt_pub_key_cb *_next; }; +/** LE Advertising Parameters. */ +struct bt_le_adv_param { + /** + * @brief Local identity. + * + * @note When extended advertising @kconfig{CONFIG_BT_EXT_ADV} is not + * enabled or not supported by the controller it is not possible + * to scan and advertise simultaneously using two different + * random addresses. + */ + uint8_t id; + + /** + * @brief Advertising Set Identifier, valid range 0x00 - 0x0f. + * + * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV + **/ + uint8_t sid; + + /** + * @brief Secondary channel maximum skip count. + * + * Maximum advertising events the advertiser can skip before it must + * send advertising data on the secondary advertising channel. + * + * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV + */ + uint8_t secondary_max_skip; + + /** Bit-field of advertising options */ + uint32_t options; + + /** Minimum Advertising Interval (N * 0.625 milliseconds) + * Minimum Advertising Interval shall be less than or equal to the + * Maximum Advertising Interval. The Minimum Advertising Interval and + * Maximum Advertising Interval should not be the same value (as stated + * in Bluetooth Core Spec 5.2, section 7.8.5) + * Range: 0x0020 to 0x4000 + */ + uint32_t interval_min; + + /** Maximum Advertising Interval (N * 0.625 milliseconds) + * Minimum Advertising Interval shall be less than or equal to the + * Maximum Advertising Interval. The Minimum Advertising Interval and + * Maximum Advertising Interval should not be the same value (as stated + * in Bluetooth Core Spec 5.2, section 7.8.5) + * Range: 0x0020 to 0x4000 + */ + uint32_t interval_max; + + /** + * @brief Directed advertising to peer + * + * When this parameter is set the advertiser will send directed + * advertising to the remote device. + * + * The advertising type will either be high duty cycle, or low duty + * cycle if the BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY option is enabled. + * When using @ref BT_LE_ADV_OPT_EXT_ADV then only low duty cycle is + * allowed. + * + * In case of connectable high duty cycle if the connection could not + * be established within the timeout the connected() callback will be + * called with the status set to @ref BT_HCI_ERR_ADV_TIMEOUT. + */ + const bt_addr_le_t *peer; +}; + typedef void (*bt_dh_key_cb_t)(const uint8_t key[BT_DH_KEY_LEN]); int bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN], bt_dh_key_cb_t cb); int bt_pub_key_gen(struct bt_pub_key_cb *new_cb); @@ -343,9 +417,11 @@ int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_ uint8_t *plaintext, size_t mic_size); void bt_mesh_register_gatt(void); int bt_le_adv_start(const struct ble_gap_adv_params *param, + int64_t duration, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len); -int bt_le_adv_stop(bool proxy); + +int bt_le_adv_stop(); struct k_work_delayable { struct ble_npl_callout work; @@ -358,6 +434,7 @@ bool k_work_delayable_is_pending(struct k_work_delayable *w); void k_work_reschedule(struct k_work_delayable *w, uint32_t ms); int64_t k_uptime_get(void); uint32_t k_uptime_get_32(void); +int64_t k_uptime_delta(int64_t *reftime); void k_sleep(int32_t duration); void k_work_submit(struct ble_npl_callout *w); void k_work_add_arg(struct ble_npl_callout *w, void *arg); @@ -428,6 +505,7 @@ static inline unsigned int find_msb_set(uint32_t op) #define CONFIG_BT_MESH_PROV_DEVICE BLE_MESH_PROV_DEVICE #define CONFIG_BT_MESH_CDB BLE_MESH_CDB #define CONFIG_BT_MESH_DEBUG_CFG BLE_MESH_DEBUG_CFG +#define CONFIG_BT_MESH_DEBUG_ADV BLE_MESH_DEBUG_ADV /* Above flags are used with IS_ENABLED macro */ #define IS_ENABLED(config) MYNEWT_VAL(config) diff --git a/nimble/host/mesh/src/adv.c b/nimble/host/mesh/src/adv.c index b3d6290819..0b0205cbc2 100644 --- a/nimble/host/mesh/src/adv.c +++ b/nimble/host/mesh/src/adv.c @@ -13,7 +13,6 @@ #include "mesh/mesh.h" #include "host/ble_hs_adv.h" #include "host/ble_gap.h" -#include "nimble/hci_common.h" #include "mesh/porting.h" #include "adv.h" @@ -23,42 +22,21 @@ #include "prov.h" #include "proxy.h" -/* Convert from ms to 0.625ms units */ -#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) - /* Window and Interval are equal for continuous scanning */ -#define MESH_SCAN_INTERVAL_MS 30 -#define MESH_SCAN_WINDOW_MS 30 -#define MESH_SCAN_INTERVAL ADV_SCAN_UNIT(MESH_SCAN_INTERVAL_MS) -#define MESH_SCAN_WINDOW ADV_SCAN_UNIT(MESH_SCAN_WINDOW_MS) - -/* Pre-5.0 controllers enforce a minimum interval of 100ms - * whereas 5.0+ controllers can go down to 20ms. - */ -#define ADV_INT_DEFAULT_MS 100 -#define ADV_INT_FAST_MS 20 +#define MESH_SCAN_INTERVAL BT_MESH_ADV_SCAN_UNIT(BT_MESH_SCAN_INTERVAL_MS) +#define MESH_SCAN_WINDOW BT_MESH_ADV_SCAN_UNIT(BT_MESH_SCAN_WINDOW_MS) -static int32_t adv_int_min = ADV_INT_DEFAULT_MS; +const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = { + [BT_MESH_ADV_PROV] = BT_DATA_MESH_PROV, + [BT_MESH_ADV_DATA] = BT_DATA_MESH_MESSAGE, + [BT_MESH_ADV_BEACON] = BT_DATA_MESH_BEACON, + [BT_MESH_ADV_URI] = BT_DATA_URI, +}; -/* TinyCrypt PRNG consumes a lot of stack space, so we need to have - * an increased call stack whenever it's used. - */ -#if MYNEWT -OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); -struct os_task adv_task; -#endif - -static struct ble_npl_eventq adv_queue; extern uint8_t g_mesh_addr_type; -static int adv_initialized = false; - -static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( - MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; struct os_mbuf_pool adv_os_mbuf_pool; -static struct os_mempool adv_buf_mempool; - +static struct ble_npl_eventq bt_mesh_adv_queue; static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT]; static struct bt_mesh_adv *adv_alloc(int id) @@ -66,153 +44,6 @@ static struct bt_mesh_adv *adv_alloc(int id) return &adv_pool[id]; } -static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->end) { - cb->end(err, cb_data); - } -} - -static inline void adv_send(struct os_mbuf *buf) -{ - static const uint8_t adv_type[] = { - [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV, - [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE, - [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON, - [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI, -} ; - - const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb; - void *cb_data = BT_MESH_ADV(buf)->cb_data; - struct ble_gap_adv_params param = { 0 }; - uint16_t duration, adv_int; - struct bt_data ad; - int err; - - adv_int = max(adv_int_min, - BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit)); -#if MYNEWT_VAL(BLE_CONTROLLER) - duration = ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * - (adv_int + 10)); -#else - /* Zephyr Bluetooth Low Energy Controller for mesh stack uses - * pre-emptible continuous scanning, allowing advertising events to be - * transmitted without delay when advertising is enabled. No need to - * compensate with scan window duration. - * An advertising event could be delayed by upto one interval when - * advertising is stopped and started in quick succession, hence add - * advertising interval to the total advertising duration. - */ - duration = (adv_int + - ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * - (adv_int + 10))); - - /* Zephyr Bluetooth Low Energy Controller built for nRF51x SoCs use - * CONFIG_BT_CTLR_LOW_LAT=y, and continuous scanning cannot be - * pre-empted, hence, scanning will block advertising events from - * being transmitted. Increase the advertising duration by the - * amount of scan window duration to compensate for the blocked - * advertising events. - */ - if (MYNEWT_VAL(BSP_NRF51)) { - duration += BT_MESH_SCAN_WINDOW_MS; - } -#endif - - BT_DBG("type %u om_len %u: %s", BT_MESH_ADV(buf)->type, - buf->om_len, bt_hex(buf->om_data, buf->om_len)); - BT_DBG("count %u interval %ums duration %ums", - BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int, - duration); - - ad.type = adv_type[BT_MESH_ADV(buf)->type]; - ad.data_len = buf->om_len; - ad.data = buf->om_data; - - param.itvl_min = ADV_SCAN_UNIT(adv_int); - param.itvl_max = param.itvl_min; - param.conn_mode = BLE_GAP_CONN_MODE_NON; - - err = bt_le_adv_start(¶m, &ad, 1, NULL, 0); - net_buf_unref(buf); - adv_send_start(duration, err, cb, cb_data); - if (err) { - BT_ERR("Advertising failed: err %d", err); - return; - } - - BT_DBG("Advertising started. Sleeping %u ms", duration); - - k_sleep(K_MSEC(duration)); - - err = bt_le_adv_stop(false); - adv_send_end(err, cb, cb_data); - if (err) { - BT_ERR("Stopping advertising failed: err %d", err); - return; - } - - BT_DBG("Advertising stopped"); -} - -void -mesh_adv_thread(void *args) -{ - static struct ble_npl_event *ev; - struct os_mbuf *buf; -#if (MYNEWT_VAL(BLE_MESH_PROXY)) - int32_t timeout; -#endif - - BT_DBG("started"); - - while (1) { -#if (MYNEWT_VAL(BLE_MESH_PROXY)) - ev = ble_npl_eventq_get(&adv_queue, 0); - while (!ev) { - timeout = bt_mesh_proxy_adv_start(); - BT_DBG("Proxy Advertising up to %d ms", (int) timeout); - - // FIXME: should we redefine K_SECONDS macro instead in glue? - if (timeout != K_FOREVER) { - timeout = ble_npl_time_ms_to_ticks32(timeout); - } - - ev = ble_npl_eventq_get(&adv_queue, timeout); - bt_mesh_proxy_adv_stop(); - } -#else - ev = ble_npl_eventq_get(&adv_queue, BLE_NPL_TIME_FOREVER); -#endif - - if (!ev || !ble_npl_event_get_arg(ev)) { - continue; - } - - buf = ble_npl_event_get_arg(ev); - - /* busy == 0 means this was canceled */ - if (BT_MESH_ADV(buf)->busy) { - BT_MESH_ADV(buf)->busy = 0; - adv_send(buf); - } else { - net_buf_unref(buf); - } - - /* os_sched(NULL); */ - } -} - -void bt_mesh_adv_update(void) -{ - static struct ble_npl_event ev = { }; - - BT_DBG(""); - - ble_npl_eventq_put(&adv_queue, &ev); -} - struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool, bt_mesh_adv_alloc_t get_id, enum bt_mesh_adv_type type, @@ -262,7 +93,8 @@ void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb, BT_MESH_ADV(buf)->cb_data = cb_data; BT_MESH_ADV(buf)->busy = 1; - net_buf_put(&adv_queue, net_buf_ref(buf)); + net_buf_put(&bt_mesh_adv_queue, net_buf_ref(buf)); + bt_mesh_adv_buf_ready(); } static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi, @@ -316,42 +148,6 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi, } } -void bt_mesh_adv_init(void) -{ - int rc; - - /* Advertising should only be initialized once. Calling - * os_task init the second time will result in an assert. */ - if (adv_initialized) { - return; - } - - rc = os_mempool_init(&adv_buf_mempool, MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, - adv_buf_mem, "adv_buf_pool"); - assert(rc == 0); - - rc = os_mbuf_pool_init(&adv_os_mbuf_pool, &adv_buf_mempool, - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, - MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)); - assert(rc == 0); - - ble_npl_eventq_init(&adv_queue); - -#if MYNEWT - os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL, - MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER, - g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); -#endif - - /* For BT5 controllers we can have fast advertising interval */ - if (ble_hs_hci_get_hci_version() >= BLE_HCI_VER_BCS_5_0) { - adv_int_min = ADV_INT_FAST_MS; - } - - adv_initialized = true; -} - int ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg) { diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index ba6d3c8d7f..9412bb0ce9 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -14,6 +14,10 @@ #define BT_MESH_ADV(om) (*(struct bt_mesh_adv **) OS_MBUF_USRHDR(om)) +#define BT_MESH_ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) +#define BT_MESH_SCAN_INTERVAL_MS 30 +#define BT_MESH_SCAN_WINDOW_MS 30 + #define BT_MESH_ADV_DATA_SIZE 31 /* The user data is a pointer (4 bytes) to struct bt_mesh_adv */ @@ -23,12 +27,17 @@ BT_MESH_ADV_USER_DATA_SIZE +\ sizeof(struct os_mbuf)) +/* We declare it as extern here to share it between 'adv' and 'adv_legacy' */ +extern struct os_mbuf_pool adv_os_mbuf_pool; + enum bt_mesh_adv_type { BT_MESH_ADV_PROV, BT_MESH_ADV_DATA, BT_MESH_ADV_BEACON, BT_MESH_ADV_URI, + + BT_MESH_ADV_TYPES, }; typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration, @@ -82,6 +91,29 @@ void bt_mesh_adv_init(void); int bt_mesh_scan_enable(void); int bt_mesh_scan_disable(void); +int bt_mesh_adv_enable(void); + +void bt_mesh_adv_buf_ready(void); + +int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len); + +static inline void bt_mesh_adv_send_start(uint16_t duration, int err, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + if (cb && cb->start) { + cb->start(duration, err, cb_data); + } +} +static inline void bt_mesh_adv_send_end( + int err, const struct bt_mesh_send_cb *cb, void *cb_data) +{ + if (cb && cb->end) { + cb->end(err, cb_data); + } +} int ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg); #endif diff --git a/nimble/host/mesh/src/adv_ext.c b/nimble/host/mesh/src/adv_ext.c new file mode 100644 index 0000000000..2dd7d13666 --- /dev/null +++ b/nimble/host/mesh/src/adv_ext.c @@ -0,0 +1,354 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define MESH_LOG_MODULE BLE_MESH_ADV_LOG +#define LOG_MODULE_NAME bt_mesh_adv_ext + + +#include "adv.h" +#include "net.h" +#include "proxy.h" +#include "syscfg/syscfg.h" +#include "host/ble_gap.h" + +#if MYNEWT_VAL(BLE_MESH_ADV_EXT) +/* Convert from ms to 0.625ms units */ +#define ADV_INT_FAST_MS 20 +#define BT_ID_DEFAULT 0 + +static struct ble_gap_ext_adv_params adv_param = { + .itvl_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS), + .itvl_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS), +}; + +bool ext_adv_configured = false; +static struct ble_npl_eventq bt_mesh_adv_queue; + +enum { + /** Controller is currently advertising */ + ADV_FLAG_ACTIVE, + /** Currently performing proxy advertising */ + ADV_FLAG_PROXY, + /** The send-call has been scheduled. */ + ADV_FLAG_SCHEDULED, + /** Custom adv params have been set, we need to update the parameters on + * the next send. + */ + ADV_FLAG_UPDATE_PARAMS, + + /* Number of adv flags. */ + ADV_FLAGS_NUM +}; + +static struct { + ATOMIC_DEFINE(flags, ADV_FLAGS_NUM); + struct bt_le_ext_adv *instance; + const struct bt_mesh_send_cb *cb; + void *cb_data; + int64_t timestamp; + struct k_work_delayable work; +} adv; + + +static void schedule_send(void) +{ + int64_t timestamp = adv.timestamp; + int64_t delta; + + if (atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { + ble_gap_ext_adv_stop(BT_ID_DEFAULT); + atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); + } + + if (atomic_test_bit(adv.flags, ADV_FLAG_ACTIVE) || + atomic_test_and_set_bit(adv.flags, ADV_FLAG_SCHEDULED)) { + return; + } + + /* The controller will send the next advertisement immediately. + * Introduce a delay here to avoid sending the next mesh packet closer + * to the previous packet than what's permitted by the specification. + */ + delta = k_uptime_delta(×tamp); + k_work_reschedule(&adv.work, K_MSEC(ADV_INT_FAST_MS - delta)); +} + +static int +ble_mesh_ext_adv_event_handler(struct ble_gap_event *event, void *arg) +{ + int64_t duration; + + switch (event->type) { + case BLE_GAP_EVENT_CONNECT: + if (atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { + atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); + schedule_send(); + } + break; + case BLE_GAP_EVENT_ADV_COMPLETE: + /* Calling k_uptime_delta on a timestamp moves it to the current time. + * This is essential here, as schedule_send() uses the end of the event + * as a reference to avoid sending the next advertisement too soon. + */ + duration = k_uptime_delta(&adv.timestamp); + + BT_DBG("Advertising stopped after %u ms", (uint32_t)duration); + + atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); + + if (!atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { + bt_mesh_adv_send_end(0, adv.cb, adv.cb_data); + } + + schedule_send(); + break; + default: + return 0; + } + return 0; +} + +static int adv_start(const struct ble_gap_ext_adv_params *param, + uint32_t timeout, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len) +{ + int err; + struct os_mbuf *ad_data; + struct os_mbuf *sd_data; + + ad_data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0); + assert(ad_data); + sd_data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0); + assert(sd_data); + if (!adv.instance) { + BT_ERR("Mesh advertiser not enabled"); + err = -ENODEV; + goto error; + } + + if (atomic_test_and_set_bit(adv.flags, ADV_FLAG_ACTIVE)) { + BT_ERR("Advertiser is busy"); + err = -EBUSY; + goto error; + } + + if (atomic_test_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS)) { + err = ble_gap_ext_adv_configure(BT_ID_DEFAULT, param, NULL, + ble_mesh_ext_adv_event_handler, NULL); + if (err) { + BT_ERR("Failed updating adv params: %d", err); + atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); + goto error; + } + + atomic_set_bit_to(adv.flags, ADV_FLAG_UPDATE_PARAMS, + param != &adv_param); + } + + assert(ad_data); + err = os_mbuf_append(ad_data, ad, ad_len); + if (err) { + goto error; + } + + err = ble_gap_ext_adv_set_data(BT_ID_DEFAULT, ad_data); + if (err) { + BT_ERR("Failed setting adv data: %d", err); + atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); + goto error; + } + + err = os_mbuf_append(sd_data, sd, sd_len); + if (err) { + goto error; + } + err = ble_gap_ext_adv_rsp_set_data(BT_ID_DEFAULT, sd_data); + if (err) { + BT_ERR("Failed setting scan response data: %d", err); + atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); + goto error; + } + + adv.timestamp = k_uptime_get(); + + err = ble_gap_ext_adv_start(BT_ID_DEFAULT, timeout, 0); + if (err) { + BT_ERR("Advertising failed: err %d", err); + atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); + } + +error: + if (ad_data) { + os_mbuf_free_chain(ad_data); + } + + if (sd_data) { + os_mbuf_free_chain(sd_data); + } + return err; +} + +static int buf_send(struct os_mbuf *buf) +{ + static const uint8_t bt_mesh_adv_type[] = { + [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV, + [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE, + [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON, + [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI, + }; + + struct bt_le_ext_adv_start_param start = { + .num_events = + BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, + }; + uint16_t duration, adv_int; + struct bt_data ad; + int err; + + adv_int = MAX(ADV_INT_FAST_MS, + BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit)); + /* Upper boundary estimate: */ + duration = start.num_events * (adv_int + 10); + + BT_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type, + buf->om_len, bt_hex(buf->om_data, buf->om_len)); + BT_DBG("count %u interval %ums duration %ums", + BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int, + duration); + + ad.type = bt_mesh_adv_type[BT_MESH_ADV(buf)->type]; + ad.data_len = buf->om_len; + ad.data = buf->om_data; + + /* Only update advertising parameters if they're different */ + if (adv_param.itvl_min != BT_MESH_ADV_SCAN_UNIT(adv_int)) { + adv_param.itvl_min = BT_MESH_ADV_SCAN_UNIT(adv_int); + adv_param.itvl_max = adv_param.itvl_min; + atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS); + } + + adv.cb = BT_MESH_ADV(buf)->cb; + adv.cb_data = BT_MESH_ADV(buf)->cb_data; + + err = adv_start(&adv_param, duration, &ad, 1, NULL, 0); + net_buf_unref(buf); + bt_mesh_adv_send_start(duration, err, adv.cb, adv.cb_data); + + return err; +} + +static void send_pending_adv(struct ble_npl_event *work) +{ + struct os_mbuf *buf; + int err; + + atomic_clear_bit(adv.flags, ADV_FLAG_SCHEDULED); + + while ((buf = net_buf_get(&bt_mesh_adv_queue, K_NO_WAIT))) { + /* busy == 0 means this was canceled */ + if (!BT_MESH_ADV(buf)->busy) { + net_buf_unref(buf); + continue; + } + + BT_MESH_ADV(buf)->busy = 0U; + err = buf_send(buf); + if (!err) { + return; /* Wait for advertising to finish */ + } + } + + /* No more pending buffers */ + if (MYNEWT_VAL(BLE_MESH_GATT_SERVER)) { + BT_DBG("Proxy Advertising"); + err = bt_mesh_proxy_adv_start(); + if (!err) { + atomic_set_bit(adv.flags, ADV_FLAG_PROXY); + } + } +} + +void bt_mesh_adv_update(void) +{ + BT_DBG(""); + + schedule_send(); +} + +void bt_mesh_adv_buf_ready(void) +{ + schedule_send(); +} + +void bt_mesh_adv_init(void) +{ + k_work_init_delayable(&adv.work, send_pending_adv); +} + +int bt_mesh_adv_enable(void) +{ + struct ble_gap_ext_adv_params params; + ble_addr_t addr; + int rc; + + if (ext_adv_configured) { + /* Already initialized */ + return 0; + } + + params.itvl_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS); + params.itvl_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS); + + if (MYNEWT_VAL(BLE_MESH_DEBUG_USE_ID_ADDR)) { + params.own_addr_type = BLE_OWN_ADDR_PUBLIC; + } else { + params.own_addr_type = BLE_OWN_ADDR_RANDOM; + /* set random (NRPA) address for instance */ + rc = ble_hs_id_gen_rnd(1, &addr); + assert (rc == 0); + + rc = ble_gap_ext_adv_set_addr(BT_ID_DEFAULT, &addr ); + assert (rc == 0); + } + + params.primary_phy = BLE_HCI_LE_PHY_1M; + params.secondary_phy = BLE_HCI_LE_PHY_1M; + params.tx_power = 127; + params.sid = 4; + + rc = ble_gap_ext_adv_configure(BT_ID_DEFAULT, ¶ms, NULL, + ble_mesh_ext_adv_event_handler, NULL); + if (rc == 0) { + ext_adv_configured = true; + } + + return rc; +} + +int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len) +{ + static uint32_t adv_timeout; + struct ble_gap_ext_adv_params params = { + .itvl_min = param->itvl_min, + .itvl_max = param->itvl_max + }; + + /* In NimBLE duration is in ms, not 10ms units */ + adv_timeout = (duration == BLE_HS_FOREVER) ? 0 : duration; + + BT_DBG("Start advertising %d ms", duration); + + atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS); + + return adv_start(¶ms, adv_timeout, ad, ad_len, sd, sd_len); +} +#endif diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c new file mode 100644 index 0000000000..c07da896c6 --- /dev/null +++ b/nimble/host/mesh/src/adv_legacy.c @@ -0,0 +1,240 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2018 Nordic Semiconductor ASA + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define MESH_LOG_MODULE BLE_MESH_ADV_LOG +#define LOG_MODULE_NAME bt_mesh_adv_legacy + +#include "adv.h" +#include "net.h" +#include "foundation.h" +#include "beacon.h" +#include "prov.h" +#include "proxy.h" + +#if MYNEWT_VAL(BLE_MESH_ADV_LEGACY) +/* Convert from ms to 0.625ms units */ +#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) + +/* Pre-5.0 controllers enforce a minimum interval of 100ms + * whereas 5.0+ controllers can go down to 20ms. + */ +#define ADV_INT_DEFAULT_MS 100 +#define ADV_INT_FAST_MS 20 + +static int32_t adv_int_min = ADV_INT_DEFAULT_MS; + +#if !MYNEWT_VAL(BLE_EXT_ADV) +static int adv_initialized = false; +/* TinyCrypt PRNG consumes a lot of stack space, so we need to have + * an increased call stack whenever it's used. + */ +#if MYNEWT +OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); +struct os_task adv_task; +#endif +static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( + MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), + BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; +static struct os_mempool adv_buf_mempool; +#endif +static struct ble_npl_eventq adv_queue; + +static inline void adv_send(struct os_mbuf *buf) +{ + static const uint8_t adv_type[] = { + [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV, + [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE, + [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON, + [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI, + }; + const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb; + void *cb_data = BT_MESH_ADV(buf)->cb_data; + struct ble_gap_adv_params param = { 0 }; + uint16_t duration, adv_int; + struct bt_data ad; + int err; + + adv_int = max(adv_int_min, + BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit)); +#if MYNEWT_VAL(BLE_CONTROLLER) + duration = ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * + (adv_int + 10)); +#else + /* Zephyr Bluetooth Low Energy Controller for mesh stack uses + * pre-emptible continuous scanning, allowing advertising events to be + * transmitted without delay when advertising is enabled. No need to + * compensate with scan window duration. + * An advertising event could be delayed by upto one interval when + * advertising is stopped and started in quick succession, hence add + * advertising interval to the total advertising duration. + */ + duration = (adv_int + + ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * + (adv_int + 10))); + + /* Zephyr Bluetooth Low Energy Controller built for nRF51x SoCs use + * CONFIG_BT_CTLR_LOW_LAT=y, and continuous scanning cannot be + * pre-empted, hence, scanning will block advertising events from + * being transmitted. Increase the advertising duration by the + * amount of scan window duration to compensate for the blocked + * advertising events. + */ + if (MYNEWT_VAL(BSP_NRF51)) { + duration += BT_MESH_SCAN_WINDOW_MS; + } +#endif + + BT_DBG("type %u om_len %u: %s", BT_MESH_ADV(buf)->type, + buf->om_len, bt_hex(buf->om_data, buf->om_len)); + BT_DBG("count %u interval %ums duration %ums", + BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int, + duration); + + ad.type = adv_type[BT_MESH_ADV(buf)->type]; + ad.data_len = buf->om_len; + ad.data = buf->om_data; + + param.itvl_min = ADV_SCAN_UNIT(adv_int); + param.itvl_max = param.itvl_min; + param.conn_mode = BLE_GAP_CONN_MODE_NON; + + err = bt_le_adv_start(¶m, duration, &ad, 1, NULL, 0); + + net_buf_unref(buf); + adv_send_start(duration, err, cb, cb_data); + if (err) { + BT_ERR("Advertising failed: err %d", err); + return; + } + + BT_DBG("Advertising started. Sleeping %u ms", duration); + + k_sleep(K_MSEC(duration)); + + err = bt_le_adv_stop(); + bt_mesh_adv_send_end(err, cb, cb_data); + if (err) { + BT_ERR("Stopping advertising failed: err %d", err); + return; + } + + BT_DBG("Advertising stopped"); +} + +void +adv_thread(void *args) +{ + static struct ble_npl_event *ev; + struct os_mbuf *buf; +#if (MYNEWT_VAL(BLE_MESH_PROXY)) + int32_t timeout; +#endif + + BT_DBG("started"); + + while (1) { +#if (MYNEWT_VAL(BLE_MESH_PROXY)) + ev = ble_npl_eventq_get(&adv_queue, 0); + while (!ev) { + timeout = bt_mesh_proxy_adv_start(); + BT_DBG("Proxy Advertising up to %d ms", (int) timeout); + + // FIXME: should we redefine K_SECONDS macro instead in glue? + if (timeout != K_FOREVER) { + timeout = ble_npl_time_ms_to_ticks32(timeout); + } + + ev = ble_npl_eventq_get(&adv_queue, timeout); + bt_le_adv_stop(); + } +#else + ev = ble_npl_eventq_get(&adv_queue, BLE_NPL_TIME_FOREVER); +#endif + + if (!ev || !ble_npl_event_get_arg(ev)) { + continue; + } + + buf = ble_npl_event_get_arg(ev); + + /* busy == 0 means this was canceled */ + if (BT_MESH_ADV(buf)->busy) { + BT_MESH_ADV(buf)->busy = 0; + adv_send(buf); + } else { + net_buf_unref(buf); + } + + /* os_sched(NULL); */ + } +} + +void bt_mesh_adv_update(void) +{ + static struct ble_npl_event ev = { }; + + BT_DBG(""); + + ble_npl_eventq_put(&adv_queue, &ev); +} + +void bt_mesh_adv_buf_ready(void) +{ + /* Will be handled automatically */ +} + +void bt_mesh_adv_init(void) +{ + int rc; + + /* Advertising should only be initialized once. Calling + * os_task init the second time will result in an assert. */ + if (adv_initialized) { + return; + } + + rc = os_mempool_init(&adv_buf_mempool, MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), + BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, + adv_buf_mem, "adv_buf_pool"); + assert(rc == 0); + + rc = os_mbuf_pool_init(&adv_os_mbuf_pool, &adv_buf_mempool, + BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, + MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)); + assert(rc == 0); + + ble_npl_eventq_init(&adv_queue); + +#if MYNEWT + os_task_init(&adv_task, "mesh_adv", adv_thread, NULL, + MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER, + g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); +#endif + + /* For BT5 controllers we can have fast advertising interval */ + if (ble_hs_hci_get_hci_version() >= BLE_HCI_VER_BCS_5_0) { + adv_int_min = ADV_INT_FAST_MS; + } + + adv_initialized = true; +} + +int bt_mesh_adv_enable(void) +{ + /* Dummy function - in legacy adv thread is started on init*/ + return 0; +} + +int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, + const struct bt_data *ad, size_t ad_len, + const struct bt_data *sd, size_t sd_len) +{ + return bt_le_adv_start(param, duration, ad, ad_len, sd, sd_len); +} +#endif \ No newline at end of file diff --git a/nimble/host/mesh/src/gatt_services.c b/nimble/host/mesh/src/gatt_services.c index 600946eeeb..40909b6964 100644 --- a/nimble/host/mesh/src/gatt_services.c +++ b/nimble/host/mesh/src/gatt_services.c @@ -101,8 +101,6 @@ ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); .itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, \ .itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, -static bool gatt_adv_enabled; - static struct { uint16_t proxy_h; uint16_t proxy_data_out_h; @@ -479,7 +477,7 @@ static const struct bt_data net_id_ad[] = { BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN), }; -static int node_id_adv(struct bt_mesh_subnet *sub) +static int node_id_adv(struct bt_mesh_subnet *sub, int32_t duration) { struct ble_gap_adv_params fast_adv_param = { ADV_OPT_PROXY @@ -520,7 +518,7 @@ static int node_id_adv(struct bt_mesh_subnet *sub) memcpy(proxy_svc_data + 3, tmp + 8, 8); - err = bt_le_adv_start(&fast_adv_param, node_id_ad, + err = bt_le_adv_start(&fast_adv_param, duration, node_id_ad, ARRAY_SIZE(node_id_ad), sd, 0); if (err) { BT_WARN("Failed to advertise using Node ID (err %d)", err); @@ -530,7 +528,7 @@ static int node_id_adv(struct bt_mesh_subnet *sub) return 0; } -static int net_id_adv(struct bt_mesh_subnet *sub) +static int net_id_adv(struct bt_mesh_subnet *sub, int32_t duration) { struct ble_gap_adv_params slow_adv_param = { ADV_OPT_PROXY @@ -558,7 +556,7 @@ static int net_id_adv(struct bt_mesh_subnet *sub) memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8); - err = bt_le_adv_start(&slow_adv_param, net_id_ad, + err = bt_le_adv_start(&slow_adv_param, duration, net_id_ad, ARRAY_SIZE(net_id_ad), sd, 0); if (err) { BT_WARN("Failed to advertise using Network ID (err %d)", err); @@ -628,6 +626,7 @@ static int gatt_proxy_advertise(struct bt_mesh_subnet *sub) { int32_t remaining = K_FOREVER; int subnet_count; + int err = -EBUSY; BT_DBG(""); @@ -642,24 +641,6 @@ static int gatt_proxy_advertise(struct bt_mesh_subnet *sub) return -ENOENT; } - if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) { - uint32_t active = k_uptime_get_32() - sub->node_id_start; - - if (active < NODE_ID_TIMEOUT) { - remaining = NODE_ID_TIMEOUT - active; - BT_DBG("Node ID active for %u ms, %d ms remaining", - (unsigned) active, (int) remaining); - node_id_adv(sub); - } else { - bt_mesh_proxy_identity_stop(sub); - BT_DBG("Node ID stopped"); - } - } - - if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) { - net_id_adv(sub); - } - subnet_count = sub_count(); BT_DBG("sub_count %u", subnet_count); if (subnet_count > 1) { @@ -678,12 +659,30 @@ static int gatt_proxy_advertise(struct bt_mesh_subnet *sub) } } + if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) { + uint32_t active = k_uptime_get_32() - sub->node_id_start; + + if (active < NODE_ID_TIMEOUT) { + remaining = NODE_ID_TIMEOUT - active; + BT_DBG("Node ID active for %u ms, %d ms remaining", + active, remaining); + err = node_id_adv(sub, remaining); + } else { + bt_mesh_proxy_identity_stop(sub); + BT_DBG("Node ID stopped"); + } + } + + if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) { + err = net_id_adv(sub, remaining); + } + BT_DBG("Advertising %d ms for net_idx 0x%04x", (int) remaining, sub->net_idx); beacon_sub = bt_mesh_subnet_next(beacon_sub); - return remaining; + return err; } static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) @@ -926,9 +925,6 @@ static void gatt_connected(uint16_t conn_handle) conn_count++; - /* Since we use ADV_OPT_ONE_TIME */ - gatt_adv_enabled = false; - /* Try to re-enable advertising in case it's possible */ if (conn_count < CONFIG_BT_MAX_CONN) { bt_mesh_adv_update(); @@ -1234,12 +1230,12 @@ static int proxy_send(uint16_t conn_handle, return err; } -int32_t bt_mesh_proxy_adv_start(void) +int bt_mesh_proxy_adv_start(void) { BT_DBG(""); if (gatt_svc == MESH_GATT_NONE) { - return K_FOREVER; + return -ENOENT; } #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) @@ -1249,30 +1245,32 @@ int32_t bt_mesh_proxy_adv_start(void) ADV_OPT_PROV ADV_FAST_INT }; + struct ble_gap_adv_params slow_adv_param = { + ADV_OPT_PROV + ADV_SLOW_INT + }; struct bt_data prov_sd[1]; size_t prov_sd_len; - - if (prov_fast_adv) { - param = &fast_adv_param; - } else { - struct ble_gap_adv_params slow_adv_param = { - ADV_OPT_PROV - ADV_SLOW_INT - }; - param = &slow_adv_param; - } + int err; prov_sd_len = gatt_prov_adv_create(prov_sd); - - if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad), - prov_sd, prov_sd_len) == 0) { - gatt_adv_enabled = true; - - /* Advertise 60 seconds using fast interval */ - if (prov_fast_adv) { + if (!prov_fast_adv) { + param = &slow_adv_param; + return bt_mesh_adv_start(param, + K_FOREVER, prov_ad, + ARRAY_SIZE(prov_ad), prov_sd, + prov_sd_len); + } else { + param = &fast_adv_param; + err = bt_mesh_adv_start(param, + (60 * MSEC_PER_SEC), prov_ad, + ARRAY_SIZE(prov_ad), prov_sd, + prov_sd_len); + if (!err) { prov_fast_adv = false; - return K_SECONDS(60); } + + return err; } } #endif /* PB_GATT */ @@ -1283,7 +1281,7 @@ int32_t bt_mesh_proxy_adv_start(void) } #endif /* GATT_PROXY */ - return K_FOREVER; + return -ENOTSUP; } @@ -1306,7 +1304,7 @@ static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) return; } - proxy_connected(event->adv_complete.conn_handle); + gatt_connected(event->adv_complete.conn_handle); } #else if (event->type == BLE_GAP_EVENT_CONNECT) { @@ -1339,25 +1337,6 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) return 0; } - -void bt_mesh_proxy_adv_stop(void) -{ - int err; - - BT_DBG("adv_enabled %u", gatt_adv_enabled); - - if (!gatt_adv_enabled) { - return; - } - - err = bt_le_adv_stop(true); - if (err) { - BT_ERR("Failed to stop advertising (err %d)", err); - } else { - gatt_adv_enabled = false; - } -} - static void resolve_svc_handles(void) { int rc; diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index 4e4715f2f0..8a9ff39cea 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -517,6 +517,17 @@ uint32_t k_uptime_get_32(void) return k_uptime_get(); } +int64_t k_uptime_delta(int64_t *reftime) +{ + int64_t uptime, delta; + + uptime = k_uptime_get(); + delta = uptime - *reftime; + *reftime = uptime; + + return delta; +} + void k_sleep(int32_t duration) { uint32_t ticks; @@ -672,6 +683,7 @@ ble_adv_conf_adv_instance(const struct ble_gap_adv_params *param, int *instance) int bt_le_adv_start(const struct ble_gap_adv_params *param, + int64_t duration, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) { @@ -737,7 +749,7 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, } /*TODO: We could use duration and max events in the future */ - err = ble_gap_ext_adv_start(instance, 0, 0); + err = ble_gap_ext_adv_start(instance, duration, 0); return err; error: @@ -747,28 +759,11 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, return err; } - -int bt_le_adv_stop(bool proxy) -{ -#if MYNEWT_VAL(BLE_MESH_PROXY) - int rc; - - if (proxy) { - rc = ble_gap_ext_adv_stop(BT_MESH_ADV_GATT_INST); - } else { - rc = ble_gap_ext_adv_stop(BT_MESH_ADV_INST); - } - - return rc; -#else - return ble_gap_ext_adv_stop(BT_MESH_ADV_INST); -#endif -} - #else int bt_le_adv_start(const struct ble_gap_adv_params *param, + int64_t duration, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) { @@ -802,7 +797,7 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, } } - err = ble_gap_adv_start(g_mesh_addr_type, NULL, BLE_HS_FOREVER, param, + err = ble_gap_adv_start(g_mesh_addr_type, NULL, duration, param, NULL, NULL); if (err) { BT_ERR("Advertising failed: err %d", err); @@ -812,7 +807,7 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, return 0; } -int bt_le_adv_stop(bool proxy) +int bt_le_adv_stop() { return ble_gap_adv_stop(); } diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index b4d658f71d..32697c1d1b 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -364,6 +364,14 @@ static void model_start(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, int bt_mesh_start(void) { + int err; + + err = bt_mesh_adv_enable(); + if (err) { + BT_ERR("Failed enabling advertiser"); + return err; + } + if (bt_mesh_beacon_enabled()) { bt_mesh_beacon_enable(); } else { diff --git a/nimble/host/mesh/src/pb_adv.c b/nimble/host/mesh/src/pb_adv.c index 3e136a2070..1fa2c35b24 100644 --- a/nimble/host/mesh/src/pb_adv.c +++ b/nimble/host/mesh/src/pb_adv.c @@ -821,8 +821,16 @@ void bt_mesh_pb_adv_recv(struct os_mbuf *buf) static int prov_link_open(const uint8_t uuid[16], int32_t timeout, const struct prov_bearer_cb *cb, void *cb_data) { + int err; + BT_DBG("uuid %s", bt_hex(uuid, 16)); + err = bt_mesh_adv_enable(); + if (err) { + BT_ERR("Failed enabling advertiser"); + return err; + } + if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACTIVE)) { return -EBUSY; } @@ -842,6 +850,14 @@ static int prov_link_open(const uint8_t uuid[16], int32_t timeout, static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data) { + int err; + + err = bt_mesh_adv_enable(); + if (err) { + BT_ERR("Failed enabling advertiser"); + return err; + } + if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { return -EBUSY; } diff --git a/nimble/host/mesh/src/proxy.h b/nimble/host/mesh/src/proxy.h index 7a79cef5e1..cf9cb87a08 100644 --- a/nimble/host/mesh/src/proxy.h +++ b/nimble/host/mesh/src/proxy.h @@ -31,8 +31,7 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub); struct os_mbuf *bt_mesh_proxy_get_buf(void); -int32_t bt_mesh_proxy_adv_start(void); -void bt_mesh_proxy_adv_stop(void); +int bt_mesh_proxy_adv_start(void); void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub); void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub); diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index 3677791a0d..9ca21a7f77 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -232,6 +232,37 @@ syscfg.defs: supported outgoing segment count (BT_MESH_TX_SEG_MAX). value: 6 + BLE_MESH_ADV: + description: > + Advertiser mode + value: 1 + + BLE_MESH_ADV_LEGACY: + description: > + Use legacy advertising commands for mesh sending. Legacy + advertising is significantly slower than the extended advertising, but + is supported by all controllers. + value: 1 + restrictions: + - "BLE_MESH_ADV if 0" + - "!BLE_MESH_ADV_EXT" + + BLE_MESH_ADV_EXT: + description: > + Use extended advertising commands for operating the advertiser. + Extended advertising is faster and uses less memory than legacy + advertising, but isn't supported by all controllers. + value: 0 + restrictions: + - "BLE_MESH_ADV if 0" + - "!BLE_MESH_ADV_LEGACY" + - "BLE_EXT_ADV" + + BLE_MESH_DEBUG_USE_ID_ADDR: + description: > + Use ID address for mesh advertisements, use random address otherwise. + value: 0 + BLE_MESH_ADV_STACK_SIZE: description: > Mesh advertiser thread stack size. From efafc215d1384d2a05320c12abd71f1a1dbc176d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 20 Oct 2021 08:17:15 +0200 Subject: [PATCH 219/306] host/mesh: Reconstructing adv callback logic The adv callback logic is reconstructed to coexist with proxy send callback. This is port of a63f2d8d608a249967975628aeaba23684a5aed7 --- nimble/host/mesh/src/adv.h | 25 +++++++++++++++++-------- nimble/host/mesh/src/adv_ext.c | 18 ++++++++++-------- nimble/host/mesh/src/adv_legacy.c | 12 +++++------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index 9412bb0ce9..14be8f84f3 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -61,7 +61,9 @@ struct bt_mesh_adv { void *cb_data; uint8_t type:2, - busy:1; + started:1, + busy:1; + uint8_t xmit; uint8_t flags; @@ -100,19 +102,26 @@ int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, const struct bt_data *sd, size_t sd_len); static inline void bt_mesh_adv_send_start(uint16_t duration, int err, - const struct bt_mesh_send_cb *cb, - void *cb_data) + struct bt_mesh_adv *adv) { - if (cb && cb->start) { - cb->start(duration, err, cb_data); + if (!adv->started) { + adv->started = 1; + + if (adv->cb && adv->cb->start) { + adv->cb->start(duration, err, adv->cb_data); + } + + if (err) { + adv->cb = NULL; + } } } static inline void bt_mesh_adv_send_end( - int err, const struct bt_mesh_send_cb *cb, void *cb_data) + int err, struct bt_mesh_adv const *adv) { - if (cb && cb->end) { - cb->end(err, cb_data); + if (adv->started && adv->cb && adv->cb->end) { + adv->cb->end(err, adv->cb_data); } } int ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg); diff --git a/nimble/host/mesh/src/adv_ext.c b/nimble/host/mesh/src/adv_ext.c index 2dd7d13666..25f31a237e 100644 --- a/nimble/host/mesh/src/adv_ext.c +++ b/nimble/host/mesh/src/adv_ext.c @@ -49,8 +49,7 @@ enum { static struct { ATOMIC_DEFINE(flags, ADV_FLAGS_NUM); struct bt_le_ext_adv *instance; - const struct bt_mesh_send_cb *cb; - void *cb_data; + struct os_mbuf *buf; int64_t timestamp; struct k_work_delayable work; } adv; @@ -103,7 +102,7 @@ ble_mesh_ext_adv_event_handler(struct ble_gap_event *event, void *arg) atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); if (!atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { - bt_mesh_adv_send_end(0, adv.cb, adv.cb_data); + net_buf_unref(adv.buf); } schedule_send(); @@ -234,12 +233,12 @@ static int buf_send(struct os_mbuf *buf) atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS); } - adv.cb = BT_MESH_ADV(buf)->cb; - adv.cb_data = BT_MESH_ADV(buf)->cb_data; - err = adv_start(&adv_param, duration, &ad, 1, NULL, 0); - net_buf_unref(buf); - bt_mesh_adv_send_start(duration, err, adv.cb, adv.cb_data); + if (!err) { + adv.buf = net_buf_ref(buf); + } + + bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf)); return err; } @@ -260,6 +259,9 @@ static void send_pending_adv(struct ble_npl_event *work) BT_MESH_ADV(buf)->busy = 0U; err = buf_send(buf); + + net_buf_unref(buf); + if (!err) { return; /* Wait for advertising to finish */ } diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index c07da896c6..80ea76a915 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -53,8 +53,7 @@ static inline void adv_send(struct os_mbuf *buf) [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON, [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI, }; - const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb; - void *cb_data = BT_MESH_ADV(buf)->cb_data; + struct ble_gap_adv_params param = { 0 }; uint16_t duration, adv_int; struct bt_data ad; @@ -106,8 +105,8 @@ static inline void adv_send(struct os_mbuf *buf) err = bt_le_adv_start(¶m, duration, &ad, 1, NULL, 0); - net_buf_unref(buf); - adv_send_start(duration, err, cb, cb_data); + + bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf)); if (err) { BT_ERR("Advertising failed: err %d", err); return; @@ -118,7 +117,6 @@ static inline void adv_send(struct os_mbuf *buf) k_sleep(K_MSEC(duration)); err = bt_le_adv_stop(); - bt_mesh_adv_send_end(err, cb, cb_data); if (err) { BT_ERR("Stopping advertising failed: err %d", err); return; @@ -167,10 +165,10 @@ adv_thread(void *args) if (BT_MESH_ADV(buf)->busy) { BT_MESH_ADV(buf)->busy = 0; adv_send(buf); - } else { - net_buf_unref(buf); } + net_buf_unref(buf); + /* os_sched(NULL); */ } } From 2f5ce02fb9c0dc13f4104742e821362aed995536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 21 Oct 2021 13:05:01 +0200 Subject: [PATCH 220/306] host/mesh: Split gatt services to pb-gatt and proxy Split gatt services to pb-gatt-srv and proxy-srv. This is port of b2889903a3afb65bf88e82637452c14c59661a83 and c057a69a2c7bdbb9b2162d8f041411d13c238b37 --- nimble/host/mesh/include/mesh/glue.h | 1 + nimble/host/mesh/src/adv_ext.c | 21 +- nimble/host/mesh/src/adv_legacy.c | 12 +- nimble/host/mesh/src/glue.c | 28 + nimble/host/mesh/src/mesh.c | 12 +- nimble/host/mesh/src/pb_gatt.c | 11 +- nimble/host/mesh/src/pb_gatt_srv.c | 447 ++++++++++++++ nimble/host/mesh/src/pb_gatt_srv.h | 26 + nimble/host/mesh/src/prov_device.c | 3 +- nimble/host/mesh/src/proxy.h | 42 +- nimble/host/mesh/src/proxy_msg.h | 5 + .../mesh/src/{gatt_services.c => proxy_srv.c} | 552 ++---------------- nimble/host/mesh/src/settings.c | 3 +- nimble/host/mesh/syscfg.yml | 4 +- 14 files changed, 636 insertions(+), 531 deletions(-) create mode 100644 nimble/host/mesh/src/pb_gatt_srv.c create mode 100644 nimble/host/mesh/src/pb_gatt_srv.h rename nimble/host/mesh/src/{gatt_services.c => proxy_srv.c} (60%) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 422f2b8018..588e79a487 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -406,6 +406,7 @@ typedef void (*bt_dh_key_cb_t)(const uint8_t key[BT_DH_KEY_LEN]); int bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN], bt_dh_key_cb_t cb); int bt_pub_key_gen(struct bt_pub_key_cb *new_cb); uint8_t *bt_pub_key_get(void); +void bt_conn_get_info(struct ble_hs_conn *conn, struct ble_gap_conn_desc *desc); int bt_rand(void *buf, size_t len); const char * bt_hex(const void *buf, size_t len); int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data); diff --git a/nimble/host/mesh/src/adv_ext.c b/nimble/host/mesh/src/adv_ext.c index 25f31a237e..364fb249b3 100644 --- a/nimble/host/mesh/src/adv_ext.c +++ b/nimble/host/mesh/src/adv_ext.c @@ -14,6 +14,7 @@ #include "adv.h" #include "net.h" #include "proxy.h" +#include "pb_gatt_srv.h" #include "syscfg/syscfg.h" #include "host/ble_gap.h" @@ -267,13 +268,23 @@ static void send_pending_adv(struct ble_npl_event *work) } } + if (!MYNEWT_VAL(BLE_MESH_GATT_SERVER)) { + return; + } + /* No more pending buffers */ - if (MYNEWT_VAL(BLE_MESH_GATT_SERVER)) { - BT_DBG("Proxy Advertising"); - err = bt_mesh_proxy_adv_start(); - if (!err) { - atomic_set_bit(adv.flags, ADV_FLAG_PROXY); + if (bt_mesh_is_provisioned()) { + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + err = bt_mesh_pb_gatt_adv_start(); + BT_DBG("Proxy Advertising"); } + } else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { + err = bt_mesh_prov_adv_start(); + BT_DBG("PB-GATT Advertising"); + } + + if (!err) { + atomic_set_bit(adv.flags, ADV_FLAG_PROXY); } } diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 80ea76a915..9506c08baf 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -16,6 +16,7 @@ #include "beacon.h" #include "prov.h" #include "proxy.h" +#include "pb_gatt_srv.h" #if MYNEWT_VAL(BLE_MESH_ADV_LEGACY) /* Convert from ms to 0.625ms units */ @@ -140,8 +141,15 @@ adv_thread(void *args) #if (MYNEWT_VAL(BLE_MESH_PROXY)) ev = ble_npl_eventq_get(&adv_queue, 0); while (!ev) { - timeout = bt_mesh_proxy_adv_start(); - BT_DBG("Proxy Advertising up to %d ms", (int) timeout); + if (bt_mesh_is_provisioned()) { + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + timeout = bt_mesh_proxy_adv_start(); + BT_DBG("Proxy Advertising up to %d ms", (int) timeout); + } + } else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { + timeout = bt_mesh_pb_gatt_adv_start(); + BT_DBG("PB-GATT Advertising up to %d ms", (int) timeout); + } // FIXME: should we redefine K_SECONDS macro instead in glue? if (timeout != K_FOREVER) { diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index 8a9ff39cea..80f9b7e75e 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -22,6 +22,7 @@ #include "mesh/glue.h" #include "adv.h" +#include "../src/ble_hs_conn_priv.h" #ifndef MYNEWT #include "nimble/nimble_port.h" #endif @@ -555,6 +556,33 @@ bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb) return 0; } +void +bt_conn_get_info(struct ble_hs_conn *conn, + struct ble_gap_conn_desc *desc) +{ + struct ble_hs_conn_addrs addrs; + + ble_hs_conn_addrs(conn, &addrs); + + desc->our_id_addr = addrs.our_id_addr; + desc->peer_id_addr = addrs.peer_id_addr; + desc->our_ota_addr = addrs.our_ota_addr; + desc->peer_ota_addr = addrs.peer_ota_addr; + + desc->conn_handle = conn->bhc_handle; + desc->conn_itvl = conn->bhc_itvl; + desc->conn_latency = conn->bhc_latency; + desc->supervision_timeout = conn->bhc_supervision_timeout; + desc->master_clock_accuracy = conn->bhc_master_clock_accuracy; + desc->sec_state = conn->bhc_sec_state; + + if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) { + desc->role = BLE_GAP_ROLE_MASTER; + } else { + desc->role = BLE_GAP_ROLE_SLAVE; + } +} + int bt_rand(void *buf, size_t len) { diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index 32697c1d1b..1ac4d02641 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -35,6 +35,7 @@ #include "shell.h" #include "mesh_priv.h" #include "settings.h" +#include "pb_gatt_srv.h" uint8_t g_mesh_addr_type; @@ -315,7 +316,7 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, return err; } -#if (MYNEWT_VAL(BLE_MESH_PROXY)) +#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) bt_mesh_proxy_init(); #endif @@ -378,14 +379,13 @@ int bt_mesh_start(void) bt_mesh_beacon_disable(); } - /* For PB-GATT provision, will enable in le disconnect handler. */ - if (bt_mesh_prov_link.bearer->type == BT_MESH_PROV_ADV) { + if (!IS_ENABLED(CONFIG_BT_MESH_PROV) || !bt_mesh_prov_active() || + bt_mesh_prov_link.bearer->type == BT_MESH_PROV_ADV) { if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - (void)bt_mesh_proxy_prov_disable(); + (void)bt_mesh_pb_gatt_disable(); } - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) { + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { (void)bt_mesh_proxy_gatt_enable(); bt_mesh_adv_update(); } diff --git a/nimble/host/mesh/src/pb_gatt.c b/nimble/host/mesh/src/pb_gatt.c index fb04963219..761ebb0a54 100644 --- a/nimble/host/mesh/src/pb_gatt.c +++ b/nimble/host/mesh/src/pb_gatt.c @@ -6,6 +6,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ + #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #include "mesh/mesh.h" @@ -14,7 +15,10 @@ #include "proxy.h" #include "adv.h" #include "prov.h" +#include "syscfg/syscfg.h" +#include "pb_gatt_srv.h" +#if MYNEWT_VAL(BLE_MESH_PB_GATT) struct prov_bearer_send_cb { prov_bearer_send_complete_t cb; void *cb_data; @@ -45,7 +49,7 @@ static void reset_state(void) /* If this fails, the protocol timeout handler will exit early. */ (void)k_work_cancel_delayable(&link.prot_timer); - link.rx.buf = bt_mesh_proxy_get_buf(); + link.rx.buf = bt_mesh_pb_gatt_get_buf(); } static void link_closed(enum prov_bearer_link_status status) @@ -127,7 +131,7 @@ int bt_mesh_pb_gatt_close(uint16_t conn_handle) static int link_accept(const struct prov_bearer_cb *cb, void *cb_data) { - (void)bt_mesh_proxy_prov_enable(); + (void)bt_mesh_pb_gatt_enable(); bt_mesh_adv_update(); link.cb = cb; @@ -177,4 +181,5 @@ const struct prov_bearer pb_gatt = { .link_accept = link_accept, .send = buf_send, .clear_tx = clear_tx, -}; \ No newline at end of file +}; +#endif \ No newline at end of file diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c new file mode 100644 index 0000000000..7cb3257ccd --- /dev/null +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2021 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define MESH_LOG_MODULE BLE_MESH_PROV_LOG + +#include "mesh_priv.h" +#include "adv.h" +#include "net.h" +#include "rpl.h" +#include "transport.h" +#include "prov.h" +#include "beacon.h" +#include "foundation.h" +#include "access.h" +#include "proxy.h" +#include "proxy_msg.h" +#include "pb_gatt_srv.h" +#include "syscfg/syscfg.h" +#include "services/gatt/ble_svc_gatt.h" +#include "../../host/src/ble_hs_priv.h" + +#if MYNEWT_VAL(BLE_MESH_PB_GATT) +#define CLIENT_BUF_SIZE 66 + +/** @def BT_UUID_MESH_PROV + * @brief Mesh Provisioning Service + */ +ble_uuid16_t BT_UUID_MESH_PROV = BLE_UUID16_INIT(0x1827); +#define BT_UUID_MESH_PROV_VAL 0x1827 +/** @def BT_UUID_MESH_PROXY + * @brief Mesh Proxy Service + */ +ble_uuid16_t BT_UUID_MESH_PROXY = BLE_UUID16_INIT(0x1828); +#define BT_UUID_MESH_PROXY_VAL 0x1828 +/** @def BT_UUID_GATT_CCC + * @brief GATT Client Characteristic Configuration + */ +ble_uuid16_t BT_UUID_GATT_CCC = BLE_UUID16_INIT(0x2902); +#define BT_UUID_GATT_CCC_VAL 0x2902 +/** @def BT_UUID_MESH_PROV_DATA_IN + * @brief Mesh Provisioning Data In + */ +ble_uuid16_t BT_UUID_MESH_PROV_DATA_IN = BLE_UUID16_INIT(0x2adb); +#define BT_UUID_MESH_PROV_DATA_IN_VAL 0x2adb +/** @def BT_UUID_MESH_PROV_DATA_OUT + * @brief Mesh Provisioning Data Out + */ +ble_uuid16_t BT_UUID_MESH_PROV_DATA_OUT = BLE_UUID16_INIT(0x2adc); +#define BT_UUID_MESH_PROV_DATA_OUT_VAL 0x2adc +/** @def BT_UUID_MESH_PROXY_DATA_IN + * @brief Mesh Proxy Data In + */ +ble_uuid16_t BT_UUID_MESH_PROXY_DATA_IN = BLE_UUID16_INIT(0x2add); +#define BT_UUID_MESH_PROXY_DATA_IN_VAL 0x2add +/** @def BT_UUID_MESH_PROXY_DATA_OUT + * @brief Mesh Proxy Data Out + */ +ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); +#define BT_UUID_MESH_PROXY_DATA_OUT_VAL 0x2ade +#define BT_UUID_16_ENCODE(w16) \ + (((w16) >> 0) & 0xFF), \ + (((w16) >> 8) & 0xFF) + +static bool prov_fast_adv; + +static struct { + uint16_t proxy_h; + uint16_t proxy_data_out_h; + uint16_t prov_h; + uint16_t prov_data_in_h; + uint16_t prov_data_out_h; +} svc_handles; + +static int gatt_send(uint16_t conn_handle, + const void *data, uint16_t len, + void (*end)(uint16_t, void *), void *user_data); + +static struct bt_mesh_proxy_role cli = { + .cb.send = gatt_send, +}; + +static bool service_registered; + +static ssize_t gatt_recv(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + const uint8_t *data = ctxt->om->om_data; + uint16_t len = ctxt->om->om_len; + + + if (conn_handle != cli.conn_handle) { + return -ENOTCONN; + } + + if (len < 1) { + BT_WARN("Too small Proxy PDU"); + return -EINVAL; + } + + if (PDU_TYPE(data) == BT_MESH_PROXY_PROV) { + BT_WARN("Proxy PDU type doesn't match GATT service"); + return -EINVAL; + } + + return bt_mesh_proxy_msg_recv(&cli, data, len); +} + +void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err) +{ + struct ble_gap_conn_desc info; + struct ble_hs_conn *conn; + + conn = ble_hs_conn_find(conn_handle); + bt_conn_get_info(conn, &info); + if (info.role != BLE_GAP_ROLE_SLAVE || + !service_registered || bt_mesh_is_provisioned()) { + return; + } + + cli.conn_handle = conn_handle; + + BT_DBG("conn %p err 0x%02x", (void *)conn, err); + + net_buf_simple_reset(cli.buf); +} + +void gatt_disconnected_pb_gatt(uint16_t conn_handle, uint8_t reason) +{ + struct ble_gap_conn_desc info; + + struct ble_hs_conn *conn; + + conn = ble_hs_conn_find(conn_handle); + bt_conn_get_info(conn, &info); + if (info.role != BLE_GAP_ROLE_SLAVE || + !service_registered) { + return; + } + + if (cli.conn_handle != conn_handle) { + BT_WARN("No PB-GATT Client found"); + return; + } + + BT_DBG("conn %p reason 0x%02x", (void *)conn, reason); + + bt_mesh_pb_gatt_close(conn_handle); + + if (bt_mesh_is_provisioned()) { + (void)bt_mesh_pb_gatt_disable(); + + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + (void)bt_mesh_proxy_gatt_enable(); + } + } + + cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; + + bt_mesh_adv_update(); +} + +int prov_ccc_write(uint16_t conn_handle, uint8_t type) +{ + if (cli.conn_handle != conn_handle) { + BT_ERR("No PB-GATT Client found"); + return -ENOTCONN; + } + + if (type != BLE_GAP_EVENT_NOTIFY_RX) { + BT_WARN("Client wrote instead enabling notify"); + return BT_GATT_ERR(EINVAL); + } + + bt_mesh_pb_gatt_open(conn_handle); + + return 0; +} + +/* Mesh Provisioning Service Declaration */ +struct os_mbuf *bt_mesh_pb_gatt_get_buf(void) +{ + struct os_mbuf *buf = cli.buf; + + if (buf != NULL) { + net_buf_simple_init(buf, 0); + } + + return buf; +} + +static int +dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + /* + * We should never never enter this callback - it's attached to notify-only + * characteristic which are notified directly from mbuf. And we can't pass + * NULL as access_cb because gatts will assert on init... + */ + BLE_HS_DBG_ASSERT(0); + return 0; +} + +static const struct ble_gatt_svc_def svc_defs [] = { + { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), + .access_cb = gatt_recv, + .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, + }, { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), + .access_cb = dummy_access_cb, + .flags = BLE_GATT_CHR_F_NOTIFY, + }, { + 0, /* No more characteristics in this service. */ + } }, + }, { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + .characteristics = (struct ble_gatt_chr_def[]) { { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), + .access_cb = gatt_recv, + .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, + }, { + .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), + .access_cb = dummy_access_cb, + .flags = BLE_GATT_CHR_F_NOTIFY, + }, { + 0, /* No more characteristics in this service. */ + } }, + }, { + 0, /* No more services. */ + }, +}; + +void resolve_svc_handles(void) +{ + int rc; + + /* Either all handles are already resolved, or none of them */ + if (svc_handles.prov_data_out_h) { + return; + } + + /* + * We assert if attribute is not found since at this stage all attributes + * shall be already registered and thus shall be found. + */ + + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), + &svc_handles.proxy_h); + assert(rc == 0); + + rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), + BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), + NULL, &svc_handles.proxy_data_out_h); + assert(rc == 0); + + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + &svc_handles.prov_h); + assert(rc == 0); + + rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), + NULL, &svc_handles.prov_data_in_h); + assert(rc == 0); + + rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), + BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), + NULL, &svc_handles.prov_data_out_h); + assert(rc == 0); +} + + +int bt_mesh_proxy_svcs_register(void) +{ + int rc; + + rc = ble_gatts_count_cfg(svc_defs); + assert(rc == 0); + + rc = ble_gatts_add_svcs(svc_defs); + assert(rc == 0); + + return 0; +} + +int bt_mesh_pb_gatt_enable(void) +{ + int rc; + uint16_t handle; + BT_DBG(""); + + if (bt_mesh_is_provisioned()) { + return -ENOTSUP; + } + + if (service_registered) { + return -EBUSY; + } + + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); + assert(rc == 0); + ble_gatts_svc_set_visibility(handle, 1); + /* FIXME: figure out end handle */ + ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); + + service_registered = true; + prov_fast_adv = true; + + return 0; +} + +int bt_mesh_pb_gatt_disable(void) +{ + uint16_t handle; + int rc; + + BT_DBG(""); + + if (!service_registered) { + return -EALREADY; + } + + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); + assert(rc == 0); + ble_gatts_svc_set_visibility(handle, 0); + /* FIXME: figure out end handle */ + ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); + service_registered = false; + + bt_mesh_adv_update(); + + return 0; +} + +static uint8_t prov_svc_data[20] = { + BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL), +}; + +static const struct bt_data prov_ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, + BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)), + BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), +}; + +int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, + void (*end)(uint16_t, void *), void *user_data) +{ + if (cli.conn_handle != conn_handle) { + BT_ERR("No PB-GATT Client found"); + return -ENOTCONN; + } + + return bt_mesh_proxy_msg_send(&cli, BT_MESH_PROXY_PROV, buf, end, user_data); +} + +static size_t gatt_prov_adv_create(struct bt_data prov_sd[1]) +{ + const struct bt_mesh_prov *prov = bt_mesh_prov_get(); + size_t uri_len; + + memcpy(prov_svc_data + 2, prov->uuid, 16); + sys_put_be16(prov->oob_info, prov_svc_data + 18); + + if (!prov->uri) { + return 0; + } + + uri_len = strlen(prov->uri); + if (uri_len > 29) { + /* There's no way to shorten an URI */ + BT_WARN("Too long URI to fit advertising packet"); + return 0; + } + + prov_sd[0].type = BT_DATA_URI; + prov_sd[0].data_len = uri_len; + prov_sd[0].data = (const uint8_t *)prov->uri; + + return 1; +} + +static int gatt_send(uint16_t conn_handle, + const void *data, uint16_t len, + void (*end)(uint16_t, void *), void *user_data) +{ + struct os_mbuf *om; + int err = 0; + + BT_DBG("%u bytes: %s", len, bt_hex(data, len)); + om = ble_hs_mbuf_from_flat(data, len); + assert(om); + err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); + /* We do not pass cb into ble_gattc_notify_custom - execute it at the end */ + + end(conn_handle, user_data); + + return err; +} + +int bt_mesh_pb_gatt_adv_start(void) +{ + BT_DBG(""); + + if (!service_registered || bt_mesh_is_provisioned()) { + return -ENOTSUP; + } + + struct ble_gap_adv_params fast_adv_param = { + ADV_OPT_PROV + ADV_FAST_INT + }; + struct bt_data prov_sd[1]; + size_t prov_sd_len; + int err; + + prov_sd_len = gatt_prov_adv_create(prov_sd); + + if (!prov_fast_adv) { + struct ble_gap_adv_params slow_adv_param = { + ADV_OPT_PROV + ADV_SLOW_INT + }; + + return bt_mesh_adv_start(&slow_adv_param, K_FOREVER, prov_ad, + ARRAY_SIZE(prov_ad), prov_sd, prov_sd_len); + } + + /* Advertise 60 seconds using fast interval */ + err = bt_mesh_adv_start(&fast_adv_param, (60 * MSEC_PER_SEC), + prov_ad, ARRAY_SIZE(prov_ad), + prov_sd, prov_sd_len); + if (!err) { + prov_fast_adv = false; + } + + return err; +} +#endif \ No newline at end of file diff --git a/nimble/host/mesh/src/pb_gatt_srv.h b/nimble/host/mesh/src/pb_gatt_srv.h new file mode 100644 index 0000000000..561f2225e9 --- /dev/null +++ b/nimble/host/mesh/src/pb_gatt_srv.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2021 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __PB_GATT_SRV_H__ +#define __PB_GATT_SRV_H__ + +int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, + void (*end)(uint16_t, void *), void *user_data); + +int bt_mesh_pb_gatt_enable(void); +int bt_mesh_pb_gatt_disable(void); + +struct os_mbuf *bt_mesh_pb_gatt_get_buf(void); + +int prov_ccc_write(uint16_t conn_handle, uint8_t type); +void gatt_disconnected_pb_gatt(uint16_t conn_handle, uint8_t err); +void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err); +void resolve_svc_handles(void); + +int bt_mesh_pb_gatt_adv_start(void); + +#endif /* __PB_GATT_SRV_H__ */ \ No newline at end of file diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index 312ecc514b..9d48547e3d 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -21,6 +21,7 @@ #include "proxy.h" #include "prov.h" #include "settings.h" +#include "pb_gatt_srv.h" static void send_pub_key(void); static void pub_key_ready(const uint8_t *pkey); @@ -626,7 +627,7 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers) if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && (bearers & BT_MESH_PROV_GATT)) { - (void)bt_mesh_proxy_prov_disable(); + (void)bt_mesh_pb_gatt_disable(); } return 0; diff --git a/nimble/host/mesh/src/proxy.h b/nimble/host/mesh/src/proxy.h index cf9cb87a08..196f540b2e 100644 --- a/nimble/host/mesh/src/proxy.h +++ b/nimble/host/mesh/src/proxy.h @@ -6,22 +6,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ -#define ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ +#ifndef __PROXY_H__ +#define __PROXY_H__ -#define BT_MESH_PROXY_NET_PDU 0x00 -#define BT_MESH_PROXY_BEACON 0x01 -#define BT_MESH_PROXY_CONFIG 0x02 -#define BT_MESH_PROXY_PROV 0x03 +#if CONFIG_BT_MESH_DEBUG_USE_ID_ADDR +#define ADV_OPT_USE_IDENTITY BT_LE_ADV_OPT_USE_IDENTITY +#else +#define ADV_OPT_USE_IDENTITY 0 +#endif -#include "mesh/mesh.h" -#include "mesh/slist.h" +#if CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME +#define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME +#else +#define ADV_OPT_USE_NAME 0 +#endif -int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, - void (*end)(uint16_t, void *), void *user_data); +#define ADV_OPT_PROV \ +.conn_mode = (BLE_GAP_CONN_MODE_UND), \ +.disc_mode = (BLE_GAP_DISC_MODE_GEN), -int bt_mesh_proxy_prov_enable(void); -int bt_mesh_proxy_prov_disable(void); +#define ADV_OPT_PROXY \ +.conn_mode = (BLE_GAP_CONN_MODE_UND), \ +.disc_mode = (BLE_GAP_DISC_MODE_GEN), + +#define ADV_SLOW_INT \ +.itvl_min = BT_GAP_ADV_SLOW_INT_MIN, \ +.itvl_max = BT_GAP_ADV_SLOW_INT_MAX, + +#define ADV_FAST_INT \ +.itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, \ +.itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, int bt_mesh_proxy_gatt_enable(void); int bt_mesh_proxy_gatt_disable(void); @@ -29,8 +43,6 @@ void bt_mesh_proxy_gatt_disconnect(void); void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub); -struct os_mbuf *bt_mesh_proxy_get_buf(void); - int bt_mesh_proxy_adv_start(void); void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub); @@ -43,4 +55,4 @@ int bt_mesh_proxy_init(void); int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg); -#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_H_ */ +#endif /* __PROXY_H__ */ diff --git a/nimble/host/mesh/src/proxy_msg.h b/nimble/host/mesh/src/proxy_msg.h index 2a9f046c99..662fadb8f5 100644 --- a/nimble/host/mesh/src/proxy_msg.h +++ b/nimble/host/mesh/src/proxy_msg.h @@ -16,6 +16,11 @@ #define CFG_FILTER_REMOVE 0x02 #define CFG_FILTER_STATUS 0x03 +#define BT_MESH_PROXY_NET_PDU 0x00 +#define BT_MESH_PROXY_BEACON 0x01 +#define BT_MESH_PROXY_CONFIG 0x02 +#define BT_MESH_PROXY_PROV 0x03 + #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) typedef int (*proxy_send_cb_t)(uint16_t conn_handle, diff --git a/nimble/host/mesh/src/gatt_services.c b/nimble/host/mesh/src/proxy_srv.c similarity index 60% rename from nimble/host/mesh/src/gatt_services.c rename to nimble/host/mesh/src/proxy_srv.c index 40909b6964..de096d07a7 100644 --- a/nimble/host/mesh/src/gatt_services.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -24,82 +24,14 @@ #include "access.h" #include "proxy.h" #include "proxy_msg.h" +#include "pb_gatt_srv.h" + +#define BT_UUID_MESH_PROXY_VAL 0x1828 +#define CLIENT_BUF_SIZE 66 #define BT_UUID_16_ENCODE(w16) \ (((w16) >> 0) & 0xFF), \ (((w16) >> 8) & 0xFF) -/* Mesh Profile 1.0 Section 6.6: - * "The timeout for the SAR transfer is 20 seconds. When the timeout - * expires, the Proxy Server shall disconnect." - */ -#define PROXY_SAR_TIMEOUT K_SECONDS(20) - -#define CLIENT_BUF_SIZE 65 - - -/** @def BT_UUID_MESH_PROV - * @brief Mesh Provisioning Service - */ -ble_uuid16_t BT_UUID_MESH_PROV = BLE_UUID16_INIT(0x1827); -#define BT_UUID_MESH_PROV_VAL 0x1827 -/** @def BT_UUID_MESH_PROXY - * @brief Mesh Proxy Service - */ -ble_uuid16_t BT_UUID_MESH_PROXY = BLE_UUID16_INIT(0x1828); -#define BT_UUID_MESH_PROXY_VAL 0x1828 -/** @def BT_UUID_GATT_CCC - * @brief GATT Client Characteristic Configuration - */ -ble_uuid16_t BT_UUID_GATT_CCC = BLE_UUID16_INIT(0x2902); -#define BT_UUID_GATT_CCC_VAL 0x2902 -/** @def BT_UUID_MESH_PROV_DATA_IN - * @brief Mesh Provisioning Data In - */ -ble_uuid16_t BT_UUID_MESH_PROV_DATA_IN = BLE_UUID16_INIT(0x2adb); -#define BT_UUID_MESH_PROV_DATA_IN_VAL 0x2adb -/** @def BT_UUID_MESH_PROV_DATA_OUT - * @brief Mesh Provisioning Data Out - */ -ble_uuid16_t BT_UUID_MESH_PROV_DATA_OUT = BLE_UUID16_INIT(0x2adc); -#define BT_UUID_MESH_PROV_DATA_OUT_VAL 0x2adc -/** @def BT_UUID_MESH_PROXY_DATA_IN - * @brief Mesh Proxy Data In - */ -ble_uuid16_t BT_UUID_MESH_PROXY_DATA_IN = BLE_UUID16_INIT(0x2add); -#define BT_UUID_MESH_PROXY_DATA_IN_VAL 0x2add -/** @def BT_UUID_MESH_PROXY_DATA_OUT - * @brief Mesh Proxy Data Out - */ -ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); -#define BT_UUID_MESH_PROXY_DATA_OUT_VAL 0x2ade - -#if CONFIG_BT_MESH_DEBUG_USE_ID_ADDR -#define ADV_OPT_USE_IDENTITY BT_LE_ADV_OPT_USE_IDENTITY -#else -#define ADV_OPT_USE_IDENTITY 0 -#endif - -#if CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME -#define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME -#else -#define ADV_OPT_USE_NAME 0 -#endif - -#define ADV_OPT_PROV \ -.conn_mode = (BLE_GAP_CONN_MODE_UND), \ -.disc_mode = (BLE_GAP_DISC_MODE_GEN), - -#define ADV_OPT_PROXY \ -.conn_mode = (BLE_GAP_CONN_MODE_UND), \ -.disc_mode = (BLE_GAP_DISC_MODE_GEN), - -#define ADV_SLOW_INT \ -.itvl_min = BT_GAP_ADV_SLOW_INT_MIN, \ -.itvl_max = BT_GAP_ADV_SLOW_INT_MAX, - -#define ADV_FAST_INT \ -.itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, \ -.itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, static struct { uint16_t proxy_h; @@ -109,23 +41,14 @@ static struct { uint16_t prov_data_out_h; } svc_handles; -#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) static void proxy_send_beacons(struct ble_npl_event *work); static void proxy_filter_recv(uint16_t conn_handle, struct bt_mesh_net_rx *rx, struct os_mbuf *buf); -#endif /* CONFIG_BT_MESH_GATT_PROXY */ - -#if MYNEWT_VAL(BLE_MESH_PB_GATT) -static bool prov_fast_adv; -#endif /* CONFIG_BT_MESH_PB_GATT */ static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len, void (*end)(uint16_t, void *), void *user_data); -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - static bool prov_fast_adv; -#endif static struct bt_mesh_proxy_client { struct bt_mesh_proxy_role cli; @@ -136,28 +59,17 @@ static struct bt_mesh_proxy_client { REJECT, PROV, } filter_type; -#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) struct ble_npl_callout send_beacons; -#endif /* CONFIG_BT_MESH_GATT_PROXY */ } clients[CONFIG_BT_MAX_CONN] = { [0 ... (CONFIG_BT_MAX_CONN - 1)] = { .cli.cb = { .send = proxy_send, -#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) .recv = proxy_filter_recv, -#endif /* CONFIG_BT_MESH_GATT_PROXY */ }, }, }; -//static uint8_t __noinit client_buf_data[CLIENT_BUF_SIZE * CONFIG_BT_MAX_CONN]; - -/* Track which service is enabled */ -static enum { - MESH_GATT_NONE, - MESH_GATT_PROV, - MESH_GATT_PROXY, -} gatt_svc = MESH_GATT_NONE; +static bool service_registered; static int conn_count; @@ -174,37 +86,6 @@ static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) return NULL; } -#define ATTR_IS_PROV(attr) (attr->user_data != NULL) - -static ssize_t gatt_recv(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - struct bt_mesh_proxy_client *client = find_client(conn_handle); - const uint8_t *data = ctxt->om->om_data; - uint16_t len = ctxt->om->om_len; - - client = find_client(conn_handle); - - if (!client) { - return -ENOTCONN; - } - - if (len < 1) { - BT_WARN("Too small Proxy PDU"); - return -EINVAL; - } - - if ((attr_handle == svc_handles.prov_data_in_h) != - (PDU_TYPE(data) == BT_MESH_PROXY_PROV)) { - BT_WARN("Proxy PDU type doesn't match GATT service"); - return -EINVAL; - } - - return bt_mesh_proxy_msg_recv(&client->cli, data, len); -} - - -#if defined(CONFIG_BT_MESH_GATT_PROXY) /* Next subnet in queue to be advertised */ static struct bt_mesh_subnet *beacon_sub; @@ -720,11 +601,11 @@ int bt_mesh_proxy_gatt_enable(void) BT_DBG(""); - if (gatt_svc == MESH_GATT_PROXY) { - return -EALREADY; + if (bt_mesh_is_provisioned()) { + return -ENOTSUP; } - if (gatt_svc != MESH_GATT_NONE) { + if (service_registered) { return -EBUSY; } @@ -734,7 +615,7 @@ int bt_mesh_proxy_gatt_enable(void) /* FIXME: figure out end handle */ ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff); - gatt_svc = MESH_GATT_PROXY; + service_registered = true; for (i = 0; i < ARRAY_SIZE(clients); i++) { if (clients[i].cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) { @@ -771,14 +652,10 @@ int bt_mesh_proxy_gatt_disable(void) int rc; BT_DBG(""); - if (gatt_svc == MESH_GATT_NONE) { + if (!service_registered) { return -EALREADY; } - if (gatt_svc != MESH_GATT_PROXY) { - return -EBUSY; - } - bt_mesh_proxy_gatt_disconnect(); rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); @@ -786,7 +663,7 @@ int bt_mesh_proxy_gatt_disable(void) ble_gatts_svc_set_visibility(handle, 0); /* FIXME: figure out end handle */ ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff); - gatt_svc = MESH_GATT_NONE; + service_registered = false; return 0; } @@ -865,11 +742,6 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) continue; } - if (client->filter_type == PROV) { - BT_ERR("Invalid PDU type for Proxy Client"); - return -EINVAL; - } - /* Proxy PDU sending modifies the original buffer, * so we need to make a copy. */ @@ -915,12 +787,19 @@ static void proxy_sar_timeout(struct ble_npl_event *work) assert(rc == 0); } } -#endif /* CONFIG_BT_MESH_GATT_PROXY */ static void gatt_connected(uint16_t conn_handle) { struct bt_mesh_proxy_client *client; + struct ble_gap_conn_desc info; + struct ble_hs_conn *conn; + conn = ble_hs_conn_find(conn_handle); + bt_conn_get_info(conn, &info); + if (info.role != BLE_GAP_ROLE_SLAVE || + !service_registered) { + return; + } BT_DBG("conn %d", conn_handle); conn_count++; @@ -955,17 +834,6 @@ static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) return; } - if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && client->filter_type == PROV) { - bt_mesh_pb_gatt_close(conn_handle); - client->filter_type = NONE; - - if (bt_mesh_is_provisioned() && - IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) { - (void)bt_mesh_proxy_gatt_enable(); - } - } - /* If this fails, the work handler exits early, as * there's no active connection. */ @@ -975,231 +843,6 @@ static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) bt_mesh_adv_update(); } -struct os_mbuf *bt_mesh_proxy_get_buf(void) -{ - struct os_mbuf *buf = clients[0].cli.buf; - - if (buf != NULL) { - net_buf_simple_init(buf, 0); - } - - return buf; -} - -#if defined(CONFIG_BT_MESH_PB_GATT) -static void prov_ccc_write(uint16_t conn_handle) -{ - struct bt_mesh_proxy_client *client; - - BT_DBG("conn_handle %d", conn_handle); - - /* If a connection exists there must be a client */ - client = find_client(conn_handle); - __ASSERT(client, "No client for connection"); - - if (client->filter_type == NONE) { - client->filter_type = PROV; - bt_mesh_pb_gatt_open(conn_handle); - } -} - -static int -dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - /* - * We should never never enter this callback - it's attached to notify-only - * characteristic which are notified directly from mbuf. And we can't pass - * NULL as access_cb because gatts will assert on init... - */ - BLE_HS_DBG_ASSERT(0); - return 0; -} - -static const struct ble_gatt_svc_def svc_defs [] = { - { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), - .access_cb = gatt_recv, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - .access_cb = gatt_recv, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, { - 0, /* No more services. */ - }, -}; - -int bt_mesh_proxy_svcs_register(void) -{ - int rc; - - rc = ble_gatts_count_cfg(svc_defs); - assert(rc == 0); - - rc = ble_gatts_add_svcs(svc_defs); - assert(rc == 0); - - return 0; -} - -int bt_mesh_proxy_prov_enable(void) -{ - uint16_t handle; - int rc; - int i; - - BT_DBG(""); - - if (gatt_svc == MESH_GATT_PROV) { - return -EALREADY; - } - - if (gatt_svc != MESH_GATT_NONE) { - return -EBUSY; - } - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 1); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - - gatt_svc = MESH_GATT_PROV; - prov_fast_adv = true; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) { - clients[i].filter_type = PROV; - } - } - - - return 0; -} - -int bt_mesh_proxy_prov_disable(void) -{ - uint16_t handle; - int rc; - - BT_DBG(""); - - if (gatt_svc == MESH_GATT_NONE) { - return -EALREADY; - } - - if (gatt_svc != MESH_GATT_PROV) { - return -EBUSY; - } - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 0); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - - gatt_svc = MESH_GATT_NONE; - - bt_mesh_adv_update(); - - return 0; -} - -static uint8_t prov_svc_data[20] = { - BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL), -}; - -static const struct bt_data prov_ad[] = { - BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, - BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)), - BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), -}; - -int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, - void (*end)(uint16_t, void *), void *user_data) -{ - struct bt_mesh_proxy_client *client = find_client(conn_handle); - - if (!client) { - BT_ERR("No Proxy Client found"); - return -ENOTCONN; - } - - if (client->filter_type != PROV) { - BT_ERR("Invalid PDU type for Proxy Client"); - return -EINVAL; - } - - return bt_mesh_proxy_msg_send(&client->cli, BT_MESH_PROXY_PROV, buf, end, user_data); -} - -static size_t gatt_prov_adv_create(struct bt_data prov_sd[2]) -{ - const struct bt_mesh_prov *prov = bt_mesh_prov_get(); - const char *name = CONFIG_BT_DEVICE_NAME; - size_t name_len = strlen(name); - size_t prov_sd_len = 0; - size_t sd_space = 31; - - memcpy(prov_svc_data + 2, prov->uuid, 16); - sys_put_be16(prov->oob_info, prov_svc_data + 18); - - if (prov->uri) { - size_t uri_len = strlen(prov->uri); - - if (uri_len > 29) { - /* There's no way to shorten an URI */ - BT_WARN("Too long URI to fit advertising packet"); - } else { - prov_sd[0].type = BT_DATA_URI; - prov_sd[0].data_len = uri_len; - prov_sd[0].data = (const uint8_t *)prov->uri; - sd_space -= 2 + uri_len; - prov_sd_len++; - } - } - - if (sd_space > 2 && name_len > 0) { - sd_space -= 2; - - if (sd_space < name_len) { - prov_sd[prov_sd_len].type = BT_DATA_NAME_SHORTENED; - prov_sd[prov_sd_len].data_len = sd_space; - } else { - prov_sd[prov_sd_len].type = BT_DATA_NAME_COMPLETE; - prov_sd[prov_sd_len].data_len = name_len; - } - - prov_sd[prov_sd_len].data = (void *)name; - prov_sd_len++; - } - - return prov_sd_len; -} -#endif /* CONFIG_BT_MESH_PB_GATT */ - static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len, void (*end)(uint16_t, void *), void *user_data) @@ -1209,22 +852,10 @@ static int proxy_send(uint16_t conn_handle, BT_DBG("%u bytes: %s", len, bt_hex(data, len)); -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - if (gatt_svc == MESH_GATT_PROXY) { - om = ble_hs_mbuf_from_flat(data, len); - assert(om); - err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); - /* We do not pass cb into ble_gattc_notify_custom - execute it at the end */ - } -#endif - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - if (gatt_svc == MESH_GATT_PROV) { - om = ble_hs_mbuf_from_flat(data, len); - assert(om); - err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); - } -#endif + om = ble_hs_mbuf_from_flat(data, len); + assert(om); + err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); + /* We do not pass cb into ble_gattc_notify_custom - execute it at the end */ end(conn_handle, user_data); return err; @@ -1234,54 +865,11 @@ int bt_mesh_proxy_adv_start(void) { BT_DBG(""); - if (gatt_svc == MESH_GATT_NONE) { - return -ENOENT; + if (!service_registered || !bt_mesh_is_provisioned()) { + return -ENOTSUP; } -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - if (!bt_mesh_is_provisioned()) { - const struct ble_gap_adv_params *param; - struct ble_gap_adv_params fast_adv_param = { - ADV_OPT_PROV - ADV_FAST_INT - }; - struct ble_gap_adv_params slow_adv_param = { - ADV_OPT_PROV - ADV_SLOW_INT - }; - struct bt_data prov_sd[1]; - size_t prov_sd_len; - int err; - - prov_sd_len = gatt_prov_adv_create(prov_sd); - if (!prov_fast_adv) { - param = &slow_adv_param; - return bt_mesh_adv_start(param, - K_FOREVER, prov_ad, - ARRAY_SIZE(prov_ad), prov_sd, - prov_sd_len); - } else { - param = &fast_adv_param; - err = bt_mesh_adv_start(param, - (60 * MSEC_PER_SEC), prov_ad, - ARRAY_SIZE(prov_ad), prov_sd, - prov_sd_len); - if (!err) { - prov_fast_adv = false; - } - - return err; - } - } -#endif /* PB_GATT */ - -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - if (bt_mesh_is_provisioned()) { - return gatt_proxy_advertise(next_sub()); - } -#endif /* GATT_PROXY */ - - return -ENOTSUP; + return gatt_proxy_advertise(next_sub()); } @@ -1305,10 +893,17 @@ static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) } gatt_connected(event->adv_complete.conn_handle); +#if MYNEWT_VAL(BLE_MESH_PB_GATT) + gatt_connected_pb_gatt(event->adv_complete.conn_handle, + event->adv_complete.status); +#endif } #else if (event->type == BLE_GAP_EVENT_CONNECT) { gatt_connected(event->connect.conn_handle); +#if MYNEWT_VAL(BLE_MESH_PB_GATT) + gatt_connected_pb_gatt(event->connect.conn_handle, event->connect.status); +#endif } #endif } @@ -1321,6 +916,10 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) } else if (event->type == BLE_GAP_EVENT_DISCONNECT) { gatt_disconnected(event->disconnect.conn.conn_handle, event->disconnect.reason); +#if MYNEWT_VAL(BLE_MESH_PB_GATT) + gatt_disconnected_pb_gatt(event->disconnect.conn.conn_handle, + event->disconnect.reason); +#endif } else if (event->type == BLE_GAP_EVENT_SUBSCRIBE) { if (event->subscribe.attr_handle == svc_handles.proxy_data_out_h) { #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) @@ -1329,7 +928,7 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) } else if (event->subscribe.attr_handle == svc_handles.prov_data_out_h) { #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - prov_ccc_write(event->subscribe.conn_handle); + prov_ccc_write(event->subscribe.conn_handle, event->type); #endif } } @@ -1337,70 +936,31 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) return 0; } -static void resolve_svc_handles(void) -{ - int rc; - - /* Either all handles are already resolved, or none of them */ - if (svc_handles.prov_data_out_h) { - return; - } - - /* - * We assert if attribute is not found since at this stage all attributes - * shall be already registered and thus shall be found. - */ - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - &svc_handles.proxy_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - NULL, &svc_handles.proxy_data_out_h); - assert(rc == 0); - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - &svc_handles.prov_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - NULL, &svc_handles.prov_data_in_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - NULL, &svc_handles.prov_data_out_h); - assert(rc == 0); -} - - int bt_mesh_proxy_init(void) { - int i; + int i; - #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - if (!bt_mesh_subnet_cb_list[4]) { - bt_mesh_subnet_cb_list[4] = subnet_evt; - } - #endif +#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) + if (!bt_mesh_subnet_cb_list[4]) { + bt_mesh_subnet_cb_list[4] = subnet_evt; + } +#endif - for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) { - #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - k_work_init(&clients[i].send_beacons, proxy_send_beacons); - #endif - clients[i].cli.buf = NET_BUF_SIMPLE(CLIENT_BUF_SIZE); - clients[i].cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; + for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) { +#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) + k_work_init(&clients[i].send_beacons, proxy_send_beacons); +#endif + clients[i].cli.buf = NET_BUF_SIMPLE(CLIENT_BUF_SIZE); + clients[i].cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; - k_work_init_delayable(&clients[i].cli.sar_timer, proxy_sar_timeout); - k_work_add_arg_delayable(&clients[i].cli.sar_timer, &clients[i]); - } + k_work_init_delayable(&clients[i].cli.sar_timer, proxy_sar_timeout); + k_work_add_arg_delayable(&clients[i].cli.sar_timer, &clients[i]); + } - resolve_svc_handles(); + resolve_svc_handles(); - ble_gatts_svc_set_visibility(svc_handles.proxy_h, 0); - ble_gatts_svc_set_visibility(svc_handles.prov_h, 0); + ble_gatts_svc_set_visibility(svc_handles.proxy_h, 0); + ble_gatts_svc_set_visibility(svc_handles.prov_h, 0); return 0; } \ No newline at end of file diff --git a/nimble/host/mesh/src/settings.c b/nimble/host/mesh/src/settings.c index cc9fd630f5..cddf025f92 100644 --- a/nimble/host/mesh/src/settings.c +++ b/nimble/host/mesh/src/settings.c @@ -20,6 +20,7 @@ #include "transport.h" #include "heartbeat.h" #include "access.h" +#include "pb_gatt_srv.h" #include "proxy.h" #include "settings.h" #include "cfg.h" @@ -70,7 +71,7 @@ static int mesh_commit(void) } if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - (void)bt_mesh_proxy_prov_disable(); + (void)bt_mesh_pb_gatt_disable(); } bt_mesh_net_settings_commit(); diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index 9ca21a7f77..f0c3ffdc29 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -150,8 +150,8 @@ syscfg.defs: descryption: > This option specifies how many Proxy Filter entries the local node supports. - value: 1 - restrictions: BLE_MESH_GATT_SERVER + value: 3 + restrictions: BLE_MESH_GATT_PROXY BLE_MESH_ACCESS_LAYER_MSG: descryption: > From 6c5fd1cdbbe18d789f9ac174e2d9c1eaa396c4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 21 Oct 2021 13:08:20 +0200 Subject: [PATCH 221/306] host/mesh: Remove unnecessary prov buf get function Remove `bt_mesh_pb_gatt_get_buf`. This is port of a88aac2a7f107d89bd5727b01d21febfb20cc13f --- nimble/host/mesh/src/pb_gatt.c | 3 --- nimble/host/mesh/src/pb_gatt_srv.c | 10 ---------- nimble/host/mesh/src/pb_gatt_srv.h | 2 -- 3 files changed, 15 deletions(-) diff --git a/nimble/host/mesh/src/pb_gatt.c b/nimble/host/mesh/src/pb_gatt.c index 761ebb0a54..6a215e1d3a 100644 --- a/nimble/host/mesh/src/pb_gatt.c +++ b/nimble/host/mesh/src/pb_gatt.c @@ -35,7 +35,6 @@ struct prov_link { uint8_t seg; /* Bit-field of unreceived segments */ uint8_t last_seg; /* Last segment (to check length) */ uint8_t fcs; /* Expected FCS value */ - struct os_mbuf *buf; } rx; struct k_work_delayable prot_timer; }; @@ -48,8 +47,6 @@ static void reset_state(void) /* If this fails, the protocol timeout handler will exit early. */ (void)k_work_cancel_delayable(&link.prot_timer); - - link.rx.buf = bt_mesh_pb_gatt_get_buf(); } static void link_closed(enum prov_bearer_link_status status) diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index 7cb3257ccd..cf13cd9f23 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -181,16 +181,6 @@ int prov_ccc_write(uint16_t conn_handle, uint8_t type) } /* Mesh Provisioning Service Declaration */ -struct os_mbuf *bt_mesh_pb_gatt_get_buf(void) -{ - struct os_mbuf *buf = cli.buf; - - if (buf != NULL) { - net_buf_simple_init(buf, 0); - } - - return buf; -} static int dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, diff --git a/nimble/host/mesh/src/pb_gatt_srv.h b/nimble/host/mesh/src/pb_gatt_srv.h index 561f2225e9..364f53553e 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.h +++ b/nimble/host/mesh/src/pb_gatt_srv.h @@ -14,8 +14,6 @@ int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, int bt_mesh_pb_gatt_enable(void); int bt_mesh_pb_gatt_disable(void); -struct os_mbuf *bt_mesh_pb_gatt_get_buf(void); - int prov_ccc_write(uint16_t conn_handle, uint8_t type); void gatt_disconnected_pb_gatt(uint16_t conn_handle, uint8_t err); void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err); From 29d5a85f8bac49b951d796895dfe8b97a89e78ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 21 Oct 2021 13:17:29 +0200 Subject: [PATCH 222/306] host/mesh: Move command buffer to proxy_msg.c Move command buffer alloc to proxy_msg.c. This is port of d831d8a7d3637e330a0dc28c6787e242b75c4f0f --- nimble/host/mesh/src/mesh.c | 4 ---- nimble/host/mesh/src/pb_gatt_srv.c | 4 ---- nimble/host/mesh/src/proxy.h | 2 -- nimble/host/mesh/src/proxy_msg.c | 38 ++++++++++++++++++++++++++++++ nimble/host/mesh/src/proxy_srv.c | 5 ++-- 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index 1ac4d02641..ccdfed37fd 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -316,10 +316,6 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, return err; } -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - bt_mesh_proxy_init(); -#endif - #if (MYNEWT_VAL(BLE_MESH_PROV)) err = bt_mesh_prov_init(prov); if (err) { diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index cf13cd9f23..64b59c5ed8 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -24,8 +24,6 @@ #include "../../host/src/ble_hs_priv.h" #if MYNEWT_VAL(BLE_MESH_PB_GATT) -#define CLIENT_BUF_SIZE 66 - /** @def BT_UUID_MESH_PROV * @brief Mesh Provisioning Service */ @@ -124,8 +122,6 @@ void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err) cli.conn_handle = conn_handle; BT_DBG("conn %p err 0x%02x", (void *)conn, err); - - net_buf_simple_reset(cli.buf); } void gatt_disconnected_pb_gatt(uint16_t conn_handle, uint8_t reason) diff --git a/nimble/host/mesh/src/proxy.h b/nimble/host/mesh/src/proxy.h index 196f540b2e..a92afaada4 100644 --- a/nimble/host/mesh/src/proxy.h +++ b/nimble/host/mesh/src/proxy.h @@ -51,8 +51,6 @@ void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub); bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst); void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr); -int bt_mesh_proxy_init(void); - int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg); #endif /* __PROXY_H__ */ diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c index 4c4d694029..5459815b47 100644 --- a/nimble/host/mesh/src/proxy_msg.c +++ b/nimble/host/mesh/src/proxy_msg.c @@ -46,6 +46,17 @@ #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) +#define PB_GATT_BUF_LEN_MAX 66 +#define PROXY_BUF_LEN_MAX 30 + +#if defined(CONFIG_BT_MESH_PB_GATT) +#define PROXY_MSG_FIRST_BUF_LEN PB_GATT_BUF_LEN_MAX +#else +#define PROXY_MSG_FIRST_BUF_LEN PROXY_BUF_LEN_MAX +#endif + +static uint8_t bufs[PROXY_MSG_FIRST_BUF_LEN + + ((CONFIG_BT_MAX_CONN - 1) * PROXY_BUF_LEN_MAX)]; #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) static void proxy_cfg(struct bt_mesh_proxy_role *role) @@ -228,4 +239,31 @@ int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, return 0; } +void bt_mesh_proxy_msg_init(struct bt_mesh_proxy_role *role) +{ + uint8_t i, len; + uint8_t *buf; + + /* Check if buf has been allocated, in this way, we no longer need + * to repeat the operation. + */ + if (role->buf->om_data) { + net_buf_simple_reset(role->buf); + return; + } + + i = role->conn_handle; + if (!i) { + len = PROXY_MSG_FIRST_BUF_LEN; + buf = bufs; + } else { + len = PROXY_BUF_LEN_MAX; + buf = &bufs[PROXY_MSG_FIRST_BUF_LEN + (PROXY_BUF_LEN_MAX * (i - 1))]; + } + + net_buf_simple_init_with_data(role->buf, buf, len); + + net_buf_simple_reset(role->buf); +} + #endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index de096d07a7..28e61959ec 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -818,7 +818,8 @@ static void gatt_connected(uint16_t conn_handle) client->cli.conn_handle = conn_handle; client->filter_type = NONE; (void)memset(client->filter, 0, sizeof(client->filter)); - net_buf_simple_init(client->cli.buf, 0); + + bt_mesh_proxy_msg_init(&client->cli); } static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) @@ -950,8 +951,6 @@ int bt_mesh_proxy_init(void) #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) k_work_init(&clients[i].send_beacons, proxy_send_beacons); #endif - clients[i].cli.buf = NET_BUF_SIMPLE(CLIENT_BUF_SIZE); - clients[i].cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; k_work_init_delayable(&clients[i].cli.sar_timer, proxy_sar_timeout); k_work_add_arg_delayable(&clients[i].cli.sar_timer, &clients[i]); From 6048746f830bdd3b2dbafbe2cc1d36421b07b051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 21 Oct 2021 13:49:44 +0200 Subject: [PATCH 223/306] host/mesh: Move proxy complete message to seperate role Move proxy complete message to seperate role. This is port of bc1d6580dc00bb09a8460f55460cf6c0bddb519d --- nimble/host/mesh/src/pb_gatt_srv.c | 19 +++++++- nimble/host/mesh/src/proxy_msg.c | 75 ++---------------------------- nimble/host/mesh/src/proxy_msg.h | 5 +- nimble/host/mesh/src/proxy_srv.c | 60 ++++++++++++++++++++++-- 4 files changed, 82 insertions(+), 77 deletions(-) diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index 64b59c5ed8..cbdd247a46 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -73,14 +73,31 @@ static struct { uint16_t prov_data_out_h; } svc_handles; +static void proxy_complete_pdu(struct bt_mesh_proxy_role *role); static int gatt_send(uint16_t conn_handle, const void *data, uint16_t len, void (*end)(uint16_t, void *), void *user_data); static struct bt_mesh_proxy_role cli = { - .cb.send = gatt_send, + .cb = { + .send = gatt_send, + .recv = proxy_complete_pdu, + }, }; +static void proxy_complete_pdu(struct bt_mesh_proxy_role *role) +{ + switch (role->msg_type) { + case BT_MESH_PROXY_PROV: + BT_DBG("Mesh Provisioning PDU"); + bt_mesh_pb_gatt_recv(role->conn_handle, role->buf); + break; + default: + BT_WARN("Unhandled Message Type 0x%02x", role->msg_type); + break; + } +} + static bool service_registered; static ssize_t gatt_recv(uint16_t conn_handle, uint16_t attr_handle, diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c index 5459815b47..e8770e2010 100644 --- a/nimble/host/mesh/src/proxy_msg.c +++ b/nimble/host/mesh/src/proxy_msg.c @@ -58,75 +58,6 @@ static uint8_t bufs[PROXY_MSG_FIRST_BUF_LEN + ((CONFIG_BT_MAX_CONN - 1) * PROXY_BUF_LEN_MAX)]; -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) -static void proxy_cfg(struct bt_mesh_proxy_role *role) -{ - struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_NET_MAX_PDU_LEN); - struct bt_mesh_net_rx rx; - int err; - - err = bt_mesh_net_decode(role->buf, BT_MESH_NET_IF_PROXY_CFG, - &rx, buf); - if (err) { - BT_ERR("Failed to decode Proxy Configuration (err %d)", err); - goto done; - } - - rx.local_match = 1U; - - if (bt_mesh_rpl_check(&rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", - rx.ctx.addr, rx.ctx.recv_dst, rx.seq); - goto done; - } - - /* Remove network headers */ - net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN); - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_len < 1) { - BT_WARN("Too short proxy configuration PDU"); - goto done; - } - - role->cb.recv(role->conn_handle, &rx, buf); -done: - os_mbuf_free_chain(buf); -} -#endif /* GATT_PROXY */ - -static void proxy_complete_pdu(struct bt_mesh_proxy_role *role) -{ - switch (role->msg_type) { -#if defined(CONFIG_BT_MESH_PROXY) - case BT_MESH_PROXY_NET_PDU: - BT_INFO("Mesh Network PDU"); - bt_mesh_net_recv(role->buf, 0, BT_MESH_NET_IF_PROXY); - break; - case BT_MESH_PROXY_BEACON: - BT_INFO("Mesh Beacon PDU"); - bt_mesh_beacon_recv(role->buf); - break; - case BT_MESH_PROXY_CONFIG: - BT_INFO("Mesh Configuration PDU"); - proxy_cfg(role); - break; -#endif -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - case BT_MESH_PROXY_PROV: - BT_INFO("Mesh Provisioning PDU"); - bt_mesh_pb_gatt_recv(role->conn_handle, role->buf); - break; -#endif - default: - BT_WARN("Unhandled Message Type 0x%02x", role->msg_type); - break; - } - - net_buf_simple_init(role->buf, 0); -} - ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, const void *buf, uint16_t len) { @@ -141,7 +72,8 @@ ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, role->msg_type = PDU_TYPE(data); net_buf_simple_add_mem(role->buf, data + 1, len - 1); - proxy_complete_pdu(role); + role->cb.recv(role); + net_buf_simple_reset(role->buf); break; case SAR_FIRST: @@ -186,7 +118,8 @@ ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, */ (void)k_work_cancel_delayable(&role->sar_timer); net_buf_simple_add_mem(role->buf, data + 1, len - 1); - proxy_complete_pdu(role); + role->cb.recv(role); + net_buf_simple_reset(role->buf); break; } diff --git a/nimble/host/mesh/src/proxy_msg.h b/nimble/host/mesh/src/proxy_msg.h index 662fadb8f5..fd8736e44f 100644 --- a/nimble/host/mesh/src/proxy_msg.h +++ b/nimble/host/mesh/src/proxy_msg.h @@ -23,12 +23,13 @@ #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) +struct bt_mesh_proxy_role; + typedef int (*proxy_send_cb_t)(uint16_t conn_handle, const void *data, uint16_t len, void (*end)(uint16_t, void *), void *user_data); -typedef void (*proxy_recv_cb_t)(uint16_t conn_handle, - struct bt_mesh_net_rx *rx, struct os_mbuf *buf); +typedef void (*proxy_recv_cb_t)(struct bt_mesh_proxy_role *role); struct bt_mesh_proxy_role { uint16_t conn_handle; diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index 28e61959ec..1234757977 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -42,8 +42,7 @@ static struct { } svc_handles; static void proxy_send_beacons(struct ble_npl_event *work); -static void proxy_filter_recv(uint16_t conn_handle, - struct bt_mesh_net_rx *rx, struct os_mbuf *buf); +static void proxy_complete_pdu(struct bt_mesh_proxy_role *role); static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len, @@ -64,7 +63,7 @@ static struct bt_mesh_proxy_client { [0 ... (CONFIG_BT_MAX_CONN - 1)] = { .cli.cb = { .send = proxy_send, - .recv = proxy_filter_recv, + .recv = proxy_complete_pdu, }, }, }; @@ -250,6 +249,61 @@ static void proxy_filter_recv(uint16_t conn_handle, } } +static void proxy_cfg(struct bt_mesh_proxy_role *role) +{ + struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_NET_MAX_PDU_LEN); + struct bt_mesh_net_rx rx; + int err; + + err = bt_mesh_net_decode(role->buf, BT_MESH_NET_IF_PROXY_CFG, + &rx, buf); + if (err) { + BT_ERR("Failed to decode Proxy Configuration (err %d)", err); + return; + } + + rx.local_match = 1U; + + if (bt_mesh_rpl_check(&rx, NULL)) { + BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + rx.ctx.addr, rx.ctx.recv_dst, rx.seq); + return; + } + + /* Remove network headers */ + net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN); + + BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); + + if (buf->om_len < 1) { + BT_WARN("Too short proxy configuration PDU"); + return; + } + + proxy_filter_recv(role->conn_handle, &rx, buf); + } + + static void proxy_complete_pdu(struct bt_mesh_proxy_role *role) + { + switch (role->msg_type) { + case BT_MESH_PROXY_NET_PDU: + BT_DBG("Mesh Network PDU"); + bt_mesh_net_recv(role->buf, 0, BT_MESH_NET_IF_PROXY); + break; + case BT_MESH_PROXY_BEACON: + BT_DBG("Mesh Beacon PDU"); + bt_mesh_beacon_recv(role->buf); + break; + case BT_MESH_PROXY_CONFIG: + BT_DBG("Mesh Configuration PDU"); + proxy_cfg(role); + break; + default: + BT_WARN("Unhandled Message Type 0x%02x", role->msg_type); + break; + } +} + static int beacon_send(struct bt_mesh_proxy_client *client, struct bt_mesh_subnet *sub) { struct os_mbuf *buf = NET_BUF_SIMPLE(23); From a162826831c950a13484f3624ae417858c8a7066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 21 Oct 2021 15:00:26 +0200 Subject: [PATCH 224/306] host/mesh: Move bt_mesh_proxy_role to proxy_msg.c Mesh bt_mesh_proxy_role structure to proxy_msg.c This is port of 22b234cf03f1139a431b0b1c9a820fe8c9d75e82 --- nimble/host/mesh/src/pb_gatt_srv.c | 42 +++++------- nimble/host/mesh/src/proxy_msg.c | 39 ++++++++++- nimble/host/mesh/src/proxy_msg.h | 18 ++++- nimble/host/mesh/src/proxy_srv.c | 104 +++++++++-------------------- 4 files changed, 104 insertions(+), 99 deletions(-) diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index cbdd247a46..a6a9c0616c 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -73,19 +73,13 @@ static struct { uint16_t prov_data_out_h; } svc_handles; -static void proxy_complete_pdu(struct bt_mesh_proxy_role *role); static int gatt_send(uint16_t conn_handle, const void *data, uint16_t len, void (*end)(uint16_t, void *), void *user_data); -static struct bt_mesh_proxy_role cli = { - .cb = { - .send = gatt_send, - .recv = proxy_complete_pdu, - }, -}; +static struct bt_mesh_proxy_role *cli; -static void proxy_complete_pdu(struct bt_mesh_proxy_role *role) +static void proxy_msg_recv(struct bt_mesh_proxy_role *role) { switch (role->msg_type) { case BT_MESH_PROXY_PROV: @@ -105,9 +99,10 @@ static ssize_t gatt_recv(uint16_t conn_handle, uint16_t attr_handle, { const uint8_t *data = ctxt->om->om_data; uint16_t len = ctxt->om->om_len; + struct bt_mesh_proxy_client *client = find_client(conn_handle); - if (conn_handle != cli.conn_handle) { + if (conn_handle != cli->conn_handle) { return -ENOTCONN; } @@ -121,7 +116,7 @@ static ssize_t gatt_recv(uint16_t conn_handle, uint16_t attr_handle, return -EINVAL; } - return bt_mesh_proxy_msg_recv(&cli, data, len); + return bt_mesh_proxy_msg_recv(client->cli, data, len); } void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err) @@ -136,7 +131,7 @@ void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err) return; } - cli.conn_handle = conn_handle; + cli = bt_mesh_proxy_role_setup(conn_handle, gatt_send, proxy_msg_recv); BT_DBG("conn %p err 0x%02x", (void *)conn, err); } @@ -154,31 +149,26 @@ void gatt_disconnected_pb_gatt(uint16_t conn_handle, uint8_t reason) return; } - if (cli.conn_handle != conn_handle) { - BT_WARN("No PB-GATT Client found"); - return; - } + cli = NULL; BT_DBG("conn %p reason 0x%02x", (void *)conn, reason); bt_mesh_pb_gatt_close(conn_handle); - if (bt_mesh_is_provisioned()) { - (void)bt_mesh_pb_gatt_disable(); - - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - (void)bt_mesh_proxy_gatt_enable(); - } + if (!bt_mesh_is_provisioned()) { + return; } - cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; + (void)bt_mesh_pb_gatt_disable(); - bt_mesh_adv_update(); + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + (void)bt_mesh_proxy_gatt_enable(); + } } int prov_ccc_write(uint16_t conn_handle, uint8_t type) { - if (cli.conn_handle != conn_handle) { + if (cli->conn_handle != conn_handle) { BT_ERR("No PB-GATT Client found"); return -ENOTCONN; } @@ -357,12 +347,12 @@ static const struct bt_data prov_ad[] = { int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, void (*end)(uint16_t, void *), void *user_data) { - if (cli.conn_handle != conn_handle) { + if (!cli || cli->conn_handle != conn_handle) { BT_ERR("No PB-GATT Client found"); return -ENOTCONN; } - return bt_mesh_proxy_msg_send(&cli, BT_MESH_PROXY_PROV, buf, end, user_data); + return bt_mesh_proxy_msg_send(cli, BT_MESH_PROXY_PROV, buf, end, user_data); } static size_t gatt_prov_adv_create(struct bt_data prov_sd[1]) diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c index e8770e2010..09064d3728 100644 --- a/nimble/host/mesh/src/proxy_msg.c +++ b/nimble/host/mesh/src/proxy_msg.c @@ -58,6 +58,8 @@ static uint8_t bufs[PROXY_MSG_FIRST_BUF_LEN + ((CONFIG_BT_MAX_CONN - 1) * PROXY_BUF_LEN_MAX)]; +static struct bt_mesh_proxy_role roles[CONFIG_BT_MAX_CONN]; + ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, const void *buf, uint16_t len) { @@ -172,7 +174,7 @@ int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, return 0; } -void bt_mesh_proxy_msg_init(struct bt_mesh_proxy_role *role) +static void proxy_msg_init(struct bt_mesh_proxy_role *role) { uint8_t i, len; uint8_t *buf; @@ -199,4 +201,39 @@ void bt_mesh_proxy_msg_init(struct bt_mesh_proxy_role *role) net_buf_simple_reset(role->buf); } +struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(uint16_t conn_handle, + proxy_send_cb_t send, + proxy_recv_cb_t recv) +{ + struct bt_mesh_proxy_role *role; + + role = &roles[conn_handle]; + + role->conn_handle = conn_handle; + proxy_msg_init(role); + + role->cb.recv = recv; + role->cb.send = send; + + return role; +} + +void gatt_disconnected_proxy_msg(uint16_t conn_handle, uint8_t reason) +{ + struct bt_mesh_proxy_role *role; + + BT_DBG("conn_handle %d reason 0x%02x", conn_handle, reason); + + role = &roles[conn_handle]; + + /* If this fails, the work handler exits early, as + * there's no active connection. + */ + (void)k_work_cancel_delayable(&role->sar_timer); + + role->conn_handle = BLE_HS_CONN_HANDLE_NONE; + + bt_mesh_adv_update(); +} + #endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ diff --git a/nimble/host/mesh/src/proxy_msg.h b/nimble/host/mesh/src/proxy_msg.h index fd8736e44f..54940b25cc 100644 --- a/nimble/host/mesh/src/proxy_msg.h +++ b/nimble/host/mesh/src/proxy_msg.h @@ -44,10 +44,26 @@ struct bt_mesh_proxy_role { struct os_mbuf *buf; }; +struct bt_mesh_proxy_client { + struct bt_mesh_proxy_role *cli; + uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)]; + enum __packed { + NONE, + ACCEPT, + REJECT, + PROV, + } filter_type; + struct ble_npl_callout send_beacons; +}; + ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, const void *buf, uint16_t len); int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, struct os_mbuf *msg, void (*end)(uint16_t, void *), void *user_data); void bt_mesh_proxy_msg_init(struct bt_mesh_proxy_role *role); - +void gatt_disconnected_proxy_msg(uint16_t conn_handle, uint8_t reason); +struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(uint16_t conn_handle, + proxy_send_cb_t send, + proxy_recv_cb_t recv); +struct bt_mesh_proxy_client *find_client(uint16_t conn_handle); #endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_MSG_H_ */ diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index 1234757977..62b6cc3856 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -42,47 +42,21 @@ static struct { } svc_handles; static void proxy_send_beacons(struct ble_npl_event *work); -static void proxy_complete_pdu(struct bt_mesh_proxy_role *role); static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len, void (*end)(uint16_t, void *), void *user_data); -static struct bt_mesh_proxy_client { - struct bt_mesh_proxy_role cli; - uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)]; - enum __packed { - NONE, - ACCEPT, - REJECT, - PROV, - } filter_type; - struct ble_npl_callout send_beacons; -} clients[CONFIG_BT_MAX_CONN] = { - [0 ... (CONFIG_BT_MAX_CONN - 1)] = { - .cli.cb = { - .send = proxy_send, - .recv = proxy_complete_pdu, - }, - }, -}; +static struct bt_mesh_proxy_client clients[CONFIG_BT_MAX_CONN]; static bool service_registered; static int conn_count; -static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) +struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) { - int i; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].cli.conn_handle == conn_handle) { - return &clients[i]; - } - } - - return NULL; + return &clients[conn_handle]; } /* Next subnet in queue to be advertised */ @@ -201,7 +175,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, return; } - err = bt_mesh_proxy_msg_send(&client->cli, BT_MESH_PROXY_CONFIG, + err = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_CONFIG, buf, NULL, NULL); if (err) { BT_ERR("Failed to send proxy cfg message (err %d)", err); @@ -215,9 +189,6 @@ static void proxy_filter_recv(uint16_t conn_handle, uint8_t opcode; client = find_client(conn_handle); - if (!client) { - return; - } opcode = net_buf_simple_pull_u8(buf); switch (opcode) { @@ -283,8 +254,8 @@ static void proxy_cfg(struct bt_mesh_proxy_role *role) proxy_filter_recv(role->conn_handle, &rx, buf); } - static void proxy_complete_pdu(struct bt_mesh_proxy_role *role) - { +static void proxy_msg_recv(struct bt_mesh_proxy_role *role) +{ switch (role->msg_type) { case BT_MESH_PROXY_NET_PDU: BT_DBG("Mesh Network PDU"); @@ -312,7 +283,7 @@ static int beacon_send(struct bt_mesh_proxy_client *client, struct bt_mesh_subne net_buf_simple_init(buf, 1); bt_mesh_beacon_create(sub, buf); - rc = bt_mesh_proxy_msg_send(&client->cli, BT_MESH_PROXY_BEACON, buf, + rc = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_BEACON, buf, NULL, NULL); os_mbuf_free_chain(buf); return rc; @@ -345,7 +316,7 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub) } for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].cli.conn_handle) { + if (clients[i].cli) { beacon_send(&clients[i], sub); } } @@ -638,7 +609,6 @@ static void proxy_ccc_write(uint16_t conn_handle) BT_DBG("conn_handle %d", conn_handle); client = find_client(conn_handle); - __ASSERT(client, "No client for connection"); if (client->filter_type == NONE) { client->filter_type = ACCEPT; @@ -672,7 +642,7 @@ int bt_mesh_proxy_gatt_enable(void) service_registered = true; for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) { + if (clients[i].cli->conn_handle != BLE_HS_CONN_HANDLE_NONE) { clients[i].filter_type = ACCEPT; } } @@ -689,11 +659,11 @@ void bt_mesh_proxy_gatt_disconnect(void) for (i = 0; i < ARRAY_SIZE(clients); i++) { struct bt_mesh_proxy_client *client = &clients[i]; - if ((client->cli.conn_handle != BLE_HS_CONN_HANDLE_NONE) && + if ((client->cli->conn_handle != BLE_HS_CONN_HANDLE_NONE) && (client->filter_type == ACCEPT || client->filter_type == REJECT)) { client->filter_type = NONE; - rc = ble_gap_terminate(client->cli.conn_handle, + rc = ble_gap_terminate(client->cli->conn_handle, BLE_ERR_REM_USER_CONN_TERM); assert(rc == 0); } @@ -724,8 +694,11 @@ int bt_mesh_proxy_gatt_disable(void) void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr) { - struct bt_mesh_proxy_client *client = - CONTAINER_OF(buf, struct bt_mesh_proxy_client, cli.buf); + struct bt_mesh_proxy_client *client; + struct bt_mesh_proxy_role *cli = + CONTAINER_OF(buf, struct bt_mesh_proxy_role, buf); + + client = find_client(cli->conn_handle); BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); @@ -788,7 +761,7 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) struct bt_mesh_proxy_client *client = &clients[i]; struct os_mbuf *msg; - if (client->cli.conn_handle == BLE_HS_CONN_HANDLE_NONE) { + if (client->cli->conn_handle == BLE_HS_CONN_HANDLE_NONE) { continue; } @@ -803,7 +776,7 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) net_buf_simple_init(msg, 1); net_buf_simple_add_mem(msg, buf->om_data, buf->om_len); - err = bt_mesh_proxy_msg_send(&client->cli, BT_MESH_PROXY_NET_PDU, + err = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_NET_PDU, msg, buf_send_end, net_buf_ref(buf)); adv_send_start(0, err, cb, cb_data); @@ -858,22 +831,18 @@ static void gatt_connected(uint16_t conn_handle) conn_count++; - /* Try to re-enable advertising in case it's possible */ - if (conn_count < CONFIG_BT_MAX_CONN) { - bt_mesh_adv_update(); - } - - client = find_client(BLE_HS_CONN_HANDLE_NONE); - if (!client) { - BT_ERR("No free Proxy Client objects"); - return; - } + client = find_client(conn_handle); - client->cli.conn_handle = conn_handle; client->filter_type = NONE; (void)memset(client->filter, 0, sizeof(client->filter)); - bt_mesh_proxy_msg_init(&client->cli); + client->cli = bt_mesh_proxy_role_setup(conn_handle, proxy_send, + proxy_msg_recv); + + /* Try to re-enable advertising in case it's possible */ + if (conn_count < CONFIG_BT_MAX_CONN) { + bt_mesh_adv_update(); + } } static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) @@ -884,18 +853,7 @@ static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) conn_count--; client = find_client(conn_handle); - if (!client) { - BT_WARN("No Gatt Client found"); - return; - } - - /* If this fails, the work handler exits early, as - * there's no active connection. - */ - (void)k_work_cancel_delayable(&client->cli.sar_timer); - client->cli.conn_handle = BLE_HS_CONN_HANDLE_NONE; - - bt_mesh_adv_update(); + client->cli = NULL; } static int proxy_send(uint16_t conn_handle, @@ -974,6 +932,10 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) #if MYNEWT_VAL(BLE_MESH_PB_GATT) gatt_disconnected_pb_gatt(event->disconnect.conn.conn_handle, event->disconnect.reason); +#endif +#if MYNEWT_VAL(BLE_MESH_PROXY) + gatt_disconnected_proxy_msg(event->disconnect.conn.conn_handle, + event->disconnect.reason); #endif } else if (event->type == BLE_GAP_EVENT_SUBSCRIBE) { if (event->subscribe.attr_handle == svc_handles.proxy_data_out_h) { @@ -1006,8 +968,8 @@ int bt_mesh_proxy_init(void) k_work_init(&clients[i].send_beacons, proxy_send_beacons); #endif - k_work_init_delayable(&clients[i].cli.sar_timer, proxy_sar_timeout); - k_work_add_arg_delayable(&clients[i].cli.sar_timer, &clients[i]); + k_work_init_delayable(&clients[i].cli->sar_timer, proxy_sar_timeout); + k_work_add_arg_delayable(&clients[i].cli->sar_timer, &clients[i]); } resolve_svc_handles(); From 66e6dfdfed0b5e6ce842f5fb29fa16f142b098e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 21 Oct 2021 15:09:25 +0200 Subject: [PATCH 225/306] host/mesh: Reflect disconnect logic to separate roles remove section ordering to use code more readable. This is port of 3f68692069be9253796822a98dd328d76925a234 --- nimble/host/mesh/src/pb_gatt_srv.c | 10 ++-------- nimble/host/mesh/src/proxy_srv.c | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index a6a9c0616c..cb68bda374 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -155,14 +155,8 @@ void gatt_disconnected_pb_gatt(uint16_t conn_handle, uint8_t reason) bt_mesh_pb_gatt_close(conn_handle); - if (!bt_mesh_is_provisioned()) { - return; - } - - (void)bt_mesh_pb_gatt_disable(); - - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - (void)bt_mesh_proxy_gatt_enable(); + if (bt_mesh_is_provisioned()) { + (void)bt_mesh_pb_gatt_disable(); } } diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index 62b6cc3856..5fb7a9b04d 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -847,11 +847,22 @@ static void gatt_connected(uint16_t conn_handle) static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) { - BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason); + struct ble_gap_conn_desc info; struct bt_mesh_proxy_client *client; + struct ble_hs_conn *conn; - conn_count--; + conn = ble_hs_conn_find(conn_handle); + bt_conn_get_info(conn, &info); + if (info.role != BLE_GAP_ROLE_SLAVE) { + return; + } + if (!service_registered && bt_mesh_is_provisioned()) { + (void)bt_mesh_proxy_gatt_enable(); + return; + } + + conn_count--; client = find_client(conn_handle); client->cli = NULL; } From ff2abc057d121824467dd15883acf2ecdebfa738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 21 Oct 2021 15:34:48 +0200 Subject: [PATCH 226/306] host/mesh: Add seperate config for pb-gatt dev name Add seperate config to control whether device name include in pb-gatt advertising scan response data. This is port of 355b18c43e8962190515e61efd770921ed3a7074 --- nimble/host/mesh/src/pb_gatt_srv.c | 23 ++++++++++++++++++++++- nimble/host/mesh/src/proxy.h | 14 -------------- nimble/host/mesh/src/proxy_msg.h | 1 - nimble/host/mesh/src/proxy_srv.c | 15 +++++++++++++-- nimble/host/mesh/syscfg.yml | 6 ++++++ 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index cb68bda374..55900e188e 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -23,6 +23,16 @@ #include "services/gatt/ble_svc_gatt.h" #include "../../host/src/ble_hs_priv.h" +#if defined(CONFIG_BT_MESH_PB_GATT_USE_DEVICE_NAME) +#define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME +#else +#define ADV_OPT_USE_NAME 0 +#endif + +#define ADV_OPT_PROV \ +.conn_mode = (BLE_GAP_CONN_MODE_UND), \ +.disc_mode = (BLE_GAP_DISC_MODE_GEN), + #if MYNEWT_VAL(BLE_MESH_PB_GATT) /** @def BT_UUID_MESH_PROV * @brief Mesh Provisioning Service @@ -405,7 +415,18 @@ int bt_mesh_pb_gatt_adv_start(void) ADV_OPT_PROV ADV_FAST_INT }; - struct bt_data prov_sd[1]; +#if ADV_OPT_USE_NAME + const char *name = CONFIG_BT_DEVICE_NAME; + size_t name_len = strlen(name); + struct bt_data prov_sd = { + .type = BT_DATA_NAME_COMPLETE, + .data_len = name_len, + .data = (void *)name + }; +#else + struct bt_data *prov_sd = NULL; +#endif + size_t prov_sd_len; int err; diff --git a/nimble/host/mesh/src/proxy.h b/nimble/host/mesh/src/proxy.h index a92afaada4..f84fa424f6 100644 --- a/nimble/host/mesh/src/proxy.h +++ b/nimble/host/mesh/src/proxy.h @@ -15,20 +15,6 @@ #define ADV_OPT_USE_IDENTITY 0 #endif -#if CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME -#define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME -#else -#define ADV_OPT_USE_NAME 0 -#endif - -#define ADV_OPT_PROV \ -.conn_mode = (BLE_GAP_CONN_MODE_UND), \ -.disc_mode = (BLE_GAP_DISC_MODE_GEN), - -#define ADV_OPT_PROXY \ -.conn_mode = (BLE_GAP_CONN_MODE_UND), \ -.disc_mode = (BLE_GAP_DISC_MODE_GEN), - #define ADV_SLOW_INT \ .itvl_min = BT_GAP_ADV_SLOW_INT_MIN, \ .itvl_max = BT_GAP_ADV_SLOW_INT_MAX, diff --git a/nimble/host/mesh/src/proxy_msg.h b/nimble/host/mesh/src/proxy_msg.h index 54940b25cc..38e9ebc110 100644 --- a/nimble/host/mesh/src/proxy_msg.h +++ b/nimble/host/mesh/src/proxy_msg.h @@ -51,7 +51,6 @@ struct bt_mesh_proxy_client { NONE, ACCEPT, REJECT, - PROV, } filter_type; struct ble_npl_callout send_beacons; }; diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index 5fb7a9b04d..b60cf3d64b 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -26,6 +26,17 @@ #include "proxy_msg.h" #include "pb_gatt_srv.h" +#if defined(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME) +#define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME +#else +#define ADV_OPT_USE_NAME 0 +#endif + +#define ADV_OPT_PROXY \ +.conn_mode = (BLE_GAP_CONN_MODE_UND), \ +.disc_mode = (BLE_GAP_DISC_MODE_GEN), + + #define BT_UUID_MESH_PROXY_VAL 0x1828 #define CLIENT_BUF_SIZE 66 @@ -642,7 +653,7 @@ int bt_mesh_proxy_gatt_enable(void) service_registered = true; for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].cli->conn_handle != BLE_HS_CONN_HANDLE_NONE) { + if (clients[i].cli) { clients[i].filter_type = ACCEPT; } } @@ -659,7 +670,7 @@ void bt_mesh_proxy_gatt_disconnect(void) for (i = 0; i < ARRAY_SIZE(clients); i++) { struct bt_mesh_proxy_client *client = &clients[i]; - if ((client->cli->conn_handle != BLE_HS_CONN_HANDLE_NONE) && + if ((client->cli) && (client->filter_type == ACCEPT || client->filter_type == REJECT)) { client->filter_type = NONE; diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index f0c3ffdc29..1ada38806d 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -115,6 +115,12 @@ syscfg.defs: restrictions: - '(BLE_MESH_GATT_SERVER && BLE_MESH_PROV)' + BLE_MESH_PB_GATT_USE_DEVICE_NAME: + description: > + This option includes GAP device name in scan response when + the PB-GATT is enabled. + value: 1 + BLE_MESH_GATT_PROXY: description: > This option enables support for the Mesh GATT Proxy Service, From 4dc1b67ed76708ed0ea0663c51c3223377a7e609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 21 Oct 2021 15:36:46 +0200 Subject: [PATCH 227/306] host/mesh: Use common buf size for all conn Use common buffer size for all bluetooth mesh connection. This is port of 4fcf5496071fad53e43cd756c65b812a1421840b --- nimble/host/mesh/src/proxy_msg.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c index 09064d3728..27d53c484d 100644 --- a/nimble/host/mesh/src/proxy_msg.c +++ b/nimble/host/mesh/src/proxy_msg.c @@ -50,12 +50,12 @@ #define PROXY_BUF_LEN_MAX 30 #if defined(CONFIG_BT_MESH_PB_GATT) -#define PROXY_MSG_FIRST_BUF_LEN PB_GATT_BUF_LEN_MAX +#define PROXY_MSG_BUF_LEN PB_GATT_BUF_LEN_MAX #else -#define PROXY_MSG_FIRST_BUF_LEN PROXY_BUF_LEN_MAX +#define PROXY_MSG_BUF_LEN PROXY_BUF_LEN_MAX #endif -static uint8_t bufs[PROXY_MSG_FIRST_BUF_LEN + +static uint8_t bufs[CONFIG_BT_MAX_CONN + ((CONFIG_BT_MAX_CONN - 1) * PROXY_BUF_LEN_MAX)]; static struct bt_mesh_proxy_role roles[CONFIG_BT_MAX_CONN]; @@ -176,8 +176,6 @@ int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, static void proxy_msg_init(struct bt_mesh_proxy_role *role) { - uint8_t i, len; - uint8_t *buf; /* Check if buf has been allocated, in this way, we no longer need * to repeat the operation. @@ -187,16 +185,9 @@ static void proxy_msg_init(struct bt_mesh_proxy_role *role) return; } - i = role->conn_handle; - if (!i) { - len = PROXY_MSG_FIRST_BUF_LEN; - buf = bufs; - } else { - len = PROXY_BUF_LEN_MAX; - buf = &bufs[PROXY_MSG_FIRST_BUF_LEN + (PROXY_BUF_LEN_MAX * (i - 1))]; - } - - net_buf_simple_init_with_data(role->buf, buf, len); + net_buf_simple_init_with_data(role->buf, + &bufs[role->conn_handle * PROXY_MSG_BUF_LEN], + PROXY_MSG_BUF_LEN); net_buf_simple_reset(role->buf); } From ed2e5ae2aea790f5fc76dc627a3fe742892bfe1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 22 Oct 2021 07:39:21 +0200 Subject: [PATCH 228/306] host/mesh: Move proxy message size to kconfig Add `BT_MESH_PROXY_MSG_LEN` to config proxy message length This is port of 5ddbdcedd0046d4f3d541667579c029afd8d01a9 --- nimble/host/mesh/include/mesh/glue.h | 1 + nimble/host/mesh/src/cfg.c | 3 +-- nimble/host/mesh/src/proxy_msg.c | 17 ++++------------- nimble/host/mesh/syscfg.yml | 11 +++++++++++ 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 588e79a487..44631f3e57 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -547,6 +547,7 @@ static inline unsigned int find_msb_set(uint32_t op) #define CONFIG_BT_MESH_RELAY MYNEWT_VAL(BLE_MESH_RELAY) #define CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_COUNT) #define CONFIG_BT_MESH_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED) +#define CONFIG_BT_MESH_PROXY_MSG_LEN MYNEWT_VAL(BLE_MESH_PROXY_MSG_LEN) #define printk console_printf diff --git a/nimble/host/mesh/src/cfg.c b/nimble/host/mesh/src/cfg.c index 9ed212abc4..e866cb7911 100644 --- a/nimble/host/mesh/src/cfg.c +++ b/nimble/host/mesh/src/cfg.c @@ -15,8 +15,7 @@ #include "cfg.h" #include "mesh/glue.h" -#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_CFG) -#define LOG_MODULE_NAME bt_mesh_cfg +#define MESH_LOG_MODULE BLE_MESH_LOG #include "log/log.h" /* Miscellaneous configuration server model states */ diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c index 27d53c484d..aa9fd5e817 100644 --- a/nimble/host/mesh/src/proxy_msg.c +++ b/nimble/host/mesh/src/proxy_msg.c @@ -46,17 +46,7 @@ #define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) -#define PB_GATT_BUF_LEN_MAX 66 -#define PROXY_BUF_LEN_MAX 30 - -#if defined(CONFIG_BT_MESH_PB_GATT) -#define PROXY_MSG_BUF_LEN PB_GATT_BUF_LEN_MAX -#else -#define PROXY_MSG_BUF_LEN PROXY_BUF_LEN_MAX -#endif - -static uint8_t bufs[CONFIG_BT_MAX_CONN + - ((CONFIG_BT_MAX_CONN - 1) * PROXY_BUF_LEN_MAX)]; +static uint8_t bufs[CONFIG_BT_MAX_CONN * CONFIG_BT_MESH_PROXY_MSG_LEN]; static struct bt_mesh_proxy_role roles[CONFIG_BT_MAX_CONN]; @@ -186,8 +176,9 @@ static void proxy_msg_init(struct bt_mesh_proxy_role *role) } net_buf_simple_init_with_data(role->buf, - &bufs[role->conn_handle * PROXY_MSG_BUF_LEN], - PROXY_MSG_BUF_LEN); + &bufs[role->conn_handle * + CONFIG_BT_MESH_PROXY_MSG_LEN], + CONFIG_BT_MESH_PROXY_MSG_LEN); net_buf_simple_reset(role->buf); } diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index 1ada38806d..eb79b04947 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -103,6 +103,12 @@ syscfg.defs: BLE_MESH_GATT: value: 1 + BLE_MESH_PROXY_MSG_LEN: + description: > + Integer value + value: + restrictions: BLE_MESH_GATT + BLE_MESH_GATT_SERVER: value: 1 restrictions: BLE_MESH_GATT @@ -970,3 +976,8 @@ syscfg.vals.BLE_MESH_PB_GATT: syscfg.vals.BLE_MESH_PB_ADV: BLE_MESH_PROV: 1 + +syscfg.vals.'BLE_MESH_PB_GATT': + BLE_MESH_PROXY_MSG_LEN: 66 +syscfg.vals.'BLE_MESH_GATT_PROXY': + BLE_MESH_PROXY_MSG_LEN: 33 \ No newline at end of file From 804a6642fb5026a5b6199efcb19a12229b37a15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 22 Oct 2021 07:53:59 +0200 Subject: [PATCH 229/306] host/mesh: cleanup log modules --- nimble/host/mesh/src/adv_ext.c | 1 - nimble/host/mesh/src/adv_legacy.c | 1 - nimble/host/mesh/src/cdb.c | 3 +-- nimble/host/mesh/src/msg.c | 3 --- nimble/host/mesh/src/proxy_srv.c | 3 +-- 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/nimble/host/mesh/src/adv_ext.c b/nimble/host/mesh/src/adv_ext.c index 364fb249b3..a531863f76 100644 --- a/nimble/host/mesh/src/adv_ext.c +++ b/nimble/host/mesh/src/adv_ext.c @@ -8,7 +8,6 @@ */ #define MESH_LOG_MODULE BLE_MESH_ADV_LOG -#define LOG_MODULE_NAME bt_mesh_adv_ext #include "adv.h" diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 9506c08baf..eed3456ddf 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -8,7 +8,6 @@ */ #define MESH_LOG_MODULE BLE_MESH_ADV_LOG -#define LOG_MODULE_NAME bt_mesh_adv_legacy #include "adv.h" #include "net.h" diff --git a/nimble/host/mesh/src/cdb.c b/nimble/host/mesh/src/cdb.c index 5c7f88d470..f92ece6090 100644 --- a/nimble/host/mesh/src/cdb.c +++ b/nimble/host/mesh/src/cdb.c @@ -4,8 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_CDB) -#define LOG_MODULE_NAME bt_mesh_cdb +#define MESH_LOG_MODULE BLE_MESH_LOG #include "log/log.h" #include diff --git a/nimble/host/mesh/src/msg.c b/nimble/host/mesh/src/msg.c index 230a2ab434..f75082cb96 100644 --- a/nimble/host/mesh/src/msg.c +++ b/nimble/host/mesh/src/msg.c @@ -8,9 +8,6 @@ #include "mesh/mesh.h" -#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_ACCESS) -#define LOG_MODULE_NAME bt_mesh_msg - void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode) { net_buf_simple_init(msg, 0); diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index b60cf3d64b..e0883a67ed 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -7,8 +7,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define BT_DBG_ENABLED CONFIG_BT_MESH_DEBUG_PROXY -#define LOG_MODULE_NAME bt_mesh_gatt +#define MESH_LOG_MODULE BLE_MESH_PROXY_LOG #include "../../host/src/ble_hs_priv.h" #include "services/gatt/ble_svc_gatt.h" From 2745cf4708d5985e92984e24db46d7892a292bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 22 Oct 2021 07:55:40 +0200 Subject: [PATCH 230/306] host/mesh: logging public key in big endian Local public key has been logged in little endian but remote public key in big endian. That has been changed. Both are logged in big endian to be able to compare in logs. This is port of 797c17436bd071e71fdc58584e6741d9d5ebb332 --- nimble/host/mesh/src/prov_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/prov_device.c b/nimble/host/mesh/src/prov_device.c index 9d48547e3d..e9e2d2b122 100644 --- a/nimble/host/mesh/src/prov_device.c +++ b/nimble/host/mesh/src/prov_device.c @@ -248,14 +248,14 @@ static void send_pub_key(void) return; } - BT_DBG("Local Public Key: %s", bt_hex(key, BT_PUB_KEY_LEN)); - bt_mesh_prov_buf_init(buf, PROV_PUB_KEY); /* Swap X and Y halves independently to big-endian */ sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), key, BT_PUB_KEY_COORD_LEN); sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), &key[BT_PUB_KEY_COORD_LEN], 32); + BT_DBG("Local Public Key: %s", bt_hex(buf->om_data + 1, BT_PUB_KEY_LEN)); + /* PublicKeyDevice */ memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, &buf->om_data[1], PDU_LEN_PUB_KEY); From 267eed3ca7adcd1d18b7de790359424acfc6639d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 22 Oct 2021 07:58:41 +0200 Subject: [PATCH 231/306] host/mesh: Missed IV update cannot be captured It seems that if the IV update is missed, a node cannot recover it until the IV index has increased to a value greater than Node's Last known IV + 1. This is port of c1e053c9b3789b613771b68ba521b1b2585517c6 --- nimble/host/mesh/src/net.c | 42 +++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index e5391bf21c..f994bcc747 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -85,6 +85,15 @@ struct bt_mesh_net bt_mesh = { .local_queue = STAILQ_HEAD_INITIALIZER(bt_mesh.local_queue), }; +/* Mesh Profile Specification 3.10.6 + * The node shall not execute more than one IV Index Recovery within a period of + * 192 hours. + * + * Mark that the IV Index Recovery has been done to prevent two recoveries to be + * done before a normal IV Index update has been completed within 96h+96h. + */ +static bool ivi_was_recovered; + static struct os_mbuf_pool loopback_os_mbuf_pool; static struct os_mempool loopback_buf_mempool; os_membuf_t loopback_mbuf_membuf[ @@ -259,24 +268,24 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) return false; } - if (iv_index > bt_mesh.iv_index + 1) { + if ((iv_index > bt_mesh.iv_index + 1) || + (iv_index == bt_mesh.iv_index + 1 && !iv_update)) { + if (ivi_was_recovered) { + BT_ERR("IV Index Recovery before minimum delay"); + return false; + } + /* The Mesh profile specification allows to initiate an + * IV Index Recovery procedure if previous IV update has + * been missed. This allows the node to remain + * functional. + */ BT_WARN("Performing IV Index Recovery"); + ivi_was_recovered = true; bt_mesh_rpl_clear(); bt_mesh.iv_index = iv_index; bt_mesh.seq = 0; goto do_update; } - - if (iv_index == bt_mesh.iv_index + 1 && !iv_update) { - BT_WARN("Ignoring new index in normal mode"); - return false; - } - - if (!iv_update) { - /* Nothing to do */ - BT_DBG("Already in Normal state"); - return false; - } } if (!(IS_ENABLED(CONFIG_BT_MESH_IV_UPDATE_TEST) && @@ -294,21 +303,22 @@ bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) return false; } -do_update: - atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv_update); - bt_mesh.ivu_duration = 0U; - if (iv_update) { bt_mesh.iv_index = iv_index; BT_DBG("IV Update state entered. New index 0x%08x", (unsigned) bt_mesh.iv_index); bt_mesh_rpl_reset(); + ivi_was_recovered = false; } else { BT_DBG("Normal mode entered"); bt_mesh.seq = 0; } +do_update: + atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv_update); + bt_mesh.ivu_duration = 0U; + k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); /* Notify other modules */ From f757df8e70ad7339465b418785bdcbf8cea8678c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 22 Oct 2021 08:10:28 +0200 Subject: [PATCH 232/306] host/mesh: Fix crash on disconnect bt_mesh_proxy_role_setup() is called conditionally when peer is connected and gatt_disconnected() is always called. This leads to unbalance in role->conn reference count and crash. Instead of hot-fixing this in gatt_disconnected(), this commit adds proper bt_mesh_proxy_role_cleanup() API that is called by roles implementations if cleanup is needed. This is port of 088fac76ed65a6cb8c367a89fae53d0e4bea2763 --- nimble/host/mesh/src/pb_gatt_srv.c | 5 ++++- nimble/host/mesh/src/proxy_msg.c | 7 +------ nimble/host/mesh/src/proxy_msg.h | 2 +- nimble/host/mesh/src/proxy_srv.c | 9 ++++----- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index 55900e188e..d04948262d 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -159,7 +159,10 @@ void gatt_disconnected_pb_gatt(uint16_t conn_handle, uint8_t reason) return; } - cli = NULL; + if (cli) { + bt_mesh_proxy_role_cleanup(cli); + cli = NULL; + } BT_DBG("conn %p reason 0x%02x", (void *)conn, reason); diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c index aa9fd5e817..91b4ba694a 100644 --- a/nimble/host/mesh/src/proxy_msg.c +++ b/nimble/host/mesh/src/proxy_msg.c @@ -200,13 +200,8 @@ struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(uint16_t conn_handle, return role; } -void gatt_disconnected_proxy_msg(uint16_t conn_handle, uint8_t reason) +void bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role *role) { - struct bt_mesh_proxy_role *role; - - BT_DBG("conn_handle %d reason 0x%02x", conn_handle, reason); - - role = &roles[conn_handle]; /* If this fails, the work handler exits early, as * there's no active connection. diff --git a/nimble/host/mesh/src/proxy_msg.h b/nimble/host/mesh/src/proxy_msg.h index 38e9ebc110..befdb1f351 100644 --- a/nimble/host/mesh/src/proxy_msg.h +++ b/nimble/host/mesh/src/proxy_msg.h @@ -60,7 +60,7 @@ ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, struct os_mbuf *msg, void (*end)(uint16_t, void *), void *user_data); void bt_mesh_proxy_msg_init(struct bt_mesh_proxy_role *role); -void gatt_disconnected_proxy_msg(uint16_t conn_handle, uint8_t reason); +void bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role *role); struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(uint16_t conn_handle, proxy_send_cb_t send, proxy_recv_cb_t recv); diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index e0883a67ed..dae61a4a1f 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -874,7 +874,10 @@ static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) conn_count--; client = find_client(conn_handle); - client->cli = NULL; + if (client->cli) { + bt_mesh_proxy_role_cleanup(client->cli); + client->cli = NULL; + } } static int proxy_send(uint16_t conn_handle, @@ -953,10 +956,6 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) #if MYNEWT_VAL(BLE_MESH_PB_GATT) gatt_disconnected_pb_gatt(event->disconnect.conn.conn_handle, event->disconnect.reason); -#endif -#if MYNEWT_VAL(BLE_MESH_PROXY) - gatt_disconnected_proxy_msg(event->disconnect.conn.conn_handle, - event->disconnect.reason); #endif } else if (event->type == BLE_GAP_EVENT_SUBSCRIBE) { if (event->subscribe.attr_handle == svc_handles.proxy_data_out_h) { From 6617c2970493e05dbb921bc20c7d9a3fe08b5c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 22 Oct 2021 08:12:43 +0200 Subject: [PATCH 233/306] host/mesh: Model extensions walk stops before last model When reaching the last model in the circular extension linked list, the walker would abandon the walk before checking the last model. This makes us skip models when checking the subscription list, potentially causing incoming messages to be wrongfully ignored. This is port of cd89f4239368b106fbfab9555cf445fbc00203a2 --- nimble/host/mesh/src/access.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 33169a7501..6df342afea 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -819,11 +819,11 @@ void bt_mesh_model_extensions_walk(struct bt_mesh_model *model, #else struct bt_mesh_model *it; - if (model->next == NULL) { - (void)cb(model, user_data); + if (cb(model, user_data) == BT_MESH_WALK_STOP || !model->next) { return; } - for (it = model; (it != NULL) && (it->next != model); it = it->next) { + /* List is circular. Step through all models until we reach the start: */ + for (it = model->next; it != model; it = it->next) { if (cb(it, user_data) == BT_MESH_WALK_STOP) { return; } From 82ccdbce6f513f2beabf62336fc46d549f888cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 22 Oct 2021 08:58:34 +0200 Subject: [PATCH 234/306] host/mesh: post-sync fixes This resolves some build errors introduced after sync with Zephyr. --- nimble/host/mesh/src/access.c | 1 - nimble/host/mesh/src/adv_legacy.c | 3 +-- nimble/host/mesh/src/glue.c | 5 ++--- nimble/host/mesh/src/proxy_srv.c | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 6df342afea..28402885c6 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -866,7 +866,6 @@ int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_mod a->next = b; } - mod->extends = base_mod; return 0; } #endif diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index eed3456ddf..ab8a921619 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -15,6 +15,7 @@ #include "beacon.h" #include "prov.h" #include "proxy.h" +#include "mesh/glue.h" #include "pb_gatt_srv.h" #if MYNEWT_VAL(BLE_MESH_ADV_LEGACY) @@ -29,7 +30,6 @@ static int32_t adv_int_min = ADV_INT_DEFAULT_MS; -#if !MYNEWT_VAL(BLE_EXT_ADV) static int adv_initialized = false; /* TinyCrypt PRNG consumes a lot of stack space, so we need to have * an increased call stack whenever it's used. @@ -42,7 +42,6 @@ static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; static struct os_mempool adv_buf_mempool; -#endif static struct ble_npl_eventq adv_queue; static inline void adv_send(struct os_mbuf *buf) diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index 80f9b7e75e..c7b2cc16f8 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -834,14 +834,13 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, return 0; } +#endif int bt_le_adv_stop() { - return ble_gap_adv_stop(); + return ble_gap_adv_stop(); } -#endif - #if MYNEWT_VAL(BLE_MESH_PROXY) int bt_mesh_proxy_svcs_register(void); #endif diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index dae61a4a1f..7fa297fa7b 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -932,7 +932,7 @@ static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) gatt_connected(event->adv_complete.conn_handle); #if MYNEWT_VAL(BLE_MESH_PB_GATT) gatt_connected_pb_gatt(event->adv_complete.conn_handle, - event->adv_complete.status); + event->adv_complete.reason); #endif } #else From 489bb3a92550e53e8e0bb6ce6315e64f362b4d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 22 Oct 2021 08:59:35 +0200 Subject: [PATCH 235/306] apps/blemesh: fix build after introducing return codes in models This applies to both blemesh, blemesh_models_example_1 and blemesh_models_example_2 --- apps/blemesh/src/main.c | 58 +- apps/blemesh_models_example_1/src/main.c | 39 +- .../src/device_composition.c | 501 +++++++++++------- .../src/device_composition.h | 12 +- 4 files changed, 377 insertions(+), 233 deletions(-) diff --git a/apps/blemesh/src/main.c b/apps/blemesh/src/main.c index 65270554b3..56d0476f86 100644 --- a/apps/blemesh/src/main.c +++ b/apps/blemesh/src/main.c @@ -144,11 +144,12 @@ static struct bt_mesh_model_pub gen_onoff_pub; static uint8_t gen_on_off_state; static int16_t gen_level_state; -static void gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { struct os_mbuf *msg = NET_BUF_SIMPLE(3); uint8_t *status; + int rc; console_printf("#mesh-onoff STATUS\n"); @@ -156,23 +157,25 @@ static void gen_onoff_status(struct bt_mesh_model *model, status = net_buf_simple_add(msg, 1); *status = gen_on_off_state; - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { console_printf("#mesh-onoff STATUS: send status failed\n"); } os_mbuf_free_chain(msg); + return rc; } -static void gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { console_printf("#mesh-onoff GET\n"); - gen_onoff_status(model, ctx); + return gen_onoff_status(model, ctx); } -static void gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -181,10 +184,10 @@ static void gen_onoff_set(struct bt_mesh_model *model, gen_on_off_state = buf->om_data[0]; hal_gpio_write(LED_2, !gen_on_off_state); - gen_onoff_status(model, ctx); + return gen_onoff_status(model, ctx); } -static void gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -192,6 +195,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model, gen_on_off_state = buf->om_data[0]; hal_gpio_write(LED_2, !gen_on_off_state); + return 0; } static const struct bt_mesh_model_op gen_onoff_op[] = { @@ -201,48 +205,56 @@ static const struct bt_mesh_model_op gen_onoff_op[] = { BT_MESH_MODEL_OP_END, }; -static void gen_level_status(struct bt_mesh_model *model, +static int gen_level_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { struct os_mbuf *msg = NET_BUF_SIMPLE(4); + int rc; console_printf("#mesh-level STATUS\n"); bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x08)); net_buf_simple_add_le16(msg, gen_level_state); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { console_printf("#mesh-level STATUS: send status failed\n"); } os_mbuf_free_chain(msg); + return rc; } -static void gen_level_get(struct bt_mesh_model *model, +static int gen_level_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { console_printf("#mesh-level GET\n"); - gen_level_status(model, ctx); + return gen_level_status(model, ctx); } -static void gen_level_set(struct bt_mesh_model *model, +static int gen_level_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { int16_t level; + int rc; level = (int16_t) net_buf_simple_pull_le16(buf); console_printf("#mesh-level SET: level=%d\n", level); - gen_level_status(model, ctx); + rc = gen_level_status(model, ctx); + if (rc) { + return rc; + } gen_level_state = level; console_printf("#mesh-level: level=%d\n", gen_level_state); + return 0; } -static void gen_level_set_unack(struct bt_mesh_model *model, +static int gen_level_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -253,9 +265,10 @@ static void gen_level_set_unack(struct bt_mesh_model *model, gen_level_state = level; console_printf("#mesh-level: level=%d\n", gen_level_state); + return 0; } -static void gen_delta_set(struct bt_mesh_model *model, +static int gen_delta_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -268,9 +281,10 @@ static void gen_delta_set(struct bt_mesh_model *model, gen_level_state += delta_level; console_printf("#mesh-level: level=%d\n", gen_level_state); + return 0; } -static void gen_delta_set_unack(struct bt_mesh_model *model, +static int gen_delta_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -281,18 +295,21 @@ static void gen_delta_set_unack(struct bt_mesh_model *model, gen_level_state += delta_level; console_printf("#mesh-level: level=%d\n", gen_level_state); + return 0; } -static void gen_move_set(struct bt_mesh_model *model, +static int gen_move_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + return 0; } -static void gen_move_set_unack(struct bt_mesh_model *model, +static int gen_move_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + return 0; } static const struct bt_mesh_model_op gen_level_op[] = { @@ -317,11 +334,12 @@ static struct bt_mesh_model root_models[] = { static struct bt_mesh_model_pub vnd_model_pub; -static void vnd_model_recv(struct bt_mesh_model *model, +static int vnd_model_recv(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(3); + int rc; console_printf("#vendor-model-recv\n"); @@ -331,11 +349,13 @@ static void vnd_model_recv(struct bt_mesh_model *model, bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_3(0x01, CID_VENDOR)); os_mbuf_append(msg, buf->om_data, buf->om_len); + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { console_printf("#vendor-model-recv: send rsp failed\n"); } os_mbuf_free_chain(msg); + return rc; } static const struct bt_mesh_model_op vnd_model_op[] = { diff --git a/apps/blemesh_models_example_1/src/main.c b/apps/blemesh_models_example_1/src/main.c index 736d4d32bf..80a69c7052 100644 --- a/apps/blemesh_models_example_1/src/main.c +++ b/apps/blemesh_models_example_1/src/main.c @@ -68,19 +68,19 @@ #define BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03) #define BT_MESH_MODEL_OP_GEN_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04) -static void gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf); -static void gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf); -static void gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf); -static void gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf); @@ -318,26 +318,29 @@ static uint16_t primary_net_idx; * */ -static void gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4); struct onoff_state *state = model->user_data; + int rc; BT_INFO("addr 0x%04x onoff 0x%02x", bt_mesh_model_elem(model)->addr, state->current); bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS); net_buf_simple_add_u8(msg, state->current); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { BT_ERR("Unable to send On Off Status response"); } os_mbuf_free_chain(msg); + return rc; } -static void gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -372,23 +375,34 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS); net_buf_simple_add_u8(msg, state->current); err = bt_mesh_model_publish(model); - if (err) { + if (err != 0) { BT_ERR("bt_mesh_model_publish err %d", err); + return err; } } + return 0; } -static void gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { BT_INFO(""); + int rc; + + rc = gen_onoff_set_unack(model, ctx, buf); + if (rc != 0) { + return rc; + } - gen_onoff_set_unack(model, ctx, buf); - gen_onoff_get(model, ctx, buf); + rc = gen_onoff_get(model, ctx, buf); + if (rc != 0) { + return rc; + } + return 0; } -static void gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -398,6 +412,7 @@ static void gen_onoff_status(struct bt_mesh_model *model, BT_INFO("Node 0x%04x OnOff status from 0x%04x with state 0x%02x", bt_mesh_model_elem(model)->addr, ctx->addr, state); + return 0; } static int output_number(bt_mesh_output_action_t action, uint32_t number) diff --git a/apps/blemesh_models_example_2/src/device_composition.c b/apps/blemesh_models_example_2/src/device_composition.c index 5dfeaf8ed5..40ede50126 100644 --- a/apps/blemesh_models_example_2/src/device_composition.c +++ b/apps/blemesh_models_example_2/src/device_composition.c @@ -147,7 +147,7 @@ static struct bt_mesh_elem elements[]; /* message handlers (Start) */ /* Generic OnOff Server message handlers */ -static void gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -168,16 +168,17 @@ static void gen_onoff_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -void gen_onoff_publish(struct bt_mesh_model *model) +int gen_onoff_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct generic_onoff_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS); @@ -193,21 +194,23 @@ void gen_onoff_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } -static void gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { uint8_t tid, onoff, tt, delay; int64_t now; + int err; struct generic_onoff_state *state = model->user_data; onoff = net_buf_simple_pull_u8(buf); tid = net_buf_simple_pull_u8(buf); if (onoff > STATE_ON) { - return; + return 0; } now = k_uptime_get(); @@ -215,7 +218,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - return; + return 0; } switch (buf->om_len) { @@ -226,13 +229,13 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -247,8 +250,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model, if (state->target_onoff != state->onoff) { onoff_tt_values(state, tt, delay); } else { - gen_onoff_publish(model); - return; + return gen_onoff_publish(model); } /* For Instantaneous Transition */ @@ -257,23 +259,28 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model, } state->transition->just_started = true; - gen_onoff_publish(model); + err = gen_onoff_publish(model); onoff_handler(state); + if (err) { + return err; + } + return 0; } -static void gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { uint8_t tid, onoff, tt, delay; int64_t now; + int rc; struct generic_onoff_state *state = model->user_data; onoff = net_buf_simple_pull_u8(buf); tid = net_buf_simple_pull_u8(buf); if (onoff > STATE_ON) { - return; + return 0; } now = k_uptime_get(); @@ -281,8 +288,8 @@ static void gen_onoff_set(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - gen_onoff_get(model, ctx, buf); - return; + rc = gen_onoff_get(model, ctx, buf); + return rc; } switch (buf->om_len) { @@ -293,13 +300,13 @@ static void gen_onoff_set(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -315,8 +322,8 @@ static void gen_onoff_set(struct bt_mesh_model *model, onoff_tt_values(state, tt, delay); } else { gen_onoff_get(model, ctx, buf); - gen_onoff_publish(model); - return; + rc = gen_onoff_publish(model); + return rc; } /* For Instantaneous Transition */ @@ -326,12 +333,13 @@ static void gen_onoff_set(struct bt_mesh_model *model, state->transition->just_started = true; gen_onoff_get(model, ctx, buf); - gen_onoff_publish(model); + rc = gen_onoff_publish(model); onoff_handler(state); + return rc; } /* Generic OnOff Client message handlers */ -static void gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -342,10 +350,11 @@ static void gen_onoff_status(struct bt_mesh_model *model, printk("Target OnOff = %02x\n", net_buf_simple_pull_u8(buf)); printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf)); } + return 0; } /* Generic Level Server message handlers */ -static void gen_level_get(struct bt_mesh_model *model, +static int gen_level_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -366,16 +375,17 @@ static void gen_level_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -void gen_level_publish(struct bt_mesh_model *model) +int gen_level_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct generic_level_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS); @@ -391,9 +401,10 @@ void gen_level_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } -static void gen_level_set_unack(struct bt_mesh_model *model, +static int gen_level_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -410,7 +421,7 @@ static void gen_level_set_unack(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - return; + return 0; } switch (buf->om_len) { @@ -421,13 +432,13 @@ static void gen_level_set_unack(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -443,7 +454,7 @@ static void gen_level_set_unack(struct bt_mesh_model *model, level_tt_values(state, tt, delay); } else { gen_level_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -463,9 +474,10 @@ static void gen_level_set_unack(struct bt_mesh_model *model, transition_type = LEVEL_TEMP_TT; level_temp_handler(state); } + return 0; } -static void gen_level_set(struct bt_mesh_model *model, +static int gen_level_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -483,7 +495,7 @@ static void gen_level_set(struct bt_mesh_model *model, state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { gen_level_get(model, ctx, buf); - return; + return 0; } switch (buf->om_len) { @@ -494,13 +506,13 @@ static void gen_level_set(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -517,7 +529,7 @@ static void gen_level_set(struct bt_mesh_model *model, } else { gen_level_get(model, ctx, buf); gen_level_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -538,9 +550,10 @@ static void gen_level_set(struct bt_mesh_model *model, transition_type = LEVEL_TEMP_TT; level_temp_handler(state); } + return 0; } -static void gen_delta_set_unack(struct bt_mesh_model *model, +static int gen_delta_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -559,7 +572,7 @@ static void gen_delta_set_unack(struct bt_mesh_model *model, (now - state->last_msg_timestamp <= K_SECONDS(6))) { if (state->last_delta == delta) { - return; + return 0; } tmp32 = state->last_level + delta; @@ -576,13 +589,13 @@ static void gen_delta_set_unack(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -605,8 +618,7 @@ static void gen_delta_set_unack(struct bt_mesh_model *model, if (state->target_level != state->level) { level_tt_values(state, tt, delay); } else { - gen_level_publish(model); - return; + return gen_level_publish(model); } /* For Instantaneous Transition */ @@ -627,9 +639,10 @@ static void gen_delta_set_unack(struct bt_mesh_model *model, transition_type = LEVEL_TEMP_TT_DELTA; level_temp_handler(state); } + return 0; } -static void gen_delta_set(struct bt_mesh_model *model, +static int gen_delta_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -649,7 +662,7 @@ static void gen_delta_set(struct bt_mesh_model *model, if (state->last_delta == delta) { gen_level_get(model, ctx, buf); - return; + return 0; } tmp32 = state->last_level + delta; @@ -666,13 +679,13 @@ static void gen_delta_set(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -697,7 +710,7 @@ static void gen_delta_set(struct bt_mesh_model *model, } else { gen_level_get(model, ctx, buf); gen_level_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -718,14 +731,16 @@ static void gen_delta_set(struct bt_mesh_model *model, transition_type = LEVEL_TEMP_TT_DELTA; level_temp_handler(state); } + return 0; } -static void gen_level_move_get(struct bt_mesh_model *model, +static int gen_level_move_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4); struct generic_level_state *state = model->user_data; + int rc; bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS); net_buf_simple_add_le16(msg, state->level); @@ -740,21 +755,23 @@ static void gen_level_move_get(struct bt_mesh_model *model, net_buf_simple_add_u8(msg, UNKNOWN_VALUE); } - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { printk("Unable to send GEN_LEVEL_SRV Status response\n"); } os_mbuf_free_chain(msg); + return rc; } -static void gen_level_move_publish(struct bt_mesh_model *model) +static int gen_level_move_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct generic_level_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_LEVEL_STATUS); @@ -774,9 +791,10 @@ static void gen_level_move_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } -static void gen_move_set_unack(struct bt_mesh_model *model, +static int gen_move_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -785,6 +803,7 @@ static void gen_move_set_unack(struct bt_mesh_model *model, int32_t tmp32; int64_t now; struct generic_level_state *state = model->user_data; + int rc; delta = (int16_t) net_buf_simple_pull_le16(buf); tid = net_buf_simple_pull_u8(buf); @@ -794,7 +813,7 @@ static void gen_move_set_unack(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - return; + return 0; } switch (buf->om_len) { @@ -805,13 +824,13 @@ static void gen_move_set_unack(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -835,16 +854,16 @@ static void gen_move_set_unack(struct bt_mesh_model *model, if (state->target_level != state->level) { level_tt_values(state, tt, delay); } else { - gen_level_move_publish(model); - return; + rc = gen_level_move_publish(model); + return rc; } if (state->transition->counter == 0) { - return; + return 0; } state->transition->just_started = true; - gen_level_move_publish(model); + rc = gen_level_move_publish(model); if (bt_mesh_model_elem(model)->addr == elements[0].addr) { /* Root element */ @@ -855,9 +874,10 @@ static void gen_move_set_unack(struct bt_mesh_model *model, transition_type = LEVEL_TEMP_TT_MOVE; level_temp_handler(state); } + return rc; } -static void gen_move_set(struct bt_mesh_model *model, +static int gen_move_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -866,6 +886,7 @@ static void gen_move_set(struct bt_mesh_model *model, int32_t tmp32; int64_t now; struct generic_level_state *state = model->user_data; + int rc; delta = (int16_t) net_buf_simple_pull_le16(buf); tid = net_buf_simple_pull_u8(buf); @@ -875,8 +896,8 @@ static void gen_move_set(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - gen_level_move_get(model, ctx, buf); - return; + rc = gen_level_move_get(model, ctx, buf); + return rc; } switch (buf->om_len) { @@ -887,13 +908,13 @@ static void gen_move_set(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -918,17 +939,17 @@ static void gen_move_set(struct bt_mesh_model *model, level_tt_values(state, tt, delay); } else { gen_level_move_get(model, ctx, buf); - gen_level_move_publish(model); - return; + rc = gen_level_move_publish(model); + return rc; } if (state->transition->counter == 0) { - return; + return 0; } state->transition->just_started = true; gen_level_move_get(model, ctx, buf); - gen_level_move_publish(model); + rc = gen_level_move_publish(model); if (bt_mesh_model_elem(model)->addr == elements[0].addr) { /* Root element */ @@ -939,10 +960,11 @@ static void gen_move_set(struct bt_mesh_model *model, transition_type = LEVEL_TEMP_TT_MOVE; level_temp_handler(state); } + return rc; } /* Generic Level Client message handlers */ -static void gen_level_status(struct bt_mesh_model *model, +static int gen_level_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -953,10 +975,11 @@ static void gen_level_status(struct bt_mesh_model *model, printk("Target Level = %04x\n", net_buf_simple_pull_le16(buf)); printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf)); } + return 0; } /* Generic Default Transition Time Server message handlers */ -static void gen_def_trans_time_get(struct bt_mesh_model *model, +static int gen_def_trans_time_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -971,16 +994,17 @@ static void gen_def_trans_time_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -static void gen_def_trans_time_publish(struct bt_mesh_model *model) +static int gen_def_trans_time_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct gen_def_trans_time_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_GEN_DEF_TRANS_TIME_STATUS); @@ -990,6 +1014,7 @@ static void gen_def_trans_time_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } static bool gen_def_trans_time_setunack(struct bt_mesh_model *model, @@ -1017,71 +1042,78 @@ static bool gen_def_trans_time_setunack(struct bt_mesh_model *model, return true; } -static void gen_def_trans_time_set_unack(struct bt_mesh_model *model, +static int gen_def_trans_time_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (gen_def_trans_time_setunack(model, ctx, buf) == true) { - gen_def_trans_time_publish(model); + return gen_def_trans_time_publish(model); } + return 0; } -static void gen_def_trans_time_set(struct bt_mesh_model *model, +static int gen_def_trans_time_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (gen_def_trans_time_setunack(model, ctx, buf) == true) { gen_def_trans_time_get(model, ctx, buf); - gen_def_trans_time_publish(model); + return gen_def_trans_time_publish(model); } + return 0; } /* Generic Default Transition Time Client message handlers */ -static void gen_def_trans_time_status(struct bt_mesh_model *model, +static int gen_def_trans_time_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { printk("Acknownledgement from GEN_DEF_TT_SRV\n"); printk("Transition Time = %02x\n", net_buf_simple_pull_u8(buf)); + return 0; } /* Generic Power OnOff Server message handlers */ -static void gen_onpowerup_get(struct bt_mesh_model *model, +static int gen_onpowerup_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4); struct generic_onpowerup_state *state = model->user_data; + int rc; bt_mesh_model_msg_init(msg, BT_MESH_MODEL_GEN_ONPOWERUP_STATUS); net_buf_simple_add_u8(msg, state->onpowerup); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { printk("Unable to send GEN_POWER_ONOFF_SRV Status response\n"); } os_mbuf_free_chain(msg); + return rc; } /* Generic Power OnOff Client message handlers */ -static void gen_onpowerup_status(struct bt_mesh_model *model, +static int gen_onpowerup_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { printk("Acknownledgement from GEN_POWER_ONOFF_SRV\n"); printk("OnPowerUp = %02x\n", net_buf_simple_pull_u8(buf)); + return 0; } /* Generic Power OnOff Setup Server message handlers */ -static void gen_onpowerup_publish(struct bt_mesh_model *model) +static int gen_onpowerup_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct generic_onpowerup_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_GEN_ONPOWERUP_STATUS); @@ -1091,6 +1123,7 @@ static void gen_onpowerup_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } static bool gen_onpowerup_setunack(struct bt_mesh_model *model, @@ -1117,32 +1150,35 @@ static bool gen_onpowerup_setunack(struct bt_mesh_model *model, return true; } -static void gen_onpowerup_set_unack(struct bt_mesh_model *model, +static int gen_onpowerup_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (gen_onpowerup_setunack(model, ctx, buf) == true) { - gen_onpowerup_publish(model); + return gen_onpowerup_publish(model); } + return 0; } -static void gen_onpowerup_set(struct bt_mesh_model *model, +static int gen_onpowerup_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (gen_onpowerup_setunack(model, ctx, buf) == true) { gen_onpowerup_get(model, ctx, buf); - gen_onpowerup_publish(model); + return gen_onpowerup_publish(model); } + return 0; } /* Vendor Model message handlers*/ -static void vnd_get(struct bt_mesh_model *model, +static int vnd_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(3 + 6 + 4); struct vendor_state *state = model->user_data; + int err; /* This is dummy response for demo purpose */ state->response = 0xA578FEB3; @@ -1151,14 +1187,16 @@ static void vnd_get(struct bt_mesh_model *model, net_buf_simple_add_le16(msg, state->current); net_buf_simple_add_le32(msg, state->response); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + err = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (err) { printk("Unable to send VENDOR Status response\n"); } os_mbuf_free_chain(msg); + return err; } -static void vnd_set_unack(struct bt_mesh_model *model, +static int vnd_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1175,7 +1213,7 @@ static void vnd_set_unack(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - return; + return 0; } state->last_tid = tid; @@ -1193,27 +1231,37 @@ static void vnd_set_unack(struct bt_mesh_model *model, /* LED2 Off */ hal_gpio_write(led_device[1], 1); } + return 0; } -static void vnd_set(struct bt_mesh_model *model, +static int vnd_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - vnd_set_unack(model, ctx, buf); - vnd_get(model, ctx, buf); + int rc; + rc = vnd_set_unack(model, ctx, buf); + if (rc) { + return rc; + } + rc = vnd_get(model, ctx, buf); + if (rc) { + return rc; + } + return 0; } -static void vnd_status(struct bt_mesh_model *model, +static int vnd_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { printk("Acknownledgement from Vendor\n"); printk("cmd = %04x\n", net_buf_simple_pull_le16(buf)); printk("response = %08lx\n", net_buf_simple_pull_le32(buf)); + return 0; } /* Light Lightness Server message handlers */ -static void light_lightness_get(struct bt_mesh_model *model, +static int light_lightness_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1234,16 +1282,17 @@ static void light_lightness_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -void light_lightness_publish(struct bt_mesh_model *model) +int light_lightness_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct light_lightness_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_LIGHTNESS_STATUS); @@ -1259,9 +1308,10 @@ void light_lightness_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } -static void light_lightness_set_unack(struct bt_mesh_model *model, +static int light_lightness_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1278,7 +1328,7 @@ static void light_lightness_set_unack(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - return; + return 0; } switch (buf->om_len) { @@ -1289,13 +1339,13 @@ static void light_lightness_set_unack(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -1318,7 +1368,7 @@ static void light_lightness_set_unack(struct bt_mesh_model *model, light_lightness_actual_tt_values(state, tt, delay); } else { light_lightness_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -1329,9 +1379,10 @@ static void light_lightness_set_unack(struct bt_mesh_model *model, state->transition->just_started = true; light_lightness_publish(model); light_lightness_actual_handler(state); + return 0; } -static void light_lightness_set(struct bt_mesh_model *model, +static int light_lightness_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1339,6 +1390,7 @@ static void light_lightness_set(struct bt_mesh_model *model, uint16_t actual; int64_t now; struct light_lightness_state *state = model->user_data; + int rc; actual = net_buf_simple_pull_le16(buf); tid = net_buf_simple_pull_u8(buf); @@ -1348,8 +1400,7 @@ static void light_lightness_set(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - light_lightness_get(model, ctx, buf); - return; + return light_lightness_get(model, ctx, buf); } switch (buf->om_len) { @@ -1360,13 +1411,13 @@ static void light_lightness_set(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -1388,9 +1439,9 @@ static void light_lightness_set(struct bt_mesh_model *model, if (state->target_actual != state->actual) { light_lightness_actual_tt_values(state, tt, delay); } else { - light_lightness_get(model, ctx, buf); + rc = light_lightness_get(model, ctx, buf); light_lightness_publish(model); - return; + return rc; } /* For Instantaneous Transition */ @@ -1402,9 +1453,10 @@ static void light_lightness_set(struct bt_mesh_model *model, light_lightness_get(model, ctx, buf); light_lightness_publish(model); light_lightness_actual_handler(state); + return 0; } -static void light_lightness_linear_get(struct bt_mesh_model *model, +static int light_lightness_linear_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1426,16 +1478,17 @@ static void light_lightness_linear_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -void light_lightness_linear_publish(struct bt_mesh_model *model) +int light_lightness_linear_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct light_lightness_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, @@ -1452,9 +1505,10 @@ void light_lightness_linear_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } -static void light_lightness_linear_set_unack(struct bt_mesh_model *model, +static int light_lightness_linear_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1471,7 +1525,7 @@ static void light_lightness_linear_set_unack(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - return; + return 0; } switch (buf->om_len) { @@ -1482,13 +1536,13 @@ static void light_lightness_linear_set_unack(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -1504,7 +1558,7 @@ static void light_lightness_linear_set_unack(struct bt_mesh_model *model, light_lightness_linear_tt_values(state, tt, delay); } else { light_lightness_linear_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -1515,9 +1569,10 @@ static void light_lightness_linear_set_unack(struct bt_mesh_model *model, state->transition->just_started = true; light_lightness_linear_publish(model); light_lightness_linear_handler(state); + return 0; } -static void light_lightness_linear_set(struct bt_mesh_model *model, +static int light_lightness_linear_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1525,6 +1580,7 @@ static void light_lightness_linear_set(struct bt_mesh_model *model, uint16_t linear; int64_t now; struct light_lightness_state *state = model->user_data; + int rc; linear = net_buf_simple_pull_le16(buf); tid = net_buf_simple_pull_u8(buf); @@ -1534,8 +1590,7 @@ static void light_lightness_linear_set(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - light_lightness_linear_get(model, ctx, buf); - return; + return light_lightness_linear_get(model, ctx, buf); } switch (buf->om_len) { @@ -1546,13 +1601,13 @@ static void light_lightness_linear_set(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -1567,9 +1622,9 @@ static void light_lightness_linear_set(struct bt_mesh_model *model, if (state->target_linear != state->linear) { light_lightness_linear_tt_values(state, tt, delay); } else { - light_lightness_linear_get(model, ctx, buf); + rc = light_lightness_linear_get(model, ctx, buf); light_lightness_linear_publish(model); - return; + return rc; } /* For Instantaneous Transition */ @@ -1581,9 +1636,10 @@ static void light_lightness_linear_set(struct bt_mesh_model *model, light_lightness_linear_get(model, ctx, buf); light_lightness_linear_publish(model); light_lightness_linear_handler(state); + return 0; } -static void light_lightness_last_get(struct bt_mesh_model *model, +static int light_lightness_last_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1598,9 +1654,10 @@ static void light_lightness_last_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -static void light_lightness_default_get(struct bt_mesh_model *model, +static int light_lightness_default_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1616,9 +1673,10 @@ static void light_lightness_default_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -static void light_lightness_range_get(struct bt_mesh_model *model, +static int light_lightness_range_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1637,18 +1695,19 @@ static void light_lightness_range_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } /* Light Lightness Setup Server message handlers */ -static void light_lightness_default_publish(struct bt_mesh_model *model) +static int light_lightness_default_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct light_lightness_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, @@ -1659,9 +1718,10 @@ static void light_lightness_default_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } -static void light_lightness_default_set_unack(struct bt_mesh_model *model, +static int light_lightness_default_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1679,26 +1739,37 @@ static void light_lightness_default_set_unack(struct bt_mesh_model *model, save_on_flash(LIGHTNESS_TEMP_DEF_STATE); } - light_lightness_default_publish(model); + return light_lightness_default_publish(model); } -static void light_lightness_default_set(struct bt_mesh_model *model, +static int light_lightness_default_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - light_lightness_default_set_unack(model, ctx, buf); - light_lightness_default_get(model, ctx, buf); - light_lightness_default_publish(model); + int rc; + rc = light_lightness_default_set_unack(model, ctx, buf); + if (rc) { + return rc; + } + rc = light_lightness_default_get(model, ctx, buf); + if (rc) { + return rc; + } + rc = light_lightness_default_publish(model); + if (rc) { + return rc; + } + return 0; } -static void light_lightness_range_publish(struct bt_mesh_model *model) +static int light_lightness_range_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct light_lightness_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_LIGHTNESS_RANGE_STATUS); @@ -1710,6 +1781,7 @@ static void light_lightness_range_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } static bool light_lightness_range_setunack(struct bt_mesh_model *model, @@ -1748,27 +1820,36 @@ static bool light_lightness_range_setunack(struct bt_mesh_model *model, return true; } -static void light_lightness_range_set_unack(struct bt_mesh_model *model, +static int light_lightness_range_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (light_lightness_range_setunack(model, ctx, buf) == true) { - light_lightness_range_publish(model); + return light_lightness_range_publish(model); } + return 0; } -static void light_lightness_range_set(struct bt_mesh_model *model, +static int light_lightness_range_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + int rc; if (light_lightness_range_setunack(model, ctx, buf) == true) { - light_lightness_range_get(model, ctx, buf); - light_lightness_range_publish(model); + rc = light_lightness_range_get(model, ctx, buf); + if (rc) { + return rc; + } + rc = light_lightness_range_publish(model); + if (rc) { + return rc; + } } + return 0; } /* Light Lightness Client message handlers */ -static void light_lightness_status(struct bt_mesh_model *model, +static int light_lightness_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1780,9 +1861,10 @@ static void light_lightness_status(struct bt_mesh_model *model, net_buf_simple_pull_le16(buf)); printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf)); } + return 0; } -static void light_lightness_linear_status(struct bt_mesh_model *model, +static int light_lightness_linear_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1794,25 +1876,28 @@ static void light_lightness_linear_status(struct bt_mesh_model *model, net_buf_simple_pull_le16(buf)); printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf)); } + return 0; } -static void light_lightness_last_status(struct bt_mesh_model *model, +static int light_lightness_last_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { printk("Acknownledgement from LIGHT_LIGHTNESS_SRV (Last)\n"); printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf)); + return 0; } -static void light_lightness_default_status(struct bt_mesh_model *model, +static int light_lightness_default_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { printk("Acknownledgement from LIGHT_LIGHTNESS_SRV (Default)\n"); printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf)); + return 0; } -static void light_lightness_range_status(struct bt_mesh_model *model, +static int light_lightness_range_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1820,10 +1905,11 @@ static void light_lightness_range_status(struct bt_mesh_model *model, printk("Status Code = %02x\n", net_buf_simple_pull_u8(buf)); printk("Range Min = %04x\n", net_buf_simple_pull_le16(buf)); printk("Range Max = %04x\n", net_buf_simple_pull_le16(buf)); + return 0; } /* Light CTL Server message handlers */ -static void light_ctl_get(struct bt_mesh_model *model, +static int light_ctl_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1846,16 +1932,17 @@ static void light_ctl_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -void light_ctl_publish(struct bt_mesh_model *model) +int light_ctl_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct light_ctl_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_STATUS); @@ -1877,9 +1964,10 @@ void light_ctl_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } -static void light_ctl_set_unack(struct bt_mesh_model *model, +static int light_ctl_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1895,7 +1983,7 @@ static void light_ctl_set_unack(struct bt_mesh_model *model, tid = net_buf_simple_pull_u8(buf); if (temp < TEMP_MIN || temp > TEMP_MAX) { - return; + return 0; } now = k_uptime_get(); @@ -1903,7 +1991,7 @@ static void light_ctl_set_unack(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - return; + return 0; } switch (buf->om_len) { @@ -1914,13 +2002,13 @@ static void light_ctl_set_unack(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -1947,7 +2035,7 @@ static void light_ctl_set_unack(struct bt_mesh_model *model, light_ctl_tt_values(state, tt, delay); } else { light_ctl_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -1960,9 +2048,10 @@ static void light_ctl_set_unack(struct bt_mesh_model *model, state->transition->just_started = true; light_ctl_publish(model); light_ctl_handler(state); + return 0; } -static void light_ctl_set(struct bt_mesh_model *model, +static int light_ctl_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -1978,7 +2067,7 @@ static void light_ctl_set(struct bt_mesh_model *model, tid = net_buf_simple_pull_u8(buf); if (temp < TEMP_MIN || temp > TEMP_MAX) { - return; + return 0; } now = k_uptime_get(); @@ -1987,7 +2076,7 @@ static void light_ctl_set(struct bt_mesh_model *model, state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { light_ctl_get(model, ctx, buf); - return; + return 0; } switch (buf->om_len) { @@ -1998,13 +2087,13 @@ static void light_ctl_set(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -2032,7 +2121,7 @@ static void light_ctl_set(struct bt_mesh_model *model, } else { light_ctl_get(model, ctx, buf); light_ctl_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -2046,14 +2135,16 @@ static void light_ctl_set(struct bt_mesh_model *model, light_ctl_get(model, ctx, buf); light_ctl_publish(model); light_ctl_handler(state); + return 0; } -static void light_ctl_temp_range_get(struct bt_mesh_model *model, +static int light_ctl_temp_range_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 5 + 4); struct light_ctl_state *state = model->user_data; + int rc; state->status_code = RANGE_SUCCESSFULLY_UPDATED; @@ -2062,42 +2153,47 @@ static void light_ctl_temp_range_get(struct bt_mesh_model *model, net_buf_simple_add_le16(msg, state->temp_range_min); net_buf_simple_add_le16(msg, state->temp_range_max); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { printk("Unable to send LightCTL Temp Range Status response\n"); } os_mbuf_free_chain(msg); + return rc; } -static void light_ctl_default_get(struct bt_mesh_model *model, +static int light_ctl_default_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 6 + 4); struct light_ctl_state *state = model->user_data; + int rc; bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_DEFAULT_STATUS); net_buf_simple_add_le16(msg, state->lightness_def); net_buf_simple_add_le16(msg, state->temp_def); net_buf_simple_add_le16(msg, state->delta_uv_def); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { printk("Unable to send LightCTL Default Status response\n"); } os_mbuf_free_chain(msg); + return rc; } /* Light CTL Setup Server message handlers */ -static void light_ctl_default_publish(struct bt_mesh_model *model) +static int light_ctl_default_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct light_ctl_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_DEFAULT_STATUS); @@ -2109,6 +2205,7 @@ static void light_ctl_default_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } static bool light_ctl_default_setunack(struct bt_mesh_model *model, @@ -2147,33 +2244,35 @@ static bool light_ctl_default_setunack(struct bt_mesh_model *model, return true; } -static void light_ctl_default_set_unack(struct bt_mesh_model *model, +static int light_ctl_default_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (light_ctl_default_setunack(model, ctx, buf) == true) { - light_ctl_default_publish(model); + return light_ctl_default_publish(model); } + return 0; } -static void light_ctl_default_set(struct bt_mesh_model *model, +static int light_ctl_default_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (light_ctl_default_setunack(model, ctx, buf) == true) { light_ctl_default_get(model, ctx, buf); - light_ctl_default_publish(model); + return light_ctl_default_publish(model); } + return 0; } -static void light_ctl_temp_range_publish(struct bt_mesh_model *model) +static int light_ctl_temp_range_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct light_ctl_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_TEMP_RANGE_STATUS); @@ -2185,6 +2284,7 @@ static void light_ctl_temp_range_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } static bool light_ctl_temp_range_setunack(struct bt_mesh_model *model, @@ -2225,27 +2325,29 @@ static bool light_ctl_temp_range_setunack(struct bt_mesh_model *model, return true; } -static void light_ctl_temp_range_set_unack(struct bt_mesh_model *model, +static int light_ctl_temp_range_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (light_ctl_temp_range_setunack(model, ctx, buf) == true) { - light_ctl_temp_range_publish(model); + return light_ctl_temp_range_publish(model); } + return 0; } -static void light_ctl_temp_range_set(struct bt_mesh_model *model, +static int light_ctl_temp_range_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { if (light_ctl_temp_range_setunack(model, ctx, buf) == true) { light_ctl_temp_range_get(model, ctx, buf); - light_ctl_temp_range_publish(model); + return light_ctl_temp_range_publish(model); } + return 0; } /* Light CTL Client message handlers */ -static void light_ctl_status(struct bt_mesh_model *model, +static int light_ctl_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -2261,9 +2363,10 @@ static void light_ctl_status(struct bt_mesh_model *model, net_buf_simple_pull_le16(buf)); printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf)); } + return 0; } -static void light_ctl_temp_range_status(struct bt_mesh_model *model, +static int light_ctl_temp_range_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -2271,9 +2374,10 @@ static void light_ctl_temp_range_status(struct bt_mesh_model *model, printk("Status Code = %02x\n", net_buf_simple_pull_u8(buf)); printk("Range Min = %04x\n", net_buf_simple_pull_le16(buf)); printk("Range Max = %04x\n", net_buf_simple_pull_le16(buf)); + return 0; } -static void light_ctl_temp_status(struct bt_mesh_model *model, +static int light_ctl_temp_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -2290,9 +2394,10 @@ static void light_ctl_temp_status(struct bt_mesh_model *model, net_buf_simple_pull_le16(buf)); printk("Remaining Time = %02x\n", net_buf_simple_pull_u8(buf)); } + return 0; } -static void light_ctl_default_status(struct bt_mesh_model *model, +static int light_ctl_default_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -2300,10 +2405,11 @@ static void light_ctl_default_status(struct bt_mesh_model *model, printk("Lightness = %04x\n", net_buf_simple_pull_le16(buf)); printk("Temperature = %04x\n", net_buf_simple_pull_le16(buf)); printk("Delta UV = %04x\n", net_buf_simple_pull_le16(buf)); + return 0; } /* Light CTL Temp. Server message handlers */ -static void light_ctl_temp_get(struct bt_mesh_model *model, +static int light_ctl_temp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -2326,16 +2432,17 @@ static void light_ctl_temp_get(struct bt_mesh_model *model, } os_mbuf_free_chain(msg); + return 0; } -void light_ctl_temp_publish(struct bt_mesh_model *model) +int light_ctl_temp_publish(struct bt_mesh_model *model) { int err; struct os_mbuf *msg = model->pub->msg; struct light_ctl_state *state = model->user_data; if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return; + return 0; } bt_mesh_model_msg_init(msg, BT_MESH_MODEL_LIGHT_CTL_TEMP_STATUS); @@ -2353,9 +2460,10 @@ void light_ctl_temp_publish(struct bt_mesh_model *model) if (err) { printk("bt_mesh_model_publish err %d\n", err); } + return err; } -static void light_ctl_temp_set_unack(struct bt_mesh_model *model, +static int light_ctl_temp_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -2370,7 +2478,7 @@ static void light_ctl_temp_set_unack(struct bt_mesh_model *model, tid = net_buf_simple_pull_u8(buf); if (temp < TEMP_MIN || temp > TEMP_MAX) { - return; + return 0; } now = k_uptime_get(); @@ -2378,7 +2486,7 @@ static void light_ctl_temp_set_unack(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - return; + return 0; } switch (buf->om_len) { @@ -2389,13 +2497,13 @@ static void light_ctl_temp_set_unack(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -2420,7 +2528,7 @@ static void light_ctl_temp_set_unack(struct bt_mesh_model *model, light_ctl_temp_tt_values(state, tt, delay); } else { light_ctl_temp_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -2432,9 +2540,10 @@ static void light_ctl_temp_set_unack(struct bt_mesh_model *model, state->transition->just_started = true; light_ctl_temp_publish(model); light_ctl_temp_handler(state); + return 0; } -static void light_ctl_temp_set(struct bt_mesh_model *model, +static int light_ctl_temp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -2449,7 +2558,7 @@ static void light_ctl_temp_set(struct bt_mesh_model *model, tid = net_buf_simple_pull_u8(buf); if (temp < TEMP_MIN || temp > TEMP_MAX) { - return; + return 0; } now = k_uptime_get(); @@ -2457,8 +2566,7 @@ static void light_ctl_temp_set(struct bt_mesh_model *model, state->last_src_addr == ctx->addr && state->last_dst_addr == ctx->recv_dst && (now - state->last_msg_timestamp <= K_SECONDS(6))) { - light_ctl_temp_get(model, ctx, buf); - return; + return light_ctl_temp_get(model, ctx, buf); } switch (buf->om_len) { @@ -2469,13 +2577,13 @@ static void light_ctl_temp_set(struct bt_mesh_model *model, case 0x02: /* Optional fields are available */ tt = net_buf_simple_pull_u8(buf); if ((tt & 0x3F) == 0x3F) { - return; + return 0; } delay = net_buf_simple_pull_u8(buf); break; default: - return; + return 0; } *ptr_counter = 0; @@ -2501,7 +2609,7 @@ static void light_ctl_temp_set(struct bt_mesh_model *model, } else { light_ctl_temp_get(model, ctx, buf); light_ctl_temp_publish(model); - return; + return 0; } /* For Instantaneous Transition */ @@ -2514,6 +2622,7 @@ static void light_ctl_temp_set(struct bt_mesh_model *model, light_ctl_temp_get(model, ctx, buf); light_ctl_temp_publish(model); light_ctl_temp_handler(state); + return 0; } /* message handlers (End) */ diff --git a/apps/blemesh_models_example_2/src/device_composition.h b/apps/blemesh_models_example_2/src/device_composition.h index d0f054ee2b..1b5bf5f72a 100644 --- a/apps/blemesh_models_example_2/src/device_composition.h +++ b/apps/blemesh_models_example_2/src/device_composition.h @@ -167,11 +167,11 @@ extern struct bt_mesh_model s0_models[]; extern const struct bt_mesh_comp comp; -void gen_onoff_publish(struct bt_mesh_model *model); -void gen_level_publish(struct bt_mesh_model *model); -void light_lightness_publish(struct bt_mesh_model *model); -void light_lightness_linear_publish(struct bt_mesh_model *model); -void light_ctl_publish(struct bt_mesh_model *model); -void light_ctl_temp_publish(struct bt_mesh_model *model); +int gen_onoff_publish(struct bt_mesh_model *model); +int gen_level_publish(struct bt_mesh_model *model); +int light_lightness_publish(struct bt_mesh_model *model); +int light_lightness_linear_publish(struct bt_mesh_model *model); +int light_ctl_publish(struct bt_mesh_model *model); +int light_ctl_temp_publish(struct bt_mesh_model *model); #endif From 039e3ca80e7e333dc9b726c6f4da1eaebdfe3265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 25 Oct 2021 10:09:15 +0200 Subject: [PATCH 236/306] host/mesh: add preprocessor directives for persistent storage After `settings` module was split among others it's necessary to compile methods depending on peristent storage only when it's enabled. --- nimble/host/mesh/src/access.c | 6 ++++++ nimble/host/mesh/src/app_keys.c | 14 ++++++++++++++ nimble/host/mesh/src/cfg.c | 5 ++++- nimble/host/mesh/src/heartbeat.c | 6 +++++- nimble/host/mesh/src/net.c | 10 ++++++++++ nimble/host/mesh/src/pb_gatt_srv.c | 2 +- nimble/host/mesh/src/proxy_msg.c | 2 +- nimble/host/mesh/src/proxy_msg.h | 2 +- nimble/host/mesh/src/rpl.c | 16 ++++++++++++++++ nimble/host/mesh/src/subnet.c | 18 +++++++++++++++++- nimble/host/mesh/src/transport.c | 6 ++++++ 11 files changed, 81 insertions(+), 6 deletions(-) diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index 28402885c6..e498910dbd 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -875,6 +875,7 @@ bool bt_mesh_model_is_extended(struct bt_mesh_model *model) return model->flags & BT_MESH_MOD_EXTENDED; } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static int mod_set_bind(struct bt_mesh_model *mod, char *val) { int len, err, i; @@ -1246,6 +1247,7 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, } return err; } +#endif static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) @@ -1276,6 +1278,7 @@ void bt_mesh_model_settings_commit(void) bt_mesh_model_foreach(commit_mod, NULL); } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct conf_handler bt_mesh_sig_mod_conf_handler = { .ch_name = "bt_mesh", .ch_get = NULL, @@ -1291,9 +1294,11 @@ static struct conf_handler bt_mesh_vnd_mod_conf_handler = { .ch_commit = NULL, .ch_export = NULL, }; +#endif void bt_mesh_access_init(void) { + #if MYNEWT_VAL(BLE_MESH_SETTINGS) int rc; rc = conf_register(&bt_mesh_sig_mod_conf_handler); @@ -1304,4 +1309,5 @@ void bt_mesh_access_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_access conf"); + #endif } \ No newline at end of file diff --git a/nimble/host/mesh/src/app_keys.c b/nimble/host/mesh/src/app_keys.c index e13245af8a..97589968d9 100644 --- a/nimble/host/mesh/src/app_keys.c +++ b/nimble/host/mesh/src/app_keys.c @@ -76,6 +76,7 @@ static struct app_key *app_get(uint16_t app_idx) static void clear_app_key(uint16_t app_idx) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char path[20]; int err; @@ -88,10 +89,12 @@ static void clear_app_key(uint16_t app_idx) } else { BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx); } +#endif } static void store_app_key(uint16_t app_idx) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) const struct app_key *app; struct app_key_val key; char path[20]; @@ -120,8 +123,10 @@ static void store_app_key(uint16_t app_idx) } else { BT_DBG("Stored AppKey %s value"); } +#endif } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct app_key_update *app_key_update_find(uint16_t key_idx, struct app_key_update **free_slot) { @@ -146,9 +151,11 @@ static struct app_key_update *app_key_update_find(uint16_t key_idx, return match; } +#endif static void update_app_key_settings(uint16_t app_idx, bool store) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) struct app_key_update *update, *free_slot; uint8_t clear = store ? 0U : 1U; @@ -175,6 +182,7 @@ static void update_app_key_settings(uint16_t app_idx, bool store) free_slot->clear = clear; bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_APP_KEYS_PENDING); +#endif } static void app_key_evt(struct app_key *app, enum bt_mesh_key_evt evt) @@ -629,6 +637,7 @@ void bt_mesh_app_keys_reset(void) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static int app_key_set(int argc, char **argv, char *val) { struct app_key_val key; @@ -662,6 +671,7 @@ static int app_key_set(int argc, char **argv, char *val) return 0; } +#endif void bt_mesh_app_key_pending_store(void) { @@ -684,6 +694,7 @@ void bt_mesh_app_key_pending_store(void) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct conf_handler bt_mesh_app_key_conf_handler = { .ch_name = "bt_mesh", .ch_get = NULL, @@ -691,13 +702,16 @@ static struct conf_handler bt_mesh_app_key_conf_handler = { .ch_commit = NULL, .ch_export = NULL, }; +#endif void bt_mesh_app_key_init(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) int rc; rc = conf_register(&bt_mesh_app_key_conf_handler); SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_app_key conf"); +#endif } \ No newline at end of file diff --git a/nimble/host/mesh/src/cfg.c b/nimble/host/mesh/src/cfg.c index e866cb7911..ec68cac7b7 100644 --- a/nimble/host/mesh/src/cfg.c +++ b/nimble/host/mesh/src/cfg.c @@ -250,6 +250,7 @@ bool bt_mesh_fixed_group_match(uint16_t addr) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static int cfg_set(int argc, char **argv, char *val) { struct cfg_val cfg; @@ -329,7 +330,6 @@ static void store_pending_cfg(void) } } - void bt_mesh_cfg_pending_store(void) { if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { @@ -346,15 +346,18 @@ static struct conf_handler bt_mesh_cfg_conf_handler = { .ch_commit = NULL, .ch_export = NULL, }; +#endif void bt_mesh_cfg_default_set(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) int rc; rc = conf_register(&bt_mesh_cfg_conf_handler); SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_settings conf"); +#endif bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL; bt_mesh.net_xmit = diff --git a/nimble/host/mesh/src/heartbeat.c b/nimble/host/mesh/src/heartbeat.c index 1d249b4899..50cfdb6d5b 100644 --- a/nimble/host/mesh/src/heartbeat.c +++ b/nimble/host/mesh/src/heartbeat.c @@ -371,6 +371,7 @@ void bt_mesh_hb_resume(void) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static int hb_pub_set(int argc, char **argv, char *val) { struct bt_mesh_hb_pub pub; @@ -447,14 +448,17 @@ static struct conf_handler bt_mesh_hb_pub_conf_handler = { .ch_set = hb_pub_set, .ch_commit = NULL, .ch_export = NULL, - }; +}; +#endif void bt_mesh_hb_pub_init(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) int rc; rc = conf_register(&bt_mesh_hb_pub_conf_handler); SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_hb_pub conf"); +#endif } \ No newline at end of file diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index f994bcc747..a36160d778 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -148,22 +148,26 @@ static void msg_cache_add(struct bt_mesh_net_rx *rx) static void store_iv(bool only_duration) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_IV_PENDING); if (!only_duration) { /* Always update Seq whenever IV changes */ bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); } +#endif } static void store_seq(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) if (CONFIG_BT_MESH_SEQ_STORE_RATE > 1 && (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)) { return; } bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); +#endif } int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], @@ -898,6 +902,7 @@ static void ivu_refresh(struct ble_npl_event *work) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static int net_set(int argc, char **argv, char *val) { struct net_val net; @@ -1031,11 +1036,13 @@ static struct conf_handler bt_mesh_seq_conf_handler = { .ch_commit = NULL, .ch_export = NULL, }; +#endif void bt_mesh_net_init(void) { int rc; +#if MYNEWT_VAL(BLE_MESH_SETTINGS) rc = conf_register(&bt_mesh_net_conf_handler); SYSINIT_PANIC_ASSERT_MSG(rc == 0, @@ -1051,6 +1058,7 @@ void bt_mesh_net_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_seq conf"); +#endif k_work_init_delayable(&bt_mesh.ivu_timer, ivu_refresh); @@ -1068,6 +1076,7 @@ void bt_mesh_net_init(void) assert(rc == 0); } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static void clear_iv(void) { int err; @@ -1204,6 +1213,7 @@ void bt_mesh_net_clear(void) bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); } +#endif void bt_mesh_net_settings_commit(void) { diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index d04948262d..94dcd174a8 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -104,7 +104,7 @@ static void proxy_msg_recv(struct bt_mesh_proxy_role *role) static bool service_registered; -static ssize_t gatt_recv(uint16_t conn_handle, uint16_t attr_handle, +static int gatt_recv(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { const uint8_t *data = ctxt->om->om_data; diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c index 91b4ba694a..1ed3acdc51 100644 --- a/nimble/host/mesh/src/proxy_msg.c +++ b/nimble/host/mesh/src/proxy_msg.c @@ -50,7 +50,7 @@ static uint8_t bufs[CONFIG_BT_MAX_CONN * CONFIG_BT_MESH_PROXY_MSG_LEN]; static struct bt_mesh_proxy_role roles[CONFIG_BT_MAX_CONN]; -ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, +int bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, const void *buf, uint16_t len) { const uint8_t *data = buf; diff --git a/nimble/host/mesh/src/proxy_msg.h b/nimble/host/mesh/src/proxy_msg.h index befdb1f351..0e06c5cae5 100644 --- a/nimble/host/mesh/src/proxy_msg.h +++ b/nimble/host/mesh/src/proxy_msg.h @@ -55,7 +55,7 @@ struct bt_mesh_proxy_client { struct ble_npl_callout send_beacons; }; -ssize_t bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, +int bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, const void *buf, uint16_t len); int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, struct os_mbuf *msg, void (*end)(uint16_t, void *), void *user_data); diff --git a/nimble/host/mesh/src/rpl.c b/nimble/host/mesh/src/rpl.c index bf5743e417..6fd08b2feb 100644 --- a/nimble/host/mesh/src/rpl.c +++ b/nimble/host/mesh/src/rpl.c @@ -34,6 +34,7 @@ static inline int rpl_idx(const struct bt_mesh_rpl *rpl) static void clear_rpl(struct bt_mesh_rpl *rpl) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) int err; char path[18]; @@ -51,10 +52,12 @@ static void clear_rpl(struct bt_mesh_rpl *rpl) (void)memset(rpl, 0, sizeof(*rpl)); atomic_clear_bit(store, rpl_idx(rpl)); +#endif } static void schedule_rpl_store(struct bt_mesh_rpl *entry, bool force) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) atomic_set_bit(store, rpl_idx(entry)); bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); if (force @@ -64,11 +67,14 @@ static void schedule_rpl_store(struct bt_mesh_rpl *entry, bool force) ) { bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); } +#endif } static void schedule_rpl_clear(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); +#endif } void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, @@ -160,6 +166,7 @@ void bt_mesh_rpl_clear(void) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src) { int i; @@ -186,6 +193,7 @@ static struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src) return NULL; } +#endif void bt_mesh_rpl_reset(void) { @@ -214,6 +222,7 @@ void bt_mesh_rpl_reset(void) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static int rpl_set(int argc, char **argv, char *val) { struct bt_mesh_rpl *entry; @@ -268,9 +277,11 @@ static int rpl_set(int argc, char **argv, char *val) (unsigned) entry->seq, entry->old_iv); return 0; } +#endif static void store_rpl(struct bt_mesh_rpl *entry) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char buf[BT_SETTINGS_SIZE(sizeof(struct rpl_val))]; struct rpl_val rpl; char path[18]; @@ -302,6 +313,7 @@ static void store_rpl(struct bt_mesh_rpl *entry) } else { BT_DBG("Stored RPL"); } +#endif } static void store_pending_rpl(struct bt_mesh_rpl *rpl) @@ -345,6 +357,7 @@ void bt_mesh_rpl_pending_store(uint16_t addr) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct conf_handler bt_mesh_rpl_conf_handler = { .ch_name = "bt_mesh", .ch_get = NULL, @@ -352,13 +365,16 @@ static struct conf_handler bt_mesh_rpl_conf_handler = { .ch_commit = NULL, .ch_export = NULL, }; +#endif void bt_mesh_rpl_init(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) int rc; rc = conf_register(&bt_mesh_rpl_conf_handler); SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_rpl conf"); +#endif } \ No newline at end of file diff --git a/nimble/host/mesh/src/subnet.c b/nimble/host/mesh/src/subnet.c index 71d7b3d1ab..14aa8623f7 100644 --- a/nimble/host/mesh/src/subnet.c +++ b/nimble/host/mesh/src/subnet.c @@ -73,6 +73,7 @@ static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) static void clear_net_key(uint16_t net_idx) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char path[20]; int err; @@ -85,10 +86,12 @@ static void clear_net_key(uint16_t net_idx) } else { BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx); } +#endif } static void store_subnet(uint16_t net_idx) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) const struct bt_mesh_subnet *sub; struct net_key_val key; char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))]; @@ -123,8 +126,10 @@ static void store_subnet(uint16_t net_idx) } else { BT_DBG("Stored NetKey"); } +#endif } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct net_key_update *net_key_update_find(uint16_t key_idx, struct net_key_update **free_slot) { @@ -149,6 +154,7 @@ static struct net_key_update *net_key_update_find(uint16_t key_idx, return match; } +#endif uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub) { @@ -167,6 +173,7 @@ uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub) static void update_subnet_settings(uint16_t net_idx, bool store) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) struct net_key_update *update, *free_slot; uint8_t clear = store ? 0U : 1U; @@ -194,12 +201,15 @@ static void update_subnet_settings(uint16_t net_idx, bool store) free_slot->clear = clear; bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_NET_KEYS_PENDING); +#endif } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) void bt_mesh_subnet_store(uint16_t net_idx) { update_subnet_settings(net_idx, true); } +#endif static void key_refresh(struct bt_mesh_subnet *sub, uint8_t new_phase) { @@ -800,6 +810,7 @@ bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct os_mbuf *in, return false; } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static int net_key_set(int argc, char **argv, char *val) { struct net_key_val key; @@ -828,6 +839,7 @@ static int net_key_set(int argc, char **argv, char *val) net_idx, key.kr_phase, key.val[0], (key.kr_phase != BT_MESH_KR_NORMAL) ? key.val[1] : NULL); } +#endif void bt_mesh_subnet_pending_store(void) { @@ -850,20 +862,24 @@ void bt_mesh_subnet_pending_store(void) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct conf_handler bt_mesh_net_key_conf_handler = { .ch_name = "bt_mesh", .ch_get = NULL, .ch_set = net_key_set, .ch_commit = NULL, .ch_export = NULL, - }; +}; +#endif void bt_mesh_net_key_init(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) int rc; rc = conf_register(&bt_mesh_net_key_conf_handler); SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_net_key conf"); +#endif } \ No newline at end of file diff --git a/nimble/host/mesh/src/transport.c b/nimble/host/mesh/src/transport.c index b1d41dbf53..d563c9fa05 100644 --- a/nimble/host/mesh/src/transport.c +++ b/nimble/host/mesh/src/transport.c @@ -1638,7 +1638,9 @@ void bt_mesh_rx_reset(void) static void store_va_label(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_VA_PENDING); +#endif } void bt_mesh_trans_reset(void) @@ -1787,6 +1789,7 @@ uint8_t *bt_mesh_va_label_get(uint16_t addr) } #if CONFIG_BT_MESH_LABEL_COUNT > 0 +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct virtual_addr *bt_mesh_va_get(uint16_t index) { if (index >= ARRAY_SIZE(virtual_addrs)) { @@ -1901,15 +1904,18 @@ static struct conf_handler bt_mesh_va_conf_handler = { .ch_commit = NULL, .ch_export = NULL, }; +#endif void bt_mesh_va_init(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) int rc; rc = conf_register(&bt_mesh_va_conf_handler); SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_hb_pub conf"); +#endif } #else From 04d723ed0595fa9c36696fcfd63ae61714a84a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 25 Oct 2021 13:03:08 +0200 Subject: [PATCH 237/306] host/mesh: define Low Latency mode for non-NimBLE controller This fixes build for porting --- nimble/host/mesh/src/adv_legacy.c | 8 +++++++- porting/examples/linux_blemesh/include/syscfg/syscfg.h | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index ab8a921619..837eaa736d 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -22,6 +22,12 @@ /* Convert from ms to 0.625ms units */ #define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) +#if (MYNEWT_VAL(BSP_NRF51) && !MYNEWT_VAL(BLE_CONTROLLER)) +#define CONFIG_BT_CTLR_LOW_LAT 1 +#else +#define CONFIG_BT_CTLR_LOW_LAT 0 +#endif + /* Pre-5.0 controllers enforce a minimum interval of 100ms * whereas 5.0+ controllers can go down to 20ms. */ @@ -83,7 +89,7 @@ static inline void adv_send(struct os_mbuf *buf) * amount of scan window duration to compensate for the blocked * advertising events. */ - if (MYNEWT_VAL(BSP_NRF51)) { + if (CONFIG_BT_CTLR_LOW_LAT) { duration += BT_MESH_SCAN_WINDOW_MS; } #endif diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index 2fd5232b94..e132d4c065 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -1013,6 +1013,11 @@ #define MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_SIZE (4) #endif + +#ifndef MYNEWT_VAL_BSP_NRF51 +#define MYNEWT_VAL_BSP_NRF51 (0) +#endif + /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_PB_ADV #define MYNEWT_VAL_BLE_MESH_PB_ADV (1) From 7914dbd984780c9b1adecf18030398faf6a0beb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 25 Oct 2021 13:05:59 +0200 Subject: [PATCH 238/306] porting/blemesh: add missing defs Added defs included in Mesh sync --- .../linux_blemesh/include/syscfg/syscfg.h | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index e132d4c065..61cc3f20e2 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -1013,6 +1013,37 @@ #define MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_SIZE (4) #endif +#ifndef MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN +#if MYNEWT_VAL_BLE_MESH_PB_GATT +#define MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN (66) +#elif MYNEWT_VAL_BLE_MESH_GATT_PROXY +#define MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN (33) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE +#define MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG +#define MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT +#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT (0x800000) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY +#define MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_ADV_EXT +#define MYNEWT_VAL_BLE_MESH_ADV_EXT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_ADV_LEGACY +#define MYNEWT_VAL_BLE_MESH_ADV_LEGACY (1) +#endif #ifndef MYNEWT_VAL_BSP_NRF51 #define MYNEWT_VAL_BSP_NRF51 (0) From 6f6fc995e58d190cd42f5afb38be947fbc1002d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 25 Oct 2021 13:06:41 +0200 Subject: [PATCH 239/306] host/mesh: make mesh adv thread method name consistent with porting --- nimble/host/mesh/src/adv_legacy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 837eaa736d..e9d41a1cdf 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -131,7 +131,7 @@ static inline void adv_send(struct os_mbuf *buf) } void -adv_thread(void *args) +mesh_adv_thread(void *args) { static struct ble_npl_event *ev; struct os_mbuf *buf; @@ -222,7 +222,7 @@ void bt_mesh_adv_init(void) ble_npl_eventq_init(&adv_queue); #if MYNEWT - os_task_init(&adv_task, "mesh_adv", adv_thread, NULL, + os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL, MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER, g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); #endif From 5b71db8b5d91303f56aaf0e3b69682157fcc66be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Mon, 25 Oct 2021 14:41:21 +0200 Subject: [PATCH 240/306] host/mesh: fix mesh advertising thread Cleans up `bt_mesh_adv_queue` after sync --- nimble/host/mesh/src/adv.c | 3 ++- nimble/host/mesh/src/adv.h | 1 + nimble/host/mesh/src/adv_ext.c | 2 +- nimble/host/mesh/src/adv_legacy.c | 11 +++++------ 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/nimble/host/mesh/src/adv.c b/nimble/host/mesh/src/adv.c index 0b0205cbc2..c6274167a2 100644 --- a/nimble/host/mesh/src/adv.c +++ b/nimble/host/mesh/src/adv.c @@ -36,7 +36,8 @@ const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = { extern uint8_t g_mesh_addr_type; struct os_mbuf_pool adv_os_mbuf_pool; -static struct ble_npl_eventq bt_mesh_adv_queue; +struct ble_npl_eventq bt_mesh_adv_queue; + static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT]; static struct bt_mesh_adv *adv_alloc(int id) diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index 14be8f84f3..f531390d4d 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -29,6 +29,7 @@ /* We declare it as extern here to share it between 'adv' and 'adv_legacy' */ extern struct os_mbuf_pool adv_os_mbuf_pool; +extern struct ble_npl_eventq bt_mesh_adv_queue; enum bt_mesh_adv_type { diff --git a/nimble/host/mesh/src/adv_ext.c b/nimble/host/mesh/src/adv_ext.c index a531863f76..680a9ca77e 100644 --- a/nimble/host/mesh/src/adv_ext.c +++ b/nimble/host/mesh/src/adv_ext.c @@ -28,7 +28,7 @@ static struct ble_gap_ext_adv_params adv_param = { }; bool ext_adv_configured = false; -static struct ble_npl_eventq bt_mesh_adv_queue; +struct ble_npl_eventq bt_mesh_adv_queue; enum { /** Controller is currently advertising */ diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index e9d41a1cdf..0eece40fa2 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -48,7 +48,6 @@ static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; static struct os_mempool adv_buf_mempool; -static struct ble_npl_eventq adv_queue; static inline void adv_send(struct os_mbuf *buf) { @@ -143,7 +142,7 @@ mesh_adv_thread(void *args) while (1) { #if (MYNEWT_VAL(BLE_MESH_PROXY)) - ev = ble_npl_eventq_get(&adv_queue, 0); + ev = ble_npl_eventq_get(&bt_mesh_adv_queue, 0); while (!ev) { if (bt_mesh_is_provisioned()) { if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { @@ -160,11 +159,11 @@ mesh_adv_thread(void *args) timeout = ble_npl_time_ms_to_ticks32(timeout); } - ev = ble_npl_eventq_get(&adv_queue, timeout); + ev = ble_npl_eventq_get(&bt_mesh_adv_queue, timeout); bt_le_adv_stop(); } #else - ev = ble_npl_eventq_get(&adv_queue, BLE_NPL_TIME_FOREVER); + ev = ble_npl_eventq_get(&bt_mesh_adv_queue, BLE_NPL_TIME_FOREVER); #endif if (!ev || !ble_npl_event_get_arg(ev)) { @@ -191,7 +190,7 @@ void bt_mesh_adv_update(void) BT_DBG(""); - ble_npl_eventq_put(&adv_queue, &ev); + ble_npl_eventq_put(&bt_mesh_adv_queue, &ev); } void bt_mesh_adv_buf_ready(void) @@ -219,7 +218,7 @@ void bt_mesh_adv_init(void) MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)); assert(rc == 0); - ble_npl_eventq_init(&adv_queue); + ble_npl_eventq_init(&bt_mesh_adv_queue); #if MYNEWT os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL, From 649fad1f2163a2d6f5c0e4998fe131fc51d6f1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 26 Oct 2021 08:50:22 +0200 Subject: [PATCH 241/306] host/mesh: fix mesh_adv_thread Solved issues with adv_timeout. --- nimble/host/mesh/src/adv_legacy.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 0eece40fa2..0698c356c7 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -48,6 +48,7 @@ static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; static struct os_mempool adv_buf_mempool; +static int32_t adv_timeout; static inline void adv_send(struct os_mbuf *buf) { @@ -134,9 +135,6 @@ mesh_adv_thread(void *args) { static struct ble_npl_event *ev; struct os_mbuf *buf; -#if (MYNEWT_VAL(BLE_MESH_PROXY)) - int32_t timeout; -#endif BT_DBG("started"); @@ -144,22 +142,21 @@ mesh_adv_thread(void *args) #if (MYNEWT_VAL(BLE_MESH_PROXY)) ev = ble_npl_eventq_get(&bt_mesh_adv_queue, 0); while (!ev) { + /* Adv timeout may be set by a call from proxy + * to bt_mesh_adv_start: + */ + adv_timeout = K_FOREVER; if (bt_mesh_is_provisioned()) { if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - timeout = bt_mesh_proxy_adv_start(); - BT_DBG("Proxy Advertising up to %d ms", (int) timeout); + (void)bt_mesh_proxy_adv_start(); + BT_DBG("Proxy Advertising up to %d ms", (int) adv_timeout); } } else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - timeout = bt_mesh_pb_gatt_adv_start(); - BT_DBG("PB-GATT Advertising up to %d ms", (int) timeout); - } - - // FIXME: should we redefine K_SECONDS macro instead in glue? - if (timeout != K_FOREVER) { - timeout = ble_npl_time_ms_to_ticks32(timeout); + (void)bt_mesh_pb_gatt_adv_start(); + BT_DBG("PB-GATT Advertising up to %d ms", (int) adv_timeout); } - ev = ble_npl_eventq_get(&bt_mesh_adv_queue, timeout); + ev = ble_npl_eventq_get(&bt_mesh_adv_queue, adv_timeout); bt_le_adv_stop(); } #else @@ -244,6 +241,7 @@ int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) { + adv_timeout = duration; return bt_le_adv_start(param, duration, ad, ad_len, sd, sd_len); } #endif \ No newline at end of file From d22137b28603e210ce314c3989c7040cd11879d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 28 Oct 2021 15:14:23 +0200 Subject: [PATCH 242/306] host/mesh: fix Extended Adv for mesh Fixes build and advertising. --- nimble/host/mesh/src/adv.c | 5 +++ nimble/host/mesh/src/adv.h | 2 + nimble/host/mesh/src/adv_ext.c | 65 +++++++++++-------------------- nimble/host/mesh/src/adv_legacy.c | 5 +-- 4 files changed, 30 insertions(+), 47 deletions(-) diff --git a/nimble/host/mesh/src/adv.c b/nimble/host/mesh/src/adv.c index c6274167a2..d7a8c123c9 100644 --- a/nimble/host/mesh/src/adv.c +++ b/nimble/host/mesh/src/adv.c @@ -38,6 +38,11 @@ extern uint8_t g_mesh_addr_type; struct os_mbuf_pool adv_os_mbuf_pool; struct ble_npl_eventq bt_mesh_adv_queue; +os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( + MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), + BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; +struct os_mempool adv_buf_mempool; + static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT]; static struct bt_mesh_adv *adv_alloc(int id) diff --git a/nimble/host/mesh/src/adv.h b/nimble/host/mesh/src/adv.h index f531390d4d..aa83a47b86 100644 --- a/nimble/host/mesh/src/adv.h +++ b/nimble/host/mesh/src/adv.h @@ -30,6 +30,8 @@ /* We declare it as extern here to share it between 'adv' and 'adv_legacy' */ extern struct os_mbuf_pool adv_os_mbuf_pool; extern struct ble_npl_eventq bt_mesh_adv_queue; +extern struct os_mempool adv_buf_mempool; +extern os_membuf_t adv_buf_mem[]; enum bt_mesh_adv_type { diff --git a/nimble/host/mesh/src/adv_ext.c b/nimble/host/mesh/src/adv_ext.c index 680a9ca77e..07c693dea1 100644 --- a/nimble/host/mesh/src/adv_ext.c +++ b/nimble/host/mesh/src/adv_ext.c @@ -28,7 +28,6 @@ static struct ble_gap_ext_adv_params adv_param = { }; bool ext_adv_configured = false; -struct ble_npl_eventq bt_mesh_adv_queue; enum { /** Controller is currently advertising */ @@ -273,13 +272,13 @@ static void send_pending_adv(struct ble_npl_event *work) /* No more pending buffers */ if (bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - err = bt_mesh_pb_gatt_adv_start(); - BT_DBG("Proxy Advertising"); - } + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + err = bt_mesh_proxy_adv_start(); + BT_DBG("Proxy Advertising"); + } } else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - err = bt_mesh_prov_adv_start(); - BT_DBG("PB-GATT Advertising"); + err = bt_mesh_pb_gatt_adv_start(); + BT_DBG("PB-GATT Advertising"); } if (!err) { @@ -301,47 +300,27 @@ void bt_mesh_adv_buf_ready(void) void bt_mesh_adv_init(void) { - k_work_init_delayable(&adv.work, send_pending_adv); -} + int rc; -int bt_mesh_adv_enable(void) -{ - struct ble_gap_ext_adv_params params; - ble_addr_t addr; - int rc; + rc = os_mempool_init(&adv_buf_mempool, MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), + BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, + adv_buf_mem, "adv_buf_pool"); + assert(rc == 0); - if (ext_adv_configured) { - /* Already initialized */ - return 0; - } + rc = os_mbuf_pool_init(&adv_os_mbuf_pool, &adv_buf_mempool, + BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, + MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)); + assert(rc == 0); - params.itvl_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS); - params.itvl_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS); + ble_npl_eventq_init(&bt_mesh_adv_queue); - if (MYNEWT_VAL(BLE_MESH_DEBUG_USE_ID_ADDR)) { - params.own_addr_type = BLE_OWN_ADDR_PUBLIC; - } else { - params.own_addr_type = BLE_OWN_ADDR_RANDOM; - /* set random (NRPA) address for instance */ - rc = ble_hs_id_gen_rnd(1, &addr); - assert (rc == 0); - - rc = ble_gap_ext_adv_set_addr(BT_ID_DEFAULT, &addr ); - assert (rc == 0); - } - - params.primary_phy = BLE_HCI_LE_PHY_1M; - params.secondary_phy = BLE_HCI_LE_PHY_1M; - params.tx_power = 127; - params.sid = 4; - - rc = ble_gap_ext_adv_configure(BT_ID_DEFAULT, ¶ms, NULL, - ble_mesh_ext_adv_event_handler, NULL); - if (rc == 0) { - ext_adv_configured = true; - } + k_work_init_delayable(&adv.work, send_pending_adv); +} - return rc; +int bt_mesh_adv_enable(void) +{ + /* No need to initialize extended advertiser instance here */ + return 0; } int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 0698c356c7..afbfc2fcde 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -44,10 +44,7 @@ static int adv_initialized = false; OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); struct os_task adv_task; #endif -static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( - MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; -static struct os_mempool adv_buf_mempool; + static int32_t adv_timeout; static inline void adv_send(struct os_mbuf *buf) From 1cc3b1daae87c8679b5e9824b4e544245fc0eae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 29 Oct 2021 14:18:53 +0200 Subject: [PATCH 243/306] host/mesh: post-sync fixes part 2 --- nimble/host/mesh/src/adv_legacy.c | 45 ++++++++-------- nimble/host/mesh/src/friend.c | 17 +++--- nimble/host/mesh/src/glue.c | 27 +++++----- nimble/host/mesh/src/mesh.c | 4 ++ nimble/host/mesh/src/pb_gatt.c | 9 +--- nimble/host/mesh/src/pb_gatt_srv.c | 57 ++++++++++++-------- nimble/host/mesh/src/pb_gatt_srv.h | 11 +++- nimble/host/mesh/src/proxy.h | 9 ++++ nimble/host/mesh/src/proxy_msg.c | 33 +++++++++--- nimble/host/mesh/src/proxy_msg.h | 6 +-- nimble/host/mesh/src/proxy_srv.c | 86 ++++++++++++------------------ 11 files changed, 167 insertions(+), 137 deletions(-) diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index afbfc2fcde..94065bc9bf 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -105,6 +105,8 @@ static inline void adv_send(struct os_mbuf *buf) param.itvl_max = param.itvl_min; param.conn_mode = BLE_GAP_CONN_MODE_NON; + int64_t time = k_uptime_get(); + err = bt_le_adv_start(¶m, duration, &ad, 1, NULL, 0); @@ -124,7 +126,7 @@ static inline void adv_send(struct os_mbuf *buf) return; } - BT_DBG("Advertising stopped"); + BT_DBG("Advertising stopped (%u ms)", (uint32_t) k_uptime_delta(&time)); } void @@ -136,30 +138,29 @@ mesh_adv_thread(void *args) BT_DBG("started"); while (1) { -#if (MYNEWT_VAL(BLE_MESH_PROXY)) - ev = ble_npl_eventq_get(&bt_mesh_adv_queue, 0); - while (!ev) { - /* Adv timeout may be set by a call from proxy - * to bt_mesh_adv_start: - */ - adv_timeout = K_FOREVER; - if (bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - (void)bt_mesh_proxy_adv_start(); - BT_DBG("Proxy Advertising up to %d ms", (int) adv_timeout); + if (MYNEWT_VAL(BLE_MESH_GATT_SERVER)) { + ev = ble_npl_eventq_get(&bt_mesh_adv_queue, 0); + while (!ev) { + /* Adv timeout may be set by a call from proxy + * to bt_mesh_adv_start: + */ + adv_timeout = K_FOREVER; + if (bt_mesh_is_provisioned()) { + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + bt_mesh_proxy_adv_start(); + BT_DBG("Proxy Advertising up to %d ms", (int) adv_timeout); + } + } else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { + bt_mesh_pb_gatt_adv_start(); + BT_DBG("PB-GATT Advertising up to %d ms", (int) adv_timeout); } - } else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - (void)bt_mesh_pb_gatt_adv_start(); - BT_DBG("PB-GATT Advertising up to %d ms", (int) adv_timeout); - } - ev = ble_npl_eventq_get(&bt_mesh_adv_queue, adv_timeout); - bt_le_adv_stop(); + ev = ble_npl_eventq_get(&bt_mesh_adv_queue, adv_timeout); + bt_le_adv_stop(); + } + } else { + ev = ble_npl_eventq_get(&bt_mesh_adv_queue, BLE_NPL_TIME_FOREVER); } -#else - ev = ble_npl_eventq_get(&bt_mesh_adv_queue, BLE_NPL_TIME_FOREVER); -#endif - if (!ev || !ble_npl_event_get_arg(ev)) { continue; } diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 475fbd54e4..c7603a8d94 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -60,15 +60,16 @@ struct friend_pdu_info { }; static struct friend_adv { + struct bt_mesh_adv adv; uint16_t app_idx; } adv_pool[FRIEND_BUF_COUNT]; -#define FRIEND_ADV(buf) (*(struct friend_adv **)net_buf_user_data(buf)) +#define FRIEND_ADV(buf) CONTAINER_OF(BT_MESH_ADV(buf), struct friend_adv, adv) -static struct friend_adv *adv_alloc(int id) +static struct bt_mesh_adv *adv_alloc(int id) { adv_pool[id].app_idx = BT_MESH_KEY_UNUSED; - return &adv_pool[id]; + return &adv_pool[id].adv; } static bool friend_is_allocated(const struct bt_mesh_friend *frnd) @@ -308,13 +309,13 @@ static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd, { struct os_mbuf *buf; - buf = os_mbuf_get_pkthdr(&friend_os_mbuf_pool, BT_MESH_ADV_USER_DATA_SIZE); + buf = bt_mesh_adv_create_from_pool(&friend_os_mbuf_pool, adv_alloc, + BT_MESH_ADV_DATA, + FRIEND_XMIT, K_NO_WAIT); if (!buf) { return NULL; } - FRIEND_ADV(buf) = adv_alloc(net_buf_id(buf)); - net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */ if (info->ctl) { @@ -538,8 +539,8 @@ static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd, info.src = bt_mesh_primary_addr(); info.dst = frnd->lpn; - info.ctl = 1; - info.ttl = 0; + info.ctl = 1U; + info.ttl = 0U; memset(info.seq, 0, sizeof(info.seq)); diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index c7b2cc16f8..7a811210f3 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -105,6 +105,10 @@ net_buf_unref(struct os_mbuf *om) } adv = BT_MESH_ADV(om); + if (adv->started && adv->cb && adv->cb->end) { + adv->cb->end(0, adv->cb_data); + } + if (--adv->ref_cnt > 0) { return; } @@ -154,13 +158,13 @@ net_buf_simple_pull_le16(struct os_mbuf *om) uint32_t net_buf_simple_pull_le24(struct os_mbuf *om) { - uint16_t val; + uint32_t val; struct os_mbuf *old = om; - om = os_mbuf_pullup(om, sizeof(val)); + om = os_mbuf_pullup(om, 3); assert(om == old); val = get_le24(om->om_data); - os_mbuf_adj(om, sizeof(val)); + os_mbuf_adj(om, 3); return val; } @@ -445,7 +449,7 @@ k_work_cancel_delayable(struct k_work_delayable *w) void k_work_schedule(struct k_work_delayable *w, uint32_t ms) - { +{ uint32_t ticks; if (ble_npl_time_ms_to_ticks(ms, &ticks) != 0) { @@ -457,15 +461,12 @@ k_work_schedule(struct k_work_delayable *w, uint32_t ms) void k_work_reschedule(struct k_work_delayable *w, uint32_t ms) { - uint32_t ticks; + uint32_t ticks; - if (ble_npl_time_ms_to_ticks(ms, &ticks) != 0) { - assert(0); - } - if (ms == 0) { - ble_npl_callout_stop(&w->work); - } - ble_npl_callout_reset(&w->work, ticks); + if (ble_npl_time_ms_to_ticks(ms, &ticks) != 0) { + assert(0); + } + ble_npl_callout_reset(&w->work, ticks); } void @@ -825,7 +826,7 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, } } - err = ble_gap_adv_start(g_mesh_addr_type, NULL, duration, param, + err = ble_gap_adv_start(g_mesh_addr_type, NULL, BLE_HS_FOREVER, param, NULL, NULL); if (err) { BT_ERR("Advertising failed: err %d", err); diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index ccdfed37fd..6ab71e8b11 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -316,6 +316,10 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, return err; } +#if (MYNEWT_VAL(BLE_MESH_PROXY)) + bt_mesh_proxy_init(); +#endif + #if (MYNEWT_VAL(BLE_MESH_PROV)) err = bt_mesh_prov_init(prov); if (err) { diff --git a/nimble/host/mesh/src/pb_gatt.c b/nimble/host/mesh/src/pb_gatt.c index 6a215e1d3a..906abd2fc9 100644 --- a/nimble/host/mesh/src/pb_gatt.c +++ b/nimble/host/mesh/src/pb_gatt.c @@ -137,13 +137,6 @@ static int link_accept(const struct prov_bearer_cb *cb, void *cb_data) return 0; } -static void buf_send_end(uint16_t conn_handle, void *user_data) -{ - if (link.comp.cb) { - link.comp.cb(0, link.comp.cb_data); - } -} - static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb, void *cb_data) { @@ -156,7 +149,7 @@ static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb, k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); - return bt_mesh_pb_gatt_send(link.conn_handle, buf, buf_send_end, NULL); + return bt_mesh_pb_gatt_send(link.conn_handle, buf); } static void clear_tx(void) diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index 94dcd174a8..61fadb6fca 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -75,17 +75,11 @@ ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); static bool prov_fast_adv; -static struct { - uint16_t proxy_h; - uint16_t proxy_data_out_h; - uint16_t prov_h; - uint16_t prov_data_in_h; - uint16_t prov_data_out_h; -} svc_handles; +struct svc_handles svc_handles; +static atomic_t pending_notifications; static int gatt_send(uint16_t conn_handle, - const void *data, uint16_t len, - void (*end)(uint16_t, void *), void *user_data); + const void *data, uint16_t len); static struct bt_mesh_proxy_role *cli; @@ -104,15 +98,34 @@ static void proxy_msg_recv(struct bt_mesh_proxy_role *role) static bool service_registered; -static int gatt_recv(uint16_t conn_handle, uint16_t attr_handle, +static int gatt_recv_proxy(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { const uint8_t *data = ctxt->om->om_data; uint16_t len = ctxt->om->om_len; struct bt_mesh_proxy_client *client = find_client(conn_handle); + if (len < 1) { + BT_WARN("Too small Proxy PDU"); + return -EINVAL; + } + + if (PDU_TYPE(data) == BT_MESH_PROXY_PROV) { + BT_WARN("Proxy PDU type doesn't match GATT service"); + return -EINVAL; + } + + return bt_mesh_proxy_msg_recv(client->cli, data, len); +} + +static int gatt_recv_prov(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + const uint8_t *data = ctxt->om->om_data; + uint16_t len = ctxt->om->om_len; if (conn_handle != cli->conn_handle) { + BT_WARN("conn_handle != cli->conn_handle"); return -ENOTCONN; } @@ -121,12 +134,12 @@ static int gatt_recv(uint16_t conn_handle, uint16_t attr_handle, return -EINVAL; } - if (PDU_TYPE(data) == BT_MESH_PROXY_PROV) { + if (PDU_TYPE(data) != BT_MESH_PROXY_PROV) { BT_WARN("Proxy PDU type doesn't match GATT service"); return -EINVAL; } - return bt_mesh_proxy_msg_recv(client->cli, data, len); + return bt_mesh_proxy_msg_recv(cli, data, len); } void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err) @@ -180,7 +193,7 @@ int prov_ccc_write(uint16_t conn_handle, uint8_t type) return -ENOTCONN; } - if (type != BLE_GAP_EVENT_NOTIFY_RX) { + if (type != BLE_GAP_EVENT_SUBSCRIBE) { BT_WARN("Client wrote instead enabling notify"); return BT_GATT_ERR(EINVAL); } @@ -211,7 +224,7 @@ static const struct ble_gatt_svc_def svc_defs [] = { .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), .characteristics = (struct ble_gatt_chr_def[]) { { .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), - .access_cb = gatt_recv, + .access_cb = gatt_recv_proxy, .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, }, { .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), @@ -225,7 +238,7 @@ static const struct ble_gatt_svc_def svc_defs [] = { .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), .characteristics = (struct ble_gatt_chr_def[]) { { .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - .access_cb = gatt_recv, + .access_cb = gatt_recv_prov, .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, }, { .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), @@ -351,15 +364,14 @@ static const struct bt_data prov_ad[] = { BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), }; -int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, - void (*end)(uint16_t, void *), void *user_data) +int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf) { if (!cli || cli->conn_handle != conn_handle) { BT_ERR("No PB-GATT Client found"); return -ENOTCONN; } - return bt_mesh_proxy_msg_send(cli, BT_MESH_PROXY_PROV, buf, end, user_data); + return bt_mesh_proxy_msg_send(cli, BT_MESH_PROXY_PROV, buf); } static size_t gatt_prov_adv_create(struct bt_data prov_sd[1]) @@ -389,8 +401,7 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[1]) } static int gatt_send(uint16_t conn_handle, - const void *data, uint16_t len, - void (*end)(uint16_t, void *), void *user_data) + const void *data, uint16_t len) { struct os_mbuf *om; int err = 0; @@ -399,9 +410,11 @@ static int gatt_send(uint16_t conn_handle, om = ble_hs_mbuf_from_flat(data, len); assert(om); err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); - /* We do not pass cb into ble_gattc_notify_custom - execute it at the end */ + notify_complete(); - end(conn_handle, user_data); + if (!err) { + atomic_inc(&pending_notifications); + } return err; } diff --git a/nimble/host/mesh/src/pb_gatt_srv.h b/nimble/host/mesh/src/pb_gatt_srv.h index 364f53553e..816089477c 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.h +++ b/nimble/host/mesh/src/pb_gatt_srv.h @@ -8,8 +8,7 @@ #ifndef __PB_GATT_SRV_H__ #define __PB_GATT_SRV_H__ -int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf, - void (*end)(uint16_t, void *), void *user_data); +int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf); int bt_mesh_pb_gatt_enable(void); int bt_mesh_pb_gatt_disable(void); @@ -21,4 +20,12 @@ void resolve_svc_handles(void); int bt_mesh_pb_gatt_adv_start(void); +extern struct svc_handles { + uint16_t proxy_h; + uint16_t proxy_data_out_h; + uint16_t prov_h; + uint16_t prov_data_in_h; + uint16_t prov_data_out_h; +} svc_handles; + #endif /* __PB_GATT_SRV_H__ */ \ No newline at end of file diff --git a/nimble/host/mesh/src/proxy.h b/nimble/host/mesh/src/proxy.h index f84fa424f6..42530293e9 100644 --- a/nimble/host/mesh/src/proxy.h +++ b/nimble/host/mesh/src/proxy.h @@ -9,6 +9,8 @@ #ifndef __PROXY_H__ #define __PROXY_H__ +#include "mesh/slist.h" + #if CONFIG_BT_MESH_DEBUG_USE_ID_ADDR #define ADV_OPT_USE_IDENTITY BT_LE_ADV_OPT_USE_IDENTITY #else @@ -23,6 +25,12 @@ .itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, \ .itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, +struct bt_mesh_proxy_idle_cb { + sys_snode_t n; + void (*cb)(void); +}; + +void notify_complete(void); int bt_mesh_proxy_gatt_enable(void); int bt_mesh_proxy_gatt_disable(void); void bt_mesh_proxy_gatt_disconnect(void); @@ -38,5 +46,6 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst); void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr); int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg); +int bt_mesh_proxy_init(void); #endif /* __PROXY_H__ */ diff --git a/nimble/host/mesh/src/proxy_msg.c b/nimble/host/mesh/src/proxy_msg.c index 1ed3acdc51..44613af16d 100644 --- a/nimble/host/mesh/src/proxy_msg.c +++ b/nimble/host/mesh/src/proxy_msg.c @@ -50,6 +50,22 @@ static uint8_t bufs[CONFIG_BT_MAX_CONN * CONFIG_BT_MESH_PROXY_MSG_LEN]; static struct bt_mesh_proxy_role roles[CONFIG_BT_MAX_CONN]; +static void proxy_sar_timeout(struct ble_npl_event *work) +{ + struct bt_mesh_proxy_role *role; + int rc; + role = ble_npl_event_get_arg(work); + + + BT_WARN("Proxy SAR timeout"); + + if (role->conn_handle) { + rc = ble_gap_terminate(role->conn_handle, + BLE_ERR_REM_USER_CONN_TERM); + assert(rc == 0); + } +} + int bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, const void *buf, uint16_t len) { @@ -119,8 +135,7 @@ int bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, } int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, - struct os_mbuf *msg, - void (*end)(uint16_t, void *), void *user_data) + struct os_mbuf *msg) { int err; uint16_t mtu; @@ -133,11 +148,11 @@ int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, mtu = ble_att_mtu(conn_handle) - 3; if (mtu > msg->om_len) { net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); - return role->cb.send(conn_handle, msg->om_data, msg->om_len, end, user_data); + return role->cb.send(conn_handle, msg->om_data, msg->om_len); } net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); - err = role->cb.send(conn_handle, msg->om_data, mtu, NULL, NULL); + err = role->cb.send(conn_handle, msg->om_data, mtu); if (err) { return err; } @@ -146,7 +161,7 @@ int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, while (msg->om_len) { if (msg->om_len + 1 < mtu) { net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); - err = role->cb.send(conn_handle, msg->om_data, msg->om_len, end, user_data); + err = role->cb.send(conn_handle, msg->om_data, msg->om_len); if (err) { return err; } @@ -154,7 +169,7 @@ int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, } net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); - err = role->cb.send(conn_handle, msg->om_data, mtu, NULL, NULL); + err = role->cb.send(conn_handle, msg->om_data, mtu); if (err) { return err; } @@ -170,17 +185,21 @@ static void proxy_msg_init(struct bt_mesh_proxy_role *role) /* Check if buf has been allocated, in this way, we no longer need * to repeat the operation. */ - if (role->buf->om_data) { + if (role->buf != NULL) { net_buf_simple_reset(role->buf); return; } + role->buf = NET_BUF_SIMPLE(CONFIG_BT_MESH_PROXY_MSG_LEN); net_buf_simple_init_with_data(role->buf, &bufs[role->conn_handle * CONFIG_BT_MESH_PROXY_MSG_LEN], CONFIG_BT_MESH_PROXY_MSG_LEN); net_buf_simple_reset(role->buf); + + k_work_init_delayable(&role->sar_timer, proxy_sar_timeout); + k_work_add_arg_delayable(&role->sar_timer, role); } struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(uint16_t conn_handle, diff --git a/nimble/host/mesh/src/proxy_msg.h b/nimble/host/mesh/src/proxy_msg.h index 0e06c5cae5..349ebcdf4a 100644 --- a/nimble/host/mesh/src/proxy_msg.h +++ b/nimble/host/mesh/src/proxy_msg.h @@ -26,8 +26,7 @@ struct bt_mesh_proxy_role; typedef int (*proxy_send_cb_t)(uint16_t conn_handle, - const void *data, uint16_t len, - void (*end)(uint16_t, void *), void *user_data); + const void *data, uint16_t len); typedef void (*proxy_recv_cb_t)(struct bt_mesh_proxy_role *role); @@ -57,8 +56,7 @@ struct bt_mesh_proxy_client { int bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, const void *buf, uint16_t len); -int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, - struct os_mbuf *msg, void (*end)(uint16_t, void *), void *user_data); +int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, struct os_mbuf *msg); void bt_mesh_proxy_msg_init(struct bt_mesh_proxy_role *role); void bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role *role); struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(uint16_t conn_handle, diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index 7fa297fa7b..f634f400e2 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -9,6 +9,8 @@ #define MESH_LOG_MODULE BLE_MESH_PROXY_LOG +#include "mesh/slist.h" +#include "mesh/mesh.h" #include "../../host/src/ble_hs_priv.h" #include "services/gatt/ble_svc_gatt.h" @@ -43,19 +45,13 @@ (((w16) >> 0) & 0xFF), \ (((w16) >> 8) & 0xFF) -static struct { - uint16_t proxy_h; - uint16_t proxy_data_out_h; - uint16_t prov_h; - uint16_t prov_data_in_h; - uint16_t prov_data_out_h; -} svc_handles; +static sys_slist_t idle_waiters; +static atomic_t pending_notifications; static void proxy_send_beacons(struct ble_npl_event *work); static int proxy_send(uint16_t conn_handle, - const void *data, uint16_t len, - void (*end)(uint16_t, void *), void *user_data); + const void *data, uint16_t len); static struct bt_mesh_proxy_client clients[CONFIG_BT_MAX_CONN]; @@ -185,8 +181,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, return; } - err = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_CONFIG, - buf, NULL, NULL); + err = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_CONFIG, buf); if (err) { BT_ERR("Failed to send proxy cfg message (err %d)", err); } @@ -262,7 +257,7 @@ static void proxy_cfg(struct bt_mesh_proxy_role *role) } proxy_filter_recv(role->conn_handle, &rx, buf); - } +} static void proxy_msg_recv(struct bt_mesh_proxy_role *role) { @@ -293,8 +288,7 @@ static int beacon_send(struct bt_mesh_proxy_client *client, struct bt_mesh_subne net_buf_simple_init(buf, 1); bt_mesh_beacon_create(sub, buf); - rc = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_BEACON, buf, - NULL, NULL); + rc = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_BEACON, buf); os_mbuf_free_chain(buf); return rc; } @@ -434,7 +428,7 @@ static int node_id_adv(struct bt_mesh_subnet *sub, int32_t duration) memcpy(proxy_svc_data + 3, tmp + 8, 8); - err = bt_le_adv_start(&fast_adv_param, duration, node_id_ad, + err = bt_mesh_adv_start(&fast_adv_param, duration, node_id_ad, ARRAY_SIZE(node_id_ad), sd, 0); if (err) { BT_WARN("Failed to advertise using Node ID (err %d)", err); @@ -472,7 +466,7 @@ static int net_id_adv(struct bt_mesh_subnet *sub, int32_t duration) memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8); - err = bt_le_adv_start(&slow_adv_param, duration, net_id_ad, + err = bt_mesh_adv_start(&slow_adv_param, duration, net_id_ad, ARRAY_SIZE(net_id_ad), sd, 0); if (err) { BT_WARN("Failed to advertise using Network ID (err %d)", err); @@ -635,7 +629,7 @@ int bt_mesh_proxy_gatt_enable(void) BT_DBG(""); - if (bt_mesh_is_provisioned()) { + if (!bt_mesh_is_provisioned()) { return -ENOTSUP; } @@ -751,13 +745,6 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, return false; } -static void buf_send_end(uint16_t conn_handle, void *user_data) -{ - struct os_mbuf *buf = user_data; - - net_buf_unref(buf); -} - bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) { const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb; @@ -787,7 +774,7 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) net_buf_simple_add_mem(msg, buf->om_data, buf->om_len); err = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_NET_PDU, - msg, buf_send_end, net_buf_ref(buf)); + msg); adv_send_start(0, err, cb, cb_data); if (err) { @@ -808,23 +795,6 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) return relayed; } - -static void proxy_sar_timeout(struct ble_npl_event *work) -{ - struct bt_mesh_proxy_role *role; - int rc; - role = ble_npl_event_get_arg(work); - - - BT_WARN("Proxy SAR timeout"); - - if (role->conn_handle) { - rc = ble_gap_terminate(role->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); - } -} - static void gatt_connected(uint16_t conn_handle) { struct bt_mesh_proxy_client *client; @@ -880,9 +850,23 @@ static void gatt_disconnected(uint16_t conn_handle, uint8_t reason) } } +void notify_complete(void) +{ + sys_snode_t *n; + + if (atomic_dec(&pending_notifications) > 1) { + return; + } + + BT_DBG(""); + + while ((n = sys_slist_get(&idle_waiters))) { + CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb(); + } +} + static int proxy_send(uint16_t conn_handle, - const void *data, uint16_t len, - void (*end)(uint16_t, void *), void *user_data) + const void *data, uint16_t len) { struct os_mbuf *om; int err = 0; @@ -892,9 +876,12 @@ static int proxy_send(uint16_t conn_handle, om = ble_hs_mbuf_from_flat(data, len); assert(om); err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); - /* We do not pass cb into ble_gattc_notify_custom - execute it at the end */ + notify_complete(); + + if (!err) { + atomic_inc(&pending_notifications); + } - end(conn_handle, user_data); return err; } @@ -948,7 +935,7 @@ static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) { if ((event->type == BLE_GAP_EVENT_CONNECT) || - (event->type == BLE_GAP_EVENT_ADV_COMPLETE)) { + (event->type == BLE_GAP_EVENT_ADV_COMPLETE)) { ble_mesh_handle_connect(event, arg); } else if (event->type == BLE_GAP_EVENT_DISCONNECT) { gatt_disconnected(event->disconnect.conn.conn_handle, @@ -963,7 +950,7 @@ int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) proxy_ccc_write(event->subscribe.conn_handle); #endif } else if (event->subscribe.attr_handle == - svc_handles.prov_data_out_h) { + svc_handles.prov_data_out_h) { #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) prov_ccc_write(event->subscribe.conn_handle, event->type); #endif @@ -987,9 +974,6 @@ int bt_mesh_proxy_init(void) #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) k_work_init(&clients[i].send_beacons, proxy_send_beacons); #endif - - k_work_init_delayable(&clients[i].cli->sar_timer, proxy_sar_timeout); - k_work_add_arg_delayable(&clients[i].cli->sar_timer, &clients[i]); } resolve_svc_handles(); From 40dddfdfc368059c888305f8a904fab310dc2bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 9 Nov 2021 10:01:50 +0100 Subject: [PATCH 244/306] host/mesh: BLE_MESH_CDB should not require BLE_MESH_SETTINGS --- nimble/host/mesh/src/cdb.c | 22 ++++++++++++++++++++++ nimble/host/mesh/syscfg.yml | 1 - 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/cdb.c b/nimble/host/mesh/src/cdb.c index f92ece6090..98084ee3d0 100644 --- a/nimble/host/mesh/src/cdb.c +++ b/nimble/host/mesh/src/cdb.c @@ -159,6 +159,7 @@ static uint16_t find_lowest_free_addr(uint8_t num_elem) return addr; } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static int cdb_net_set(int argc, char *val) { struct net_val net; @@ -385,9 +386,11 @@ static int cdb_set(int argc, char **argv, char *name) BT_WARN("Unknown module key %s", name); return -ENOENT; } +#endif static void store_cdb_node(const struct bt_mesh_cdb_node *node) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char buf[BT_SETTINGS_SIZE(sizeof(struct node_val))]; struct node_val val; char path[30]; @@ -420,10 +423,12 @@ static void store_cdb_node(const struct bt_mesh_cdb_node *node) } else { BT_DBG("Stored Node %s value", path); } +#endif } static void clear_cdb_node(uint16_t addr) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char path[30]; int err; @@ -436,10 +441,12 @@ static void clear_cdb_node(uint16_t addr) } else { BT_DBG("Cleared Node 0x%04x", addr); } +#endif } static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))]; struct net_key_val key; char path[30]; @@ -468,10 +475,12 @@ static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) } else { BT_DBG("Stored Subnet value"); } +#endif } static void clear_cdb_subnet(uint16_t net_idx) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char path[30]; int err; @@ -484,10 +493,12 @@ static void clear_cdb_subnet(uint16_t net_idx) } else { BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx); } +#endif } static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; struct app_key_val key; char path[30]; @@ -508,10 +519,12 @@ static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app) } else { BT_DBG("Stored AppKey"); } +#endif } static void clear_cdb_app_key(uint16_t app_idx) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char path[30]; int err; @@ -522,6 +535,7 @@ static void clear_cdb_app_key(uint16_t app_idx) } else { BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx); } +#endif } static void schedule_cdb_store(int flag) @@ -964,6 +978,7 @@ void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key) static void clear_cdb_net(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) char path[30]; int err; @@ -974,10 +989,12 @@ static void clear_cdb_net(void) } else { BT_DBG("Cleared NetKeyIndex 0x%03x"); } +#endif } static void store_cdb_pending_net(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) struct net_val net; int err; char buf[BT_SETTINGS_SIZE(sizeof(struct net_val))]; @@ -1000,6 +1017,7 @@ static void store_cdb_pending_net(void) } else { BT_DBG("Stored Network value"); } +#endif } static void store_cdb_pending_nodes(void) @@ -1100,6 +1118,7 @@ void bt_mesh_cdb_pending_store(void) } } +#if MYNEWT_VAL(BLE_MESH_SETTINGS) static struct conf_handler bt_mesh_cdb_conf_handler = { .ch_name = "bt_mesh", .ch_get = NULL, @@ -1107,14 +1126,17 @@ static struct conf_handler bt_mesh_cdb_conf_handler = { .ch_commit = NULL, .ch_export = NULL, }; +#endif void bt_mesh_cdb_init(void) { +#if MYNEWT_VAL(BLE_MESH_SETTINGS) int rc; rc = conf_register(&bt_mesh_cdb_conf_handler); SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_net conf"); +#endif } #endif diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index eb79b04947..ae8190f859 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -63,7 +63,6 @@ syscfg.defs: description: > Mesh Configuration Database [EXPERIMENTAL] value: 0 - restrictions: BLE_MESH_SETTINGS BLE_MESH_CDB_NODE_COUNT: description: > From 5cc57dee076ca4613134e3b916e81f08ec4d59b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 9 Nov 2021 10:15:49 +0100 Subject: [PATCH 245/306] porting: fix blemesh build after mesh sync --- porting/examples/linux_blemesh/ble.c | 46 ++++++++++++------- .../linux_blemesh/include/syscfg/syscfg.h | 4 ++ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/porting/examples/linux_blemesh/ble.c b/porting/examples/linux_blemesh/ble.c index deaef5a462..7a64eac9ea 100644 --- a/porting/examples/linux_blemesh/ble.c +++ b/porting/examples/linux_blemesh/ble.c @@ -142,11 +142,12 @@ static struct bt_mesh_model_pub gen_onoff_pub; static uint8_t gen_on_off_state; static int16_t gen_level_state; -static void gen_onoff_status(struct bt_mesh_model *model, +static int gen_onoff_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { struct os_mbuf *msg = NET_BUF_SIMPLE(3); uint8_t *status; + int rc; console_printf("#mesh-onoff STATUS\n"); @@ -154,23 +155,25 @@ static void gen_onoff_status(struct bt_mesh_model *model, status = net_buf_simple_add(msg, 1); *status = gen_on_off_state; - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { console_printf("#mesh-onoff STATUS: send status failed\n"); } os_mbuf_free_chain(msg); + return rc; } -static void gen_onoff_get(struct bt_mesh_model *model, +static int gen_onoff_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { console_printf("#mesh-onoff GET\n"); - gen_onoff_status(model, ctx); + return gen_onoff_status(model, ctx); } -static void gen_onoff_set(struct bt_mesh_model *model, +static int gen_onoff_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -178,16 +181,17 @@ static void gen_onoff_set(struct bt_mesh_model *model, gen_on_off_state = buf->om_data[0]; - gen_onoff_status(model, ctx); + return gen_onoff_status(model, ctx); } -static void gen_onoff_set_unack(struct bt_mesh_model *model, +static int gen_onoff_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { console_printf("#mesh-onoff SET-UNACK\n"); gen_on_off_state = buf->om_data[0]; + return 0; } static const struct bt_mesh_model_op gen_onoff_op[] = { @@ -214,16 +218,17 @@ static void gen_level_status(struct bt_mesh_model *model, os_mbuf_free_chain(msg); } -static void gen_level_get(struct bt_mesh_model *model, +static int gen_level_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { console_printf("#mesh-level GET\n"); gen_level_status(model, ctx); + return 0; } -static void gen_level_set(struct bt_mesh_model *model, +static int gen_level_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -236,9 +241,10 @@ static void gen_level_set(struct bt_mesh_model *model, gen_level_state = level; console_printf("#mesh-level: level=%d\n", gen_level_state); + return 0; } -static void gen_level_set_unack(struct bt_mesh_model *model, +static int gen_level_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -249,9 +255,10 @@ static void gen_level_set_unack(struct bt_mesh_model *model, gen_level_state = level; console_printf("#mesh-level: level=%d\n", gen_level_state); + return 0; } -static void gen_delta_set(struct bt_mesh_model *model, +static int gen_delta_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -264,9 +271,10 @@ static void gen_delta_set(struct bt_mesh_model *model, gen_level_state += delta_level; console_printf("#mesh-level: level=%d\n", gen_level_state); + return 0; } -static void gen_delta_set_unack(struct bt_mesh_model *model, +static int gen_delta_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { @@ -277,18 +285,21 @@ static void gen_delta_set_unack(struct bt_mesh_model *model, gen_level_state += delta_level; console_printf("#mesh-level: level=%d\n", gen_level_state); + return 0; } -static void gen_move_set(struct bt_mesh_model *model, +static int gen_move_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + return 0; } -static void gen_move_set_unack(struct bt_mesh_model *model, +static int gen_move_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + return 0; } static const struct bt_mesh_model_op gen_level_op[] = { @@ -313,11 +324,12 @@ static struct bt_mesh_model root_models[] = { static struct bt_mesh_model_pub vnd_model_pub; -static void vnd_model_recv(struct bt_mesh_model *model, +static int vnd_model_recv(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(3); + int rc; console_printf("#vendor-model-recv\n"); @@ -327,11 +339,13 @@ static void vnd_model_recv(struct bt_mesh_model *model, bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_3(0x01, CID_VENDOR)); os_mbuf_append(msg, buf->om_data, buf->om_len); - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + rc = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (rc) { console_printf("#vendor-model-recv: send rsp failed\n"); } os_mbuf_free_chain(msg); + return rc; } static const struct bt_mesh_model_op vnd_model_op[] = { diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index 61cc3f20e2..5a5288f52e 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -1260,6 +1260,10 @@ #define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1) #endif +#ifndef MYNEWT_VAL_BLE_MESH_GATT_SERVER +#define MYNEWT_VAL_BLE_MESH_GATT_SERVER (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED #define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1) #endif From b9c20addd87f1692ea27600ede82f641c77315be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 9 Nov 2021 17:33:31 +0100 Subject: [PATCH 246/306] host/mesh: make all files have single empty line at the end --- nimble/host/mesh/include/mesh/cdb.h | 2 +- nimble/host/mesh/include/mesh/cfg.h | 2 +- nimble/host/mesh/include/mesh/heartbeat.h | 2 +- nimble/host/mesh/include/mesh/msg.h | 2 +- nimble/host/mesh/src/access.c | 2 +- nimble/host/mesh/src/adv_legacy.c | 2 +- nimble/host/mesh/src/app_keys.c | 2 +- nimble/host/mesh/src/app_keys.h | 2 +- nimble/host/mesh/src/cfg.c | 2 +- nimble/host/mesh/src/cfg.h | 2 +- nimble/host/mesh/src/heartbeat.c | 2 +- nimble/host/mesh/src/heartbeat.h | 2 +- nimble/host/mesh/src/light_model.c | 1 - nimble/host/mesh/src/model_cli.c | 1 - nimble/host/mesh/src/msg.c | 2 +- nimble/host/mesh/src/pb_gatt.c | 2 +- nimble/host/mesh/src/pb_gatt_srv.c | 2 +- nimble/host/mesh/src/pb_gatt_srv.h | 2 +- nimble/host/mesh/src/provisioner.h | 2 +- nimble/host/mesh/src/proxy_srv.c | 2 +- nimble/host/mesh/src/rpl.c | 2 +- nimble/host/mesh/src/rpl.h | 2 +- nimble/host/mesh/src/subnet.c | 2 +- nimble/host/mesh/src/subnet.h | 2 +- nimble/host/mesh/src/transport.h | 2 +- nimble/host/mesh/syscfg.yml | 2 +- 26 files changed, 24 insertions(+), 26 deletions(-) diff --git a/nimble/host/mesh/include/mesh/cdb.h b/nimble/host/mesh/include/mesh/cdb.h index 444fb5d295..fa691eb642 100644 --- a/nimble/host/mesh/include/mesh/cdb.h +++ b/nimble/host/mesh/include/mesh/cdb.h @@ -262,4 +262,4 @@ struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx); */ void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key); -#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */ \ No newline at end of file +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */ diff --git a/nimble/host/mesh/include/mesh/cfg.h b/nimble/host/mesh/include/mesh/cfg.h index 6fd69266ea..422ef3e661 100644 --- a/nimble/host/mesh/include/mesh/cfg.h +++ b/nimble/host/mesh/include/mesh/cfg.h @@ -488,4 +488,4 @@ ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max, * @} */ -#endif /* _BT_MESH_CFG_H_ */ \ No newline at end of file +#endif /* _BT_MESH_CFG_H_ */ diff --git a/nimble/host/mesh/include/mesh/heartbeat.h b/nimble/host/mesh/include/mesh/heartbeat.h index b9990f6fdc..2e4986094d 100644 --- a/nimble/host/mesh/include/mesh/heartbeat.h +++ b/nimble/host/mesh/include/mesh/heartbeat.h @@ -120,4 +120,4 @@ extern struct bt_mesh_hb_cb hb_cb; * @} */ -#endif /* _BLUETOOTH_MESH_HEARTBEAT_H_ */ \ No newline at end of file +#endif /* _BLUETOOTH_MESH_HEARTBEAT_H_ */ diff --git a/nimble/host/mesh/include/mesh/msg.h b/nimble/host/mesh/include/mesh/msg.h index 0cc00ff35b..e327545b12 100644 --- a/nimble/host/mesh/include/mesh/msg.h +++ b/nimble/host/mesh/include/mesh/msg.h @@ -222,4 +222,4 @@ bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, /** * @} */ -#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ */ \ No newline at end of file +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ */ diff --git a/nimble/host/mesh/src/access.c b/nimble/host/mesh/src/access.c index e498910dbd..2c07b09478 100644 --- a/nimble/host/mesh/src/access.c +++ b/nimble/host/mesh/src/access.c @@ -1310,4 +1310,4 @@ void bt_mesh_access_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_access conf"); #endif -} \ No newline at end of file +} diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 94065bc9bf..5bebff8960 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -242,4 +242,4 @@ int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, adv_timeout = duration; return bt_le_adv_start(param, duration, ad, ad_len, sd, sd_len); } -#endif \ No newline at end of file +#endif diff --git a/nimble/host/mesh/src/app_keys.c b/nimble/host/mesh/src/app_keys.c index 97589968d9..acc51f2a60 100644 --- a/nimble/host/mesh/src/app_keys.c +++ b/nimble/host/mesh/src/app_keys.c @@ -714,4 +714,4 @@ void bt_mesh_app_key_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_app_key conf"); #endif -} \ No newline at end of file +} diff --git a/nimble/host/mesh/src/app_keys.h b/nimble/host/mesh/src/app_keys.h index 1c560560de..3ef9ce7c8f 100644 --- a/nimble/host/mesh/src/app_keys.h +++ b/nimble/host/mesh/src/app_keys.h @@ -65,4 +65,4 @@ extern void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx, /** @brief Store pending application keys in persistent storage. */ void bt_mesh_app_key_pending_store(void); void bt_mesh_app_key_init(void); -#endif /* _BT_MESH_APP_KEYS_H_ */ \ No newline at end of file +#endif /* _BT_MESH_APP_KEYS_H_ */ diff --git a/nimble/host/mesh/src/cfg.c b/nimble/host/mesh/src/cfg.c index ec68cac7b7..282aefaf43 100644 --- a/nimble/host/mesh/src/cfg.c +++ b/nimble/host/mesh/src/cfg.c @@ -385,4 +385,4 @@ void bt_mesh_cfg_default_set(void) if (CONFIG_BT_MESH_FRIEND_ENABLED) { atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND); } -} \ No newline at end of file +} diff --git a/nimble/host/mesh/src/cfg.h b/nimble/host/mesh/src/cfg.h index 0bd7ad39c6..4901655f57 100644 --- a/nimble/host/mesh/src/cfg.h +++ b/nimble/host/mesh/src/cfg.h @@ -7,4 +7,4 @@ void bt_mesh_cfg_default_set(void); void bt_mesh_cfg_pending_store(void); -bool bt_mesh_fixed_group_match(uint16_t addr); \ No newline at end of file +bool bt_mesh_fixed_group_match(uint16_t addr); diff --git a/nimble/host/mesh/src/heartbeat.c b/nimble/host/mesh/src/heartbeat.c index 50cfdb6d5b..faf2f76611 100644 --- a/nimble/host/mesh/src/heartbeat.c +++ b/nimble/host/mesh/src/heartbeat.c @@ -461,4 +461,4 @@ void bt_mesh_hb_pub_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_hb_pub conf"); #endif -} \ No newline at end of file +} diff --git a/nimble/host/mesh/src/heartbeat.h b/nimble/host/mesh/src/heartbeat.h index 7fcfacf197..a036366637 100644 --- a/nimble/host/mesh/src/heartbeat.h +++ b/nimble/host/mesh/src/heartbeat.h @@ -40,4 +40,4 @@ uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *hb_pub); uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period); void bt_mesh_hb_sub_reset_count(void); void bt_mesh_hb_pub_pending_store(void); -void bt_mesh_hb_pub_init(void); \ No newline at end of file +void bt_mesh_hb_pub_init(void); diff --git a/nimble/host/mesh/src/light_model.c b/nimble/host/mesh/src/light_model.c index bc4792c637..e7199519bb 100644 --- a/nimble/host/mesh/src/light_model.c +++ b/nimble/host/mesh/src/light_model.c @@ -55,4 +55,3 @@ int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightne { return light_model_gen_level_set(model, lightness); } - diff --git a/nimble/host/mesh/src/model_cli.c b/nimble/host/mesh/src/model_cli.c index fd052426a1..22f9b99ee8 100644 --- a/nimble/host/mesh/src/model_cli.c +++ b/nimble/host/mesh/src/model_cli.c @@ -302,4 +302,3 @@ int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx, os_mbuf_free_chain(msg); return err; } - diff --git a/nimble/host/mesh/src/msg.c b/nimble/host/mesh/src/msg.c index f75082cb96..b788ffe1e9 100644 --- a/nimble/host/mesh/src/msg.c +++ b/nimble/host/mesh/src/msg.c @@ -81,4 +81,4 @@ bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, } return true; -} \ No newline at end of file +} diff --git a/nimble/host/mesh/src/pb_gatt.c b/nimble/host/mesh/src/pb_gatt.c index 906abd2fc9..9a0d7091e1 100644 --- a/nimble/host/mesh/src/pb_gatt.c +++ b/nimble/host/mesh/src/pb_gatt.c @@ -172,4 +172,4 @@ const struct prov_bearer pb_gatt = { .send = buf_send, .clear_tx = clear_tx, }; -#endif \ No newline at end of file +#endif diff --git a/nimble/host/mesh/src/pb_gatt_srv.c b/nimble/host/mesh/src/pb_gatt_srv.c index 61fadb6fca..ee37819d5c 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.c +++ b/nimble/host/mesh/src/pb_gatt_srv.c @@ -468,4 +468,4 @@ int bt_mesh_pb_gatt_adv_start(void) return err; } -#endif \ No newline at end of file +#endif diff --git a/nimble/host/mesh/src/pb_gatt_srv.h b/nimble/host/mesh/src/pb_gatt_srv.h index 816089477c..a5ebce5283 100644 --- a/nimble/host/mesh/src/pb_gatt_srv.h +++ b/nimble/host/mesh/src/pb_gatt_srv.h @@ -28,4 +28,4 @@ extern struct svc_handles { uint16_t prov_data_out_h; } svc_handles; -#endif /* __PB_GATT_SRV_H__ */ \ No newline at end of file +#endif /* __PB_GATT_SRV_H__ */ diff --git a/nimble/host/mesh/src/provisioner.h b/nimble/host/mesh/src/provisioner.h index ccda47efed..315bde299f 100644 --- a/nimble/host/mesh/src/provisioner.h +++ b/nimble/host/mesh/src/provisioner.h @@ -7,4 +7,4 @@ */ int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, - uint8_t attention_duration); \ No newline at end of file + uint8_t attention_duration); diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index f634f400e2..3507d0a45a 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -982,4 +982,4 @@ int bt_mesh_proxy_init(void) ble_gatts_svc_set_visibility(svc_handles.prov_h, 0); return 0; -} \ No newline at end of file +} diff --git a/nimble/host/mesh/src/rpl.c b/nimble/host/mesh/src/rpl.c index 6fd08b2feb..3a54414cea 100644 --- a/nimble/host/mesh/src/rpl.c +++ b/nimble/host/mesh/src/rpl.c @@ -377,4 +377,4 @@ void bt_mesh_rpl_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_rpl conf"); #endif -} \ No newline at end of file +} diff --git a/nimble/host/mesh/src/rpl.h b/nimble/host/mesh/src/rpl.h index b79ce887d4..9d110d9dab 100644 --- a/nimble/host/mesh/src/rpl.h +++ b/nimble/host/mesh/src/rpl.h @@ -29,4 +29,4 @@ bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, void bt_mesh_rpl_clear(void); void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx); -void bt_mesh_rpl_init(void); \ No newline at end of file +void bt_mesh_rpl_init(void); diff --git a/nimble/host/mesh/src/subnet.c b/nimble/host/mesh/src/subnet.c index 14aa8623f7..9108cc471f 100644 --- a/nimble/host/mesh/src/subnet.c +++ b/nimble/host/mesh/src/subnet.c @@ -882,4 +882,4 @@ void bt_mesh_net_key_init(void) SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failed to register bt_mesh_net_key conf"); #endif -} \ No newline at end of file +} diff --git a/nimble/host/mesh/src/subnet.h b/nimble/host/mesh/src/subnet.h index b3ac899272..b64177d364 100644 --- a/nimble/host/mesh/src/subnet.h +++ b/nimble/host/mesh/src/subnet.h @@ -203,4 +203,4 @@ void bt_mesh_subnet_store(uint16_t net_idx); /** @brief Store the pending Subnets in persistent storage. */ void bt_mesh_subnet_pending_store(void); void bt_mesh_net_key_init(void); -#endif /* _BLUETOOTH_MESH_SUBNET_H_ */ \ No newline at end of file +#endif /* _BLUETOOTH_MESH_SUBNET_H_ */ diff --git a/nimble/host/mesh/src/transport.h b/nimble/host/mesh/src/transport.h index a1af9a4bd8..ad7a59f236 100644 --- a/nimble/host/mesh/src/transport.h +++ b/nimble/host/mesh/src/transport.h @@ -103,4 +103,4 @@ uint8_t *bt_mesh_va_label_get(uint16_t addr); void bt_mesh_va_pending_store(void); -void bt_mesh_va_init(void); \ No newline at end of file +void bt_mesh_va_init(void); diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index ae8190f859..ca74cdff7d 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -979,4 +979,4 @@ syscfg.vals.BLE_MESH_PB_ADV: syscfg.vals.'BLE_MESH_PB_GATT': BLE_MESH_PROXY_MSG_LEN: 66 syscfg.vals.'BLE_MESH_GATT_PROXY': - BLE_MESH_PROXY_MSG_LEN: 33 \ No newline at end of file + BLE_MESH_PROXY_MSG_LEN: 33 From 3ac500716892d2395c616b8937030bc0aef9ee65 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 17 Nov 2021 11:53:47 +0100 Subject: [PATCH 247/306] targets: Rename pca10095 target Target nordic_pca10095-blehci was defined for nordic_pca10095_net bsp. Name suggested that nordic_pca10095 is being used. This just changes target name to avoid confusion. --- .../pkg.yml | 2 +- .../syscfg.yml | 0 .../target.yml | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename targets/{nordic_pca10095-blehci => nordic_pca10095_net-blehci}/pkg.yml (95%) rename targets/{nordic_pca10095-blehci => nordic_pca10095_net-blehci}/syscfg.yml (100%) rename targets/{nordic_pca10095-blehci => nordic_pca10095_net-blehci}/target.yml (100%) diff --git a/targets/nordic_pca10095-blehci/pkg.yml b/targets/nordic_pca10095_net-blehci/pkg.yml similarity index 95% rename from targets/nordic_pca10095-blehci/pkg.yml rename to targets/nordic_pca10095_net-blehci/pkg.yml index 3b72abe1bc..af24376a83 100644 --- a/targets/nordic_pca10095-blehci/pkg.yml +++ b/targets/nordic_pca10095_net-blehci/pkg.yml @@ -17,7 +17,7 @@ # under the License. # -pkg.name: targets/nordic_pca10095-blehci +pkg.name: targets/nordic_pca10095_net-blehci pkg.type: target pkg.description: Sample target for BLE controller on NRF5340 pkg.author: "Apache Mynewt " diff --git a/targets/nordic_pca10095-blehci/syscfg.yml b/targets/nordic_pca10095_net-blehci/syscfg.yml similarity index 100% rename from targets/nordic_pca10095-blehci/syscfg.yml rename to targets/nordic_pca10095_net-blehci/syscfg.yml diff --git a/targets/nordic_pca10095-blehci/target.yml b/targets/nordic_pca10095_net-blehci/target.yml similarity index 100% rename from targets/nordic_pca10095-blehci/target.yml rename to targets/nordic_pca10095_net-blehci/target.yml From 57eb4237aed7f2345eb970a9a5278ea2ee2f3280 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 19 Nov 2021 08:41:08 +0100 Subject: [PATCH 248/306] transport/usb: Drop events when not mounted If controller sends events before USB transport is ready event will be added to events queue but later interface initialization will clear queue without sending notification that event was sent to host. This change drops events generated by controller (most likely first NOP) if host is not connected yet. --- nimble/transport/usb/src/ble_hci_usb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nimble/transport/usb/src/ble_hci_usb.c b/nimble/transport/usb/src/ble_hci_usb.c index 3f87856f11..8160536b95 100644 --- a/nimble/transport/usb/src/ble_hci_usb.c +++ b/nimble/transport/usb/src/ble_hci_usb.c @@ -285,6 +285,11 @@ ble_hci_trans_ll_evt_tx(uint8_t *hci_ev) assert(hci_ev != NULL); + if (!tud_ready()) { + ble_hci_trans_buf_free(hci_ev); + return 0; + } + pkt = os_memblock_get(&ble_hci_pkt_pool); if (pkt == NULL) { ble_hci_trans_buf_free(hci_ev); From f44ab19694bfcb5824fef58471b586e20086992b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 18 Nov 2021 07:41:49 +0100 Subject: [PATCH 249/306] host/l2cap_sig: MPS on any channel cannot be decreased If reconfiguration request contains >1 CID and MPS value is reduced for only one of them this request should still fail. This is affecting L2CAP/ECFC/BI-04-C --- nimble/host/src/ble_l2cap_sig.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nimble/host/src/ble_l2cap_sig.c b/nimble/host/src/ble_l2cap_sig.c index 2a36161998..b74f88a4d0 100644 --- a/nimble/host/src/ble_l2cap_sig.c +++ b/nimble/host/src/ble_l2cap_sig.c @@ -796,10 +796,6 @@ ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle, if (chan[i]->peer_coc_mps > req->mps) { reduction_mps++; - if (reduction_mps > 1) { - rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED); - goto failed; - } } if (chan[i]->coc_tx.mtu > req->mtu) { @@ -808,6 +804,11 @@ ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle, } } + if (reduction_mps > 0 && cid_cnt > 1) { + rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED); + goto failed; + } + ble_hs_unlock(); for (i = 0; i < cid_cnt; i++) { From 3fe2fd9f578957b23d1dc0c987664c1989830a55 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 16 Nov 2021 13:17:20 +0100 Subject: [PATCH 250/306] Revert "l2cap: implement echo request-response procedure" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ddf8043d1b97f1600aa88c53bd935d0fc9b22c9c. Unfortunatelly this procedure is not allowed on LE transport. This is affecting L2CAP/LE/REJ/BI-02-C [Command Reject – Reserved PDU Codes] qualification test case. --- nimble/host/include/host/ble_l2cap.h | 22 ----- nimble/host/src/ble_l2cap.c | 7 -- nimble/host/src/ble_l2cap_sig.c | 120 +-------------------------- nimble/host/src/ble_l2cap_sig_priv.h | 2 - 4 files changed, 1 insertion(+), 150 deletions(-) diff --git a/nimble/host/include/host/ble_l2cap.h b/nimble/host/include/host/ble_l2cap.h index 5c5383b261..aef9682cc4 100644 --- a/nimble/host/include/host/ble_l2cap.h +++ b/nimble/host/include/host/ble_l2cap.h @@ -246,8 +246,6 @@ struct ble_l2cap_chan_info { typedef int ble_l2cap_event_fn(struct ble_l2cap_event *event, void *arg); -typedef void ble_l2cap_ping_fn(uint16_t conn_handle, uint32_t rtt_ms, - struct os_mbuf *om); uint16_t ble_l2cap_get_conn_handle(struct ble_l2cap_chan *chan); int ble_l2cap_create_server(uint16_t psm, uint16_t mtu, @@ -261,26 +259,6 @@ int ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx); int ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx); int ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info); -/** - * Send an ECHO_REQ packet over the L2CAP signalling channel for the given - * connection - * - * @param conn_handle Connection handle - * @param cb Function called once the corresponding ECHO_RSP is - * received. May be NULL. - * @param data User payload appended to the ECHO_REQ packet, may be - * NULL - * @param data_len Length of @p data in bytes. Set to 0 to omit any user - * payload - * - * @return 0 on success - * BLE_HS_EBADDATA if given payload is invalid - * BLE_HS_ENOMEM if request packet cannot be allocated - * BLE_HS_ENOTCONN if not connected - */ -int ble_l2cap_ping(uint16_t conn_handle, ble_l2cap_ping_fn cb, - const void *data, uint16_t data_len); - #ifdef __cplusplus } #endif diff --git a/nimble/host/src/ble_l2cap.c b/nimble/host/src/ble_l2cap.c index a2c5156339..2bc50e0e93 100644 --- a/nimble/host/src/ble_l2cap.c +++ b/nimble/host/src/ble_l2cap.c @@ -178,13 +178,6 @@ ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info return 0; } -int -ble_l2cap_ping(uint16_t conn_handle, ble_l2cap_ping_fn cb, - const void *data, uint16_t data_len) -{ - return ble_l2cap_sig_ping(conn_handle, cb, data, data_len); -} - int ble_l2cap_enhanced_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, diff --git a/nimble/host/src/ble_l2cap_sig.c b/nimble/host/src/ble_l2cap_sig.c index b74f88a4d0..f34c20b8bb 100644 --- a/nimble/host/src/ble_l2cap_sig.c +++ b/nimble/host/src/ble_l2cap_sig.c @@ -60,7 +60,6 @@ #define BLE_L2CAP_SIG_PROC_OP_RECONFIG 2 #define BLE_L2CAP_SIG_PROC_OP_DISCONNECT 3 #define BLE_L2CAP_SIG_PROC_OP_MAX 4 -#define BLE_L2CAP_SIG_PROC_OP_PING 5 #if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC) #define BLE_L2CAP_ECOC_MIN_MTU (64) @@ -98,10 +97,6 @@ struct ble_l2cap_sig_proc { uint16_t new_mtu; } reconfig; #endif - struct { - ble_l2cap_ping_fn *cb; - ble_npl_time_t time_sent; - } ping; }; }; @@ -117,10 +112,6 @@ static ble_l2cap_sig_rx_fn ble_l2cap_sig_rx_noop; static ble_l2cap_sig_rx_fn ble_l2cap_sig_update_req_rx; static ble_l2cap_sig_rx_fn ble_l2cap_sig_update_rsp_rx; static ble_l2cap_sig_rx_fn ble_l2cap_sig_rx_reject; -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 -static ble_l2cap_sig_rx_fn ble_l2cap_sig_echo_req; -static ble_l2cap_sig_rx_fn ble_l2cap_sig_echo_rsp; -#endif #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 static ble_l2cap_sig_rx_fn ble_l2cap_sig_coc_req_rx; @@ -154,10 +145,7 @@ static ble_l2cap_sig_rx_fn * const ble_l2cap_sig_dispatch[] = { [BLE_L2CAP_SIG_OP_CONFIG_RSP] = ble_l2cap_sig_rx_noop, [BLE_L2CAP_SIG_OP_DISCONN_REQ] = ble_l2cap_sig_disc_req_rx, [BLE_L2CAP_SIG_OP_DISCONN_RSP] = ble_l2cap_sig_disc_rsp_rx, -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 - [BLE_L2CAP_SIG_OP_ECHO_REQ] = ble_l2cap_sig_echo_req, - [BLE_L2CAP_SIG_OP_ECHO_RSP] = ble_l2cap_sig_echo_rsp, -#endif + [BLE_L2CAP_SIG_OP_ECHO_RSP] = ble_l2cap_sig_rx_noop, [BLE_L2CAP_SIG_OP_INFO_RSP] = ble_l2cap_sig_rx_noop, [BLE_L2CAP_SIG_OP_CREATE_CHAN_RSP] = ble_l2cap_sig_rx_noop, [BLE_L2CAP_SIG_OP_MOVE_CHAN_RSP] = ble_l2cap_sig_rx_noop, @@ -1651,58 +1639,6 @@ ble_l2cap_sig_disc_rsp_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, return 0; } -static int -ble_l2cap_sig_echo_req(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, - struct os_mbuf **om) -{ - void *rsp; - struct os_mbuf *txom; - struct ble_l2cap_sig_hdr *rsp_hdr; - int rc; - - /* we temporarily set size to 0 as we do not want to allocate additional - * space yet */ - rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_ECHO_RSP, - hdr->identifier, 0, &txom); - if (rsp == NULL) { - return BLE_HS_ENOMEM; - } - rc = os_mbuf_appendfrom(txom, *om, 0, OS_MBUF_PKTLEN(*om)); - if (rc != 0) { - os_mbuf_free_chain(txom); - return BLE_HS_ENOMEM; - } - /* after copying the request payload into the response, we need to adjust - * the size field in the header to the actual value */ - rsp_hdr = (struct ble_l2cap_sig_hdr *)txom->om_data; - rsp_hdr->length = htole16(OS_MBUF_PKTLEN(*om)); - - return ble_l2cap_sig_tx(conn_handle, txom); -} - -static int -ble_l2cap_sig_echo_rsp(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, - struct os_mbuf **om) -{ - struct ble_l2cap_sig_proc *proc; - uint32_t rtt_ms; - - proc = ble_l2cap_sig_proc_extract(conn_handle, BLE_L2CAP_SIG_PROC_OP_PING, - hdr->identifier); - if (proc == NULL) { - return BLE_HS_ENOENT; - } - - if (proc->ping.cb != NULL) { - ble_npl_time_t now = ble_npl_time_get(); - rtt_ms = ble_npl_time_ticks_to_ms32(now - proc->ping.time_sent); - proc->ping.cb(conn_handle, rtt_ms, *om); - ble_l2cap_sig_proc_free(proc); - } - - return 0; -} - int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan) { @@ -1940,60 +1876,6 @@ ble_l2cap_sig_extract_expired(struct ble_l2cap_sig_proc_list *dst_list) return next_exp_in; } -int -ble_l2cap_sig_ping(uint16_t conn_handle, ble_l2cap_ping_fn cb, - const void *data, uint16_t data_len) -{ - struct ble_l2cap_sig_proc *proc; - struct os_mbuf *txom; - void *req; - struct ble_l2cap_sig_hdr *hdr; - int rc; - - if ((data_len > 0) && (data == NULL)) { - return BLE_HS_EBADDATA; - } - - ble_hs_lock(); - proc = ble_l2cap_sig_proc_alloc(); - ble_hs_unlock(); - - if (!proc) { - return BLE_HS_ENOMEM; - } - - /* allocate and fill procedure context */ - proc->op = BLE_L2CAP_SIG_PROC_OP_PING; - proc->id = ble_l2cap_sig_next_id(); - proc->conn_handle = conn_handle; - proc->ping.cb = cb; - proc->ping.time_sent = ble_npl_time_get(); - - /* allocate signalling packet and copy payload into packet */ - req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_ECHO_REQ, - proc->id, 0, &txom); - if (req == NULL) { - ble_l2cap_sig_proc_free(proc); - return BLE_HS_ENOMEM; - } - if (data_len > 0) { - rc = os_mbuf_append(txom, data, data_len); - if (rc != 0) { - os_mbuf_free_chain(txom); - ble_l2cap_sig_proc_free(proc); - return BLE_HS_ENOMEM; - } - /* adjust the size field in the signalling header */ - hdr = (struct ble_l2cap_sig_hdr *)txom->om_data; - hdr->length = htole16(data_len); - } - - - rc = ble_l2cap_sig_tx(proc->conn_handle, txom); - ble_l2cap_sig_process_status(proc, rc); - return rc; -} - void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason) { diff --git a/nimble/host/src/ble_l2cap_sig_priv.h b/nimble/host/src/ble_l2cap_sig_priv.h index 55b37cd206..a698cd0d8f 100644 --- a/nimble/host/src/ble_l2cap_sig_priv.h +++ b/nimble/host/src/ble_l2cap_sig_priv.h @@ -172,8 +172,6 @@ ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], } #endif -int ble_l2cap_sig_ping(uint16_t conn_handle, ble_l2cap_ping_fn cb, - const void *data, uint16_t data_len); void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason); int32_t ble_l2cap_sig_timer(void); struct ble_l2cap_chan *ble_l2cap_sig_create_chan(uint16_t conn_handle); From 89ac67032e382a0c9a92b0798d1e877d252f6f00 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 9 Nov 2021 15:03:54 +0100 Subject: [PATCH 251/306] nimble/ll: Use 'vs' for vendor specific HCI consistently --- nimble/controller/include/controller/ble_ll.h | 2 +- nimble/controller/include/controller/ble_ll_ctrl.h | 6 +++--- nimble/controller/src/ble_ll_ctrl.c | 10 ++++++---- nimble/controller/src/ble_ll_hci_ev.c | 14 +++++++------- nimble/controller/syscfg.yml | 8 ++++++-- nimble/include/nimble/hci_common.h | 4 ++-- 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index 556883422c..dfda8cfeb4 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -48,7 +48,7 @@ extern "C" { if (hal_debugger_connected()) { \ assert(0);\ } else {\ - ble_ll_hci_ev_send_vendor_err(__FILE__, __LINE__); \ + ble_ll_hci_ev_send_vs_assert(__FILE__, __LINE__); \ while(1) {}\ }\ } diff --git a/nimble/controller/include/controller/ble_ll_ctrl.h b/nimble/controller/include/controller/ble_ll_ctrl.h index bd38e583e9..62e1a53569 100644 --- a/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/nimble/controller/include/controller/ble_ll_ctrl.h @@ -315,9 +315,9 @@ int ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status); void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm); void ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm); void ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm); -void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line); -void ble_ll_hci_ev_send_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, - void *pdu, size_t length); +void ble_ll_hci_ev_send_vs_assert(const char *file, uint32_t line); +void ble_ll_hci_ev_send_vs_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, + void *pdu, size_t length); 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); diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c index b6c6036ec1..94d73a9bb5 100644 --- a/nimble/controller/src/ble_ll_ctrl.c +++ b/nimble/controller/src/ble_ll_ctrl.c @@ -2469,8 +2469,9 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) opcode = dptr[2]; #if MYNEWT_VAL(BLE_LL_HCI_LLCP_TRACE) - ble_ll_hci_ev_send_llcp_trace(0x03, connsm->conn_handle, connsm->event_cntr, - &dptr[2], len); + ble_ll_hci_ev_send_vs_llcp_trace(0x03, connsm->conn_handle, + connsm->event_cntr, + &dptr[2], len); #endif /* @@ -2803,8 +2804,9 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) uint8_t opcode; #if MYNEWT_VAL(BLE_LL_HCI_LLCP_TRACE) - ble_ll_hci_ev_send_llcp_trace(0x04, connsm->conn_handle, connsm->event_cntr, - txpdu->om_data, txpdu->om_len); + ble_ll_hci_ev_send_vs_llcp_trace(0x04, connsm->conn_handle, + connsm->event_cntr, + txpdu->om_data, txpdu->om_len); #endif rc = 0; diff --git a/nimble/controller/src/ble_ll_hci_ev.c b/nimble/controller/src/ble_ll_hci_ev.c index ccbb1aa94d..9d6c39ecc0 100644 --- a/nimble/controller/src/ble_ll_hci_ev.c +++ b/nimble/controller/src/ble_ll_hci_ev.c @@ -493,9 +493,9 @@ ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm, uint8_t status, #endif void -ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line) +ble_ll_hci_ev_send_vs_assert(const char *file, uint32_t line) { - struct ble_hci_ev_vendor_debug *ev; + struct ble_hci_ev_vs_debug *ev; struct ble_hci_ev *hci_ev; unsigned int str_len; bool skip = true; @@ -510,7 +510,7 @@ ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line) hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_VENDOR_DEBUG; + hci_ev->opcode = BLE_HCI_EVCODE_VS_DEBUG; hci_ev->length = sizeof(*ev); ev = (void *) hci_ev->data; @@ -554,15 +554,15 @@ ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line) #if MYNEWT_VAL(BLE_LL_HCI_LLCP_TRACE) void -ble_ll_hci_ev_send_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, - void *pdu, size_t length) +ble_ll_hci_ev_send_vs_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, + void *pdu, size_t length) { - struct ble_hci_ev_vendor_debug *ev; + struct ble_hci_ev_vs_debug *ev; struct ble_hci_ev *hci_ev; hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_VENDOR_DEBUG; + hci_ev->opcode = BLE_HCI_EVCODE_VS_DEBUG; hci_ev->length = sizeof(*ev) + 8 + length; ev = (void *) hci_ev->data; diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index de6e688c6d..d60e18fc25 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -348,7 +348,7 @@ syscfg.defs: depending on specified HCI command length. value: 0 - BLE_LL_VND_EVENT_ON_ASSERT: + BLE_LL_HCI_VS_EVENT_ON_ASSERT: description: > This options enables controller to send a vendor-specific event on an assertion in controller code. The event contains file name and @@ -438,6 +438,10 @@ syscfg.defs: description: use BLE_LL_SCA instead value: 60 deprecated: 1 + BLE_LL_VND_EVENT_ON_ASSERT: + description: use BLE_LL_HCI_VS_EVENT_ON_ASSERT + value: 0 + deprecated: 1 # defunct settings (to be removed eventually) BLE_DEVICE: @@ -466,7 +470,7 @@ syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV: # Enable vendor event on assert in standalone build to make failed assertions in # controller code visible when connected to external host syscfg.vals.!BLE_HOST: - BLE_LL_VND_EVENT_ON_ASSERT: 1 + BLE_LL_HCI_VS_EVENT_ON_ASSERT: 1 syscfg.restrictions: - OS_CPUTIME_FREQ == 32768 diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 9acb76238f..b6f9869a71 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -1446,8 +1446,8 @@ struct ble_hci_ev_auth_pyld_tmo { #define BLE_HCI_EVCODE_SAM_STATUS_CHG (0x58) -#define BLE_HCI_EVCODE_VENDOR_DEBUG (0xFF) -struct ble_hci_ev_vendor_debug { +#define BLE_HCI_EVCODE_VS_DEBUG (0xFF) +struct ble_hci_ev_vs_debug { uint8_t id; uint8_t data[0]; } __attribute__((packed)); From b8ddf0fe06dfc7c717d183c9202eab2283421d06 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Fri, 5 Nov 2021 11:42:06 +0100 Subject: [PATCH 252/306] nimble/ll: Add support for vs hci commands registration This adds API to allow registration of custom HCI VS commands. --- .../include/controller/ble_ll_hci.h | 18 +++ nimble/controller/src/ble_ll.c | 5 + nimble/controller/src/ble_ll_hci.c | 44 +------ nimble/controller/src/ble_ll_hci_priv.h | 37 ++++++ nimble/controller/src/ble_ll_hci_vs.c | 119 ++++++++++++++++++ nimble/controller/syscfg.yml | 5 + 6 files changed, 186 insertions(+), 42 deletions(-) create mode 100644 nimble/controller/src/ble_ll_hci_priv.h create mode 100644 nimble/controller/src/ble_ll_hci_vs.c diff --git a/nimble/controller/include/controller/ble_ll_hci.h b/nimble/controller/include/controller/ble_ll_hci.h index 6a9e48e537..9f3fc9503f 100644 --- a/nimble/controller/include/controller/ble_ll_hci.h +++ b/nimble/controller/include/controller/ble_ll_hci.h @@ -43,6 +43,20 @@ extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN]; typedef void (*ble_ll_hci_post_cmd_complete_cb)(void); +#if MYNEWT_VAL(BLE_HCI_VS) +typedef int (* ble_ll_hci_vs_cb_t)(uint16_t ocf, + const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen); + +#define BLE_LL_HCI_VS_CMD(_ocf, _cb) { .ocf = (_ocf), .cb = (_cb) } + +struct ble_ll_hci_vs_cmd { + uint16_t ocf; + ble_ll_hci_vs_cb_t cb; + SLIST_ENTRY(ble_ll_hci_vs_cmd) link; +}; +#endif + /* Initialize LL HCI */ void ble_ll_hci_init(void); @@ -68,6 +82,10 @@ bool ble_ll_hci_adv_mode_ext(void); /* Get TX power compensation rounded to integer dB */ int8_t ble_ll_get_tx_pwr_compensation(void); +#if MYNEWT_VAL(BLE_HCI_VS) +void ble_ll_hci_vs_register(struct ble_ll_hci_vs_cmd *cmds, uint32_t num_cmds); +#endif + #ifdef __cplusplus } #endif diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 5305e162bc..16c2242c22 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -45,6 +45,7 @@ #include "controller/ble_ll_trace.h" #include "controller/ble_ll_sync.h" #include "ble_ll_conn_priv.h" +#include "ble_ll_hci_priv.h" #include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_DTM) @@ -1731,6 +1732,10 @@ ble_ll_init(void) ble_ll_dtm_init(); #endif +#if MYNEWT_VAL(BLE_HCI_VS) + ble_ll_hci_vs_init(); +#endif + #if MYNEWT /* Initialize the LL task */ os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL, diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index c2603c989d..0e92939133 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -36,6 +36,7 @@ #include "controller/ble_ll_iso.h" #include "ble_ll_priv.h" #include "ble_ll_conn_priv.h" +#include "ble_ll_hci_priv.h" #if MYNEWT_VAL(BLE_LL_DTM) #include "ble_ll_dtm_priv.h" @@ -1525,47 +1526,6 @@ ble_ll_hci_status_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, return rc; } -#if MYNEWT_VAL(BLE_HCI_VS) -static int -ble_ll_hci_vs_rd_static_addr(uint8_t *rspbuf, uint8_t *rsplen) -{ - struct ble_hci_vs_rd_static_addr_rp *rsp = (void *) rspbuf; - ble_addr_t addr; - - if (ble_hw_get_static_addr(&addr) < 0) { - return BLE_ERR_UNSPECIFIED; - } - - memcpy(rsp->addr, addr.val, sizeof(rsp->addr)); - - *rsplen = sizeof(*rsp); - return BLE_ERR_SUCCESS; -} - -static int -ble_ll_hci_vs_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, - uint8_t *rspbuf, uint8_t *rsplen) -{ - int rc; - - /* Assume error; if all pass rc gets set to 0 */ - rc = BLE_ERR_INV_HCI_CMD_PARMS; - - switch (ocf) { - case BLE_HCI_OCF_VS_RD_STATIC_ADDR: - if (len == 0) { - rc = ble_ll_hci_vs_rd_static_addr(rspbuf, rsplen); - } - break; - default: - rc = BLE_ERR_UNKNOWN_HCI_CMD; - break; - } - - return rc; -} -#endif - /** * Called to process an HCI command from the host. * @@ -1625,7 +1585,7 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) case BLE_HCI_OGF_LE: rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen, &post_cb); break; -#if MYNEWT_VAL(BLE_HCI_VS) +#if MYNEWT_VAL(BLE_LL_HCI_VS) case BLE_HCI_OGF_VENDOR: rc = ble_ll_hci_vs_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); break; diff --git a/nimble/controller/src/ble_ll_hci_priv.h b/nimble/controller/src/ble_ll_hci_priv.h new file mode 100644 index 0000000000..f289dc1035 --- /dev/null +++ b/nimble/controller/src/ble_ll_hci_priv.h @@ -0,0 +1,37 @@ +/* + * 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_HCI_PRIV_ +#define H_BLE_LL_HCI_PRIV_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(BLE_HCI_VS) +void ble_ll_hci_vs_init(void); +int ble_ll_hci_vs_cmd_proc(const uint8_t *cmdbuf, uint8_t cmdlen, uint16_t ocf, + uint8_t *rspbuf, uint8_t *rsplen); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_HCI_ */ diff --git a/nimble/controller/src/ble_ll_hci_vs.c b/nimble/controller/src/ble_ll_hci_vs.c new file mode 100644 index 0000000000..8903525ec9 --- /dev/null +++ b/nimble/controller/src/ble_ll_hci_vs.c @@ -0,0 +1,119 @@ +/* + * 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 "controller/ble_ll.h" +#include "controller/ble_ll_hci.h" +#include "controller/ble_hw.h" + +#if MYNEWT_VAL(BLE_LL_HCI_VS) + +SLIST_HEAD(ble_ll_hci_vs_list, ble_ll_hci_vs_cmd); +static struct ble_ll_hci_vs_list g_ble_ll_hci_vs_list; + +static int +ble_ll_hci_vs_rd_static_addr(uint16_t ocf, + const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_hci_vs_rd_static_addr_rp *rsp = (void *) rspbuf; + ble_addr_t addr; + + if (cmdlen != 0) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (ble_hw_get_static_addr(&addr) < 0) { + return BLE_ERR_UNSPECIFIED; + } + + memcpy(rsp->addr, addr.val, sizeof(rsp->addr)); + + *rsplen = sizeof(*rsp); + + return BLE_ERR_SUCCESS; +} + +static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_RD_STATIC_ADDR, + ble_ll_hci_vs_rd_static_addr), +}; + +static struct ble_ll_hci_vs_cmd * +ble_ll_hci_vs_find_by_ocf(uint16_t ocf) +{ + struct ble_ll_hci_vs_cmd *entry; + + entry = SLIST_FIRST(&g_ble_ll_hci_vs_list); + while (entry) { + if (entry->ocf == ocf) { + return entry; + } + + entry = SLIST_NEXT(entry, link); + } + + return NULL; +} + +int +ble_ll_hci_vs_cmd_proc(const uint8_t *cmdbuf, uint8_t cmdlen, uint16_t ocf, + uint8_t *rspbuf, uint8_t *rsplen) +{ + struct ble_ll_hci_vs_cmd *cmd; + int rc; + + cmd = ble_ll_hci_vs_find_by_ocf(ocf); + if (!cmd) { + rc = BLE_ERR_UNKNOWN_HCI_CMD; + } else { + rc = cmd->cb(ocf, cmdbuf, cmdlen, rspbuf, rsplen); + } + + return rc; +} + +void +ble_ll_hci_vs_register(struct ble_ll_hci_vs_cmd *cmds, uint32_t num_cmds) +{ + uint32_t i; + + /* Assume all cmds are registered early on init, so just assert in case of + * invalid request since it means something is wrong with the code itself. + */ + + for (i = 0; i < num_cmds; i++, cmds++) { + BLE_LL_ASSERT(cmds->cb != NULL); + BLE_LL_ASSERT(ble_ll_hci_vs_find_by_ocf(cmds->ocf) == NULL); + + SLIST_INSERT_HEAD(&g_ble_ll_hci_vs_list, cmds, link); + } +} + +void +ble_ll_hci_vs_init(void) +{ + SLIST_INIT(&g_ble_ll_hci_vs_list); + + ble_ll_hci_vs_register(g_ble_ll_hci_vs_cmds, + ARRAY_SIZE(g_ble_ll_hci_vs_cmds)); +} + +#endif diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index d60e18fc25..d799e1c757 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -348,6 +348,11 @@ syscfg.defs: depending on specified HCI command length. value: 0 + BLE_LL_HCI_VS: + description: > + Enables support for vendor-specific HCI commands. + value: MYNEWT_VAL(BLE_HCI_VS) + BLE_LL_HCI_VS_EVENT_ON_ASSERT: description: > This options enables controller to send a vendor-specific event on From 51c0f770ee92b3605029f24e4433bfde39c8314b Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 4 Nov 2021 17:21:39 +0100 Subject: [PATCH 253/306] nimble/phy/nrf: Remove workrounds for ifs on LE Coded BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN was added with initial implementation for LE Coded to workaround problems with some early releases of devices that could not keep ifs timing properly. We do not want it anymore, all devices should have ifs implemented properly in 2021 already. --- nimble/drivers/nrf52/src/ble_phy.c | 11 ----------- nimble/drivers/nrf52/syscfg.yml | 10 ---------- 2 files changed, 21 deletions(-) diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c index 6c520ab8b8..7085e78c68 100644 --- a/nimble/drivers/nrf52/src/ble_phy.c +++ b/nimble/drivers/nrf52/src/ble_phy.c @@ -703,17 +703,6 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) * by waiting 1 usec more. */ end_time += 1; -#if MYNEWT_VAL(BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN) > 0 - if ((phy == BLE_PHY_MODE_CODED_125KBPS) || - (phy == BLE_PHY_MODE_CODED_500KBPS)) { - /* - * Some controllers exceed T_IFS when transmitting on coded phy - * so let's wait a bit longer to be able to talk to them if this - * workaround is enabled. - */ - end_time += MYNEWT_VAL(BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN); - } -#endif } else { /* * RX shall start no later than wfr_usecs after RX enabled. diff --git a/nimble/drivers/nrf52/syscfg.yml b/nimble/drivers/nrf52/syscfg.yml index ce5123721a..bb6a2e1ba0 100644 --- a/nimble/drivers/nrf52/syscfg.yml +++ b/nimble/drivers/nrf52/syscfg.yml @@ -22,16 +22,6 @@ syscfg.defs: Enable SystemView tracing module for radio driver. value: 0 - BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN: - description: > - This defines additional margin for T_IFS tolerance while in - RX on coded phy to allow maintaining connections with some - controllers that exceed proper T_IFS (150 usecs) by more - than allowed 2 usecs. - This value shall be only used for debugging purposes. It is - strongly recommended to keep this settings at default value - to ensure compliance with specification. - value: 0 BLE_PHY_DBG_TIME_TXRXEN_READY_PIN: description: > When set to proper GPIO pin number, this pin will be set From 0ef8d590db8bc741f3e25610c6e3e6d11dba2c6c Mon Sep 17 00:00:00 2001 From: Kaka1234-ai <73267746+Kaka1234-ai@users.noreply.github.com> Date: Thu, 18 Nov 2021 10:26:25 +0800 Subject: [PATCH 254/306] nimble/ll: Fix master SCA in LE Connection Complete Event MCA in LE (Enhanced) Connection Complete Event is valid only for peripheral role (5.3 V4 Part E 7.7.6.5.1). --- nimble/controller/src/ble_ll_conn_hci.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index 7e47377381..6489af0d5b 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -200,7 +200,9 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, enh_ev->conn_itvl = htole16(connsm->conn_itvl); enh_ev->conn_latency = htole16(connsm->slave_latency); enh_ev->supervision_timeout = htole16(connsm->supervision_tmo); - enh_ev->mca = connsm->master_sca; + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + enh_ev->mca = connsm->master_sca; + } } ble_ll_hci_event_send(hci_ev); @@ -225,7 +227,9 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, ev->conn_itvl = htole16(connsm->conn_itvl); ev->conn_latency = htole16(connsm->slave_latency); ev->supervision_timeout = htole16(connsm->supervision_tmo); - ev->mca = connsm->master_sca; + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + ev->mca = connsm->master_sca; + } } ble_ll_hci_event_send(hci_ev); From 10a7493c0f12e1b428c5becdfd2c13495827ba1a Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 25 Nov 2021 13:47:28 +0100 Subject: [PATCH 255/306] nimble/ll: Fix include guards for HCI_VS --- nimble/controller/include/controller/ble_ll_hci.h | 4 ++-- nimble/controller/src/ble_ll.c | 2 +- nimble/controller/src/ble_ll_hci_priv.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_hci.h b/nimble/controller/include/controller/ble_ll_hci.h index 9f3fc9503f..a9ea3bb055 100644 --- a/nimble/controller/include/controller/ble_ll_hci.h +++ b/nimble/controller/include/controller/ble_ll_hci.h @@ -43,7 +43,7 @@ extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN]; typedef void (*ble_ll_hci_post_cmd_complete_cb)(void); -#if MYNEWT_VAL(BLE_HCI_VS) +#if MYNEWT_VAL(BLE_LL_HCI_VS) typedef int (* ble_ll_hci_vs_cb_t)(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen); @@ -82,7 +82,7 @@ bool ble_ll_hci_adv_mode_ext(void); /* Get TX power compensation rounded to integer dB */ int8_t ble_ll_get_tx_pwr_compensation(void); -#if MYNEWT_VAL(BLE_HCI_VS) +#if MYNEWT_VAL(BLE_LL_HCI_VS) void ble_ll_hci_vs_register(struct ble_ll_hci_vs_cmd *cmds, uint32_t num_cmds); #endif diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 16c2242c22..b5a527abb8 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -1732,7 +1732,7 @@ ble_ll_init(void) ble_ll_dtm_init(); #endif -#if MYNEWT_VAL(BLE_HCI_VS) +#if MYNEWT_VAL(BLE_LL_HCI_VS) ble_ll_hci_vs_init(); #endif diff --git a/nimble/controller/src/ble_ll_hci_priv.h b/nimble/controller/src/ble_ll_hci_priv.h index f289dc1035..af67e0a1a3 100644 --- a/nimble/controller/src/ble_ll_hci_priv.h +++ b/nimble/controller/src/ble_ll_hci_priv.h @@ -24,7 +24,7 @@ extern "C" { #endif -#if MYNEWT_VAL(BLE_HCI_VS) +#if MYNEWT_VAL(BLE_LL_HCI_VS) void ble_ll_hci_vs_init(void); int ble_ll_hci_vs_cmd_proc(const uint8_t *cmdbuf, uint8_t cmdlen, uint16_t ocf, uint8_t *rspbuf, uint8_t *rsplen); From f1d2cbd8d3f7fa0a15840f91b78446be9f1cc3c1 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 25 Nov 2021 13:47:43 +0100 Subject: [PATCH 256/306] porting/riot: Refresh syscfg --- porting/npl/riot/include/syscfg/syscfg.h | 73 ++++++++++++++++++++---- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/porting/npl/riot/include/syscfg/syscfg.h b/porting/npl/riot/include/syscfg/syscfg.h index 480616b819..24b49da51d 100644 --- a/porting/npl/riot/include/syscfg/syscfg.h +++ b/porting/npl/riot/include/syscfg/syscfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0 + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSCFG_ @@ -18,16 +18,16 @@ /*** Repository @apache-mynewt-core info */ #ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE ("58d4be4b8e33dd4738a2a0c1c2016a9195542833") +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE ("49ac781dfadbeecfd03d60bcaac15617744783b7-dirty") #endif #ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE -#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE ("0.0.1") +#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE ("0.0.0") #endif /*** Repository @apache-mynewt-mcumgr info */ #ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR ("12b496e37caf20a45ab5aee4209b06c5d79ef9b1") +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR ("b03a5d43ef6640d4f8858f59140b256a0ee4e772-dirty") #endif #ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR @@ -36,22 +36,58 @@ /*** Repository @apache-mynewt-nimble info */ #ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE ("99de1340e7fbdee6a604415972bd24ec5117a78d") +#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE ("846dda1f93c05aaf38281925b256fdbd5044492d-dirty") #endif #ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE #define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE ("0.0.0") #endif +/*** Repository @bsim info */ +#ifndef MYNEWT_VAL_REPO_HASH_BSIM +#define MYNEWT_VAL_REPO_HASH_BSIM ("8c5297423a7602b2c0bf47c64c2ac22d55d646ac") +#endif + +#ifndef MYNEWT_VAL_REPO_VERSION_BSIM +#define MYNEWT_VAL_REPO_VERSION_BSIM ("0.0.0") +#endif + /*** Repository @mcuboot info */ #ifndef MYNEWT_VAL_REPO_HASH_MCUBOOT -#define MYNEWT_VAL_REPO_HASH_MCUBOOT ("137d79717764ed32d5da4b4b301f32f81b2bf40f") +#define MYNEWT_VAL_REPO_HASH_MCUBOOT ("d4c2d15c3ef524333abf7f1e5839265ad5055d96") #endif #ifndef MYNEWT_VAL_REPO_VERSION_MCUBOOT #define MYNEWT_VAL_REPO_VERSION_MCUBOOT ("0.0.0") #endif +/*** Repository @mynewt_runtime info */ +#ifndef MYNEWT_VAL_REPO_HASH_MYNEWT_RUNTIME +#define MYNEWT_VAL_REPO_HASH_MYNEWT_RUNTIME ("17c53cd08300587cb5b6e5647566799eff2de198") +#endif + +#ifndef MYNEWT_VAL_REPO_VERSION_MYNEWT_RUNTIME +#define MYNEWT_VAL_REPO_VERSION_MYNEWT_RUNTIME ("0.0.0") +#endif + +/*** Repository @onsemi info */ +#ifndef MYNEWT_VAL_REPO_HASH_ONSEMI +#define MYNEWT_VAL_REPO_HASH_ONSEMI ("a3bf406b581c1aba025b8fe9472a6d8628e94e53") +#endif + +#ifndef MYNEWT_VAL_REPO_VERSION_ONSEMI +#define MYNEWT_VAL_REPO_VERSION_ONSEMI ("0.0.0") +#endif + +/*** Repository @tinyusb info */ +#ifndef MYNEWT_VAL_REPO_HASH_TINYUSB +#define MYNEWT_VAL_REPO_HASH_TINYUSB ("aa1a5a11c7729548957e5d8baf1c18ba7a333d14") +#endif + +#ifndef MYNEWT_VAL_REPO_VERSION_TINYUSB +#define MYNEWT_VAL_REPO_VERSION_TINYUSB ("0.0.0") +#endif + /*** @apache-mynewt-core/compiler/arm-none-eabi-m4 */ @@ -1016,8 +1052,8 @@ #define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_RFMGMT (-1) #endif -#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB -#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM_CB (-1) +#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM +#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM (-1) #endif #ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_RUN @@ -1045,6 +1081,19 @@ #define MYNEWT_VAL_BLE_LL_HCI_LLCP_TRACE (0) #endif +/* Value copied from BLE_HCI_VS */ +#ifndef MYNEWT_VAL_BLE_LL_HCI_VS +#define MYNEWT_VAL_BLE_LL_HCI_VS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_ON_ASSERT +#define MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_ON_ASSERT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_STATS_ON_RESET +#define MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_STATS_ON_RESET (0) +#endif + #ifndef MYNEWT_VAL_BLE_LL_MASTER_SCA #define MYNEWT_VAL_BLE_LL_MASTER_SCA (4) #endif @@ -1077,6 +1126,10 @@ #define MYNEWT_VAL_BLE_LL_PRIO (0) #endif +#ifndef MYNEWT_VAL_BLE_LL_PUBLIC_DEV_ADDR +#define MYNEWT_VAL_BLE_LL_PUBLIC_DEV_ADDR (0x000000000000) +#endif + #ifndef MYNEWT_VAL_BLE_LL_RESOLV_LIST_SIZE #define MYNEWT_VAL_BLE_LL_RESOLV_LIST_SIZE (4) #endif @@ -1170,10 +1223,6 @@ #endif /*** @apache-mynewt-nimble/nimble/drivers/nrf52 */ -#ifndef MYNEWT_VAL_BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN -#define MYNEWT_VAL_BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN (0) -#endif - #ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_ADDRESS_END_PIN #define MYNEWT_VAL_BLE_PHY_DBG_TIME_ADDRESS_END_PIN (-1) #endif From 8d912e27c2bf4bfd4196b82299084b552281ec05 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 30 Nov 2021 09:42:51 +0100 Subject: [PATCH 257/306] nimble/ll: Fix os_cputime comparisons in ll_adv Need to use macros, otherwise it won't work as expected... --- nimble/controller/src/ble_ll_adv.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 88c4ae12b1..64a3b4034c 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -1527,7 +1527,8 @@ ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm) * scheduled aux will fit inside duration. If not, remove it from scheduler * so advertising will stop after current aux. */ - if (advsm->duration && (aux_next->sch.end_time > advsm->adv_end_time)) { + if (advsm->duration && + CPUTIME_GT(aux_next->sch.end_time, advsm->adv_end_time)) { ble_ll_sched_rmv_elem(&aux_next->sch); } } @@ -1657,7 +1658,7 @@ ble_ll_adv_aux_schedule(struct ble_ll_adv_sm *advsm) * not start extended advertising event which we cannot finish in time. */ if (advsm->duration && - (AUX_CURRENT(advsm)->sch.end_time > advsm->adv_end_time)) { + CPUTIME_GT(AUX_CURRENT(advsm)->sch.end_time, advsm->adv_end_time)) { ble_ll_adv_sm_stop_timeout(advsm); } } @@ -2414,8 +2415,8 @@ ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm) sync_next); /* if we are pass advertising interval, drop chain */ - if (sch->end_time > advsm->periodic_adv_event_start_time + - advsm->periodic_adv_itvl_ticks) { + if (CPUTIME_GT(sch->end_time, advsm->periodic_adv_event_start_time + + advsm->periodic_adv_itvl_ticks)) { STATS_INC(ble_ll_stats, periodic_chain_drop_event); ble_ll_sched_rmv_elem(&sync->sch); ble_npl_eventq_put(&g_ble_ll_data.ll_evq, @@ -4730,7 +4731,8 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) /* If we're past aux (unlikely, but can happen), just drop an event */ if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && advsm->aux_active && - advsm->adv_pdu_start_time > AUX_CURRENT(advsm)->start_time) { + CPUTIME_GT(advsm->adv_pdu_start_time, + AUX_CURRENT(advsm)->start_time)) { ble_ll_adv_drop_event(advsm); return; } @@ -4742,7 +4744,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) /* check if advertising timed out */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (advsm->duration && - advsm->adv_pdu_start_time >= advsm->adv_end_time) { + CPUTIME_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) { /* Legacy PDUs need to be stop here. * For ext adv it will be stopped when AUX is done (unless it was * dropped so check if AUX is active here as well). @@ -4756,7 +4758,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) } #else if ((advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) && - (advsm->adv_pdu_start_time >= advsm->adv_end_time)) { + CPUTIME_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) { ble_ll_adv_sm_stop_timeout(advsm); return; } @@ -4860,7 +4862,8 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm) ble_ll_scan_chk_resume(); /* Check if advertising timed out */ - if (advsm->duration && (advsm->adv_pdu_start_time >= advsm->adv_end_time)) { + if (advsm->duration && + CPUTIME_GEQ(advsm->adv_pdu_start_time, advsm->adv_end_time)) { ble_ll_adv_sm_stop_timeout(advsm); return; } From afd677efd275d18f76be25da04a5da9cba4e66f6 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 30 Nov 2021 16:00:56 +0100 Subject: [PATCH 258/306] nimble/ll: Move BLE_PUBLIC_DEV_ADDR to deprecated settings --- nimble/controller/syscfg.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index d799e1c757..7c33242716 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -315,15 +315,6 @@ syscfg.defs: Note: this setting should only be used for testing purposes, it is not intended for production builds. value: 0x000000000000 - BLE_PUBLIC_DEV_ADDR: - description: > - Allows the target or app to override the public device address - used by the controller. If all zero, the controller will - attempt to retrieve the public device address from its - chip specific location. If non-zero, this address will - be used. - value: "(uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}" - deprecated: 1 BLE_LL_DTM: description: > @@ -447,6 +438,10 @@ syscfg.defs: description: use BLE_LL_HCI_VS_EVENT_ON_ASSERT value: 0 deprecated: 1 + BLE_PUBLIC_DEV_ADDR: + description: use BLE_LL_PUBLIC_DEV_ADDR + value: "(uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}" + deprecated: 1 # defunct settings (to be removed eventually) BLE_DEVICE: From a17ed2a1da2f5850bb33ac65b18334c8104ac5bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Wed, 1 Dec 2021 14:56:24 +0100 Subject: [PATCH 259/306] host/mesh: fix bt_mesh_proxy_relay client->cli can be NULL - and this should be checked, not connection handle. --- nimble/host/mesh/src/proxy_srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/proxy_srv.c b/nimble/host/mesh/src/proxy_srv.c index 3507d0a45a..dcbabfa296 100644 --- a/nimble/host/mesh/src/proxy_srv.c +++ b/nimble/host/mesh/src/proxy_srv.c @@ -758,7 +758,7 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) struct bt_mesh_proxy_client *client = &clients[i]; struct os_mbuf *msg; - if (client->cli->conn_handle == BLE_HS_CONN_HANDLE_NONE) { + if (!client->cli) { continue; } From bc142016bdef082ba7997aea09aec1c1e4db0104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 23 Nov 2021 13:31:16 +0100 Subject: [PATCH 260/306] host/mesh: fix loopback in net net_buf structure in Zephyr has field user_data, which was wrongly ported as os_mbuf->om_data. To stick with porting net_buf as os_mbuf we can base on old Zephyr's implementation, which was changed in commit dd09cbc1c455ab1e067b53f46bee7b6d50689bbc. Before it, user_data was part of data buffer of net_buf. We can implement this the same way, so data_buf is last N octets of os_mbuf->om_data. Accomodate mbuf allocation and freeing to NimBLE. --- nimble/host/mesh/src/net.c | 4 ++-- nimble/host/mesh/src/net.h | 7 ++++++- nimble/host/mesh/syscfg.yml | 5 +++++ porting/examples/linux_blemesh/include/syscfg/syscfg.h | 4 ++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/nimble/host/mesh/src/net.c b/nimble/host/mesh/src/net.c index a36160d778..229e40546e 100644 --- a/nimble/host/mesh/src/net.c +++ b/nimble/host/mesh/src/net.c @@ -398,7 +398,7 @@ static void bt_mesh_net_local(struct ble_npl_event *work) rx.ctx.addr, rx.seq, sub); (void) bt_mesh_trans_recv(buf, &rx); - net_buf_unref(buf); + os_mbuf_free_chain(buf); } } @@ -480,7 +480,7 @@ static int loopback(const struct bt_mesh_net_tx *tx, const uint8_t *data, { struct os_mbuf *buf; - buf = os_mbuf_get_pkthdr(&loopback_os_mbuf_pool, 0); + buf = os_mbuf_get_pkthdr(&loopback_os_mbuf_pool, BT_MESH_NET_HDR_LEN); if (!buf) { BT_WARN("Unable to allocate loopback"); return -ENOMEM; diff --git a/nimble/host/mesh/src/net.h b/nimble/host/mesh/src/net.h index 9d8f857610..b8147b4d86 100644 --- a/nimble/host/mesh/src/net.h +++ b/nimble/host/mesh/src/net.h @@ -271,7 +271,12 @@ extern struct bt_mesh_net bt_mesh; static inline void *net_buf_user_data(const struct os_mbuf *buf) { - return (void *)buf->om_data; + /* In Zephyr at the end of net_buf (which is ported as os_mbuf) is place + * for user_data, which is array of octets, just like os_mbuf's om_data. Let's just + * use last octets (starting at start of om_data + total size of data mbuf can hold - + * intended user_data size) of om_data as Zephyr's user_data. + */ + return (void *)(buf->om_data + buf->om_omp->omp_databuf_len - MYNEWT_VAL(BLE_MESH_NET_BUF_USER_DATA_SIZE)); } int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], diff --git a/nimble/host/mesh/syscfg.yml b/nimble/host/mesh/syscfg.yml index ca74cdff7d..c75828d243 100644 --- a/nimble/host/mesh/syscfg.yml +++ b/nimble/host/mesh/syscfg.yml @@ -233,6 +233,11 @@ syscfg.defs: but has a different purpose. value: 10 + BLE_MESH_NET_BUF_USER_DATA_SIZE: + description: > + Number of octets that are used as user_data at the end of os_mbufs + value: 4 + BLE_MESH_ADV_BUF_COUNT: description: > Number of advertising buffers available. This should be chosen diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index 5a5288f52e..5d21359010 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -772,6 +772,10 @@ #endif /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE +#define MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE (4) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT #define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (20) #endif From 6b40986a1f508881aea3cbdd8c497627fd3180b3 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 7 Dec 2021 12:15:16 +0100 Subject: [PATCH 261/306] porting: Allow to build with -Wcast-align It is expected that mbuf structures are properly aligned so we can just cast to void pointer here and silence warning. --- porting/nimble/include/os/os_mbuf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/porting/nimble/include/os/os_mbuf.h b/porting/nimble/include/os/os_mbuf.h index 771ea76159..bee47d0bbf 100644 --- a/porting/nimble/include/os/os_mbuf.h +++ b/porting/nimble/include/os/os_mbuf.h @@ -133,11 +133,11 @@ struct os_mqueue { /** Get a packet header pointer given an mbuf pointer */ #define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *) \ - ((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf))) + (void *)((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf))) /** Given a mbuf packet header pointer, return a pointer to the mbuf */ #define OS_MBUF_PKTHDR_TO_MBUF(__hdr) \ - (struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf)) + (struct os_mbuf *)(void *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf)) /** * Gets the length of an entire mbuf chain. The specified mbuf must have a From 5e94b1b85a798ff17ad3ccc0879d676a11deae6f Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 6 Dec 2021 16:16:58 +0100 Subject: [PATCH 262/306] nimble/ll: Fix not validating no-param HCI commands sizes If command has no input parameters its size should be verified before passing it to handler function. --- nimble/controller/src/ble_ll_hci.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 0e92939133..c59137a884 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -1152,10 +1152,14 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, #endif #endif case BLE_HCI_OCF_LE_RD_TRANSMIT_POWER: - rc = ble_ll_read_tx_power(rspbuf, rsplen); + if (len == 0) { + rc = ble_ll_read_tx_power(rspbuf, rsplen); + } break; case BLE_HCI_OCF_LE_RD_RF_PATH_COMPENSATION: - rc = ble_ll_read_rf_path_compensation(rspbuf, rsplen); + if (len == 0) { + rc = ble_ll_read_rf_path_compensation(rspbuf, rsplen); + } break; case BLE_HCI_OCF_LE_WR_RF_PATH_COMPENSATION: rc = ble_ll_write_rf_path_compensation(cmdbuf, len); @@ -1217,7 +1221,9 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, 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); + if (len == 0) { + rc = ble_ll_hci_le_read_bufsize_v2(rspbuf, rsplen); + } break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST) From 64b74026961663f9172f90559f75975808ebae62 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 6 Dec 2021 16:18:24 +0100 Subject: [PATCH 263/306] nimble/ll: Fix typo in ble_ll_read_rf_path_compensation ;; are not needed here --- nimble/controller/src/ble_ll_hci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index c59137a884..e3e558e612 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -786,7 +786,7 @@ ble_ll_read_rf_path_compensation(uint8_t *rspbuf, uint8_t *rsplen) rsp->rx_path_compensation = htole16(rx_path_pwr_compensation); rsp->tx_path_compensation = htole16(tx_path_pwr_compensation); - *rsplen = sizeof(*rsp);; + *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } From 96df59e1deca6c5bf90b18fe7d7fd144353c0806 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 6 Dec 2021 10:58:34 +0100 Subject: [PATCH 264/306] nimble/transport: Fix ble_ll_hw_error declaration in UART transport ble_ll_hw_error() is defined as taking no arguments. --- nimble/transport/uart/src/ble_hci_uart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/transport/uart/src/ble_hci_uart.c b/nimble/transport/uart/src/ble_hci_uart.c index cbb6dd4259..2cad55a7d9 100644 --- a/nimble/transport/uart/src/ble_hci_uart.c +++ b/nimble/transport/uart/src/ble_hci_uart.c @@ -55,7 +55,7 @@ /* XXX: for now, define this here */ #if MYNEWT_VAL(BLE_CONTROLLER) extern void ble_ll_data_buffer_overflow(void); -extern void ble_ll_hw_error(uint8_t err); +extern void ble_ll_hw_error(void); static const uint8_t ble_hci_uart_reset_cmd[4] = { 0x01, 0x03, 0x0C, 0x00 }; #endif @@ -400,7 +400,7 @@ ble_hci_uart_sync_lost(void) ble_hci_uart_state.rx_cmd.cur = 0; ble_hci_uart_state.rx_cmd.data = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); - ble_ll_hw_error(BLE_HW_ERR_HCI_SYNC_LOSS); + ble_ll_hw_error(); ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SYNC_LOSS; } #endif From 7a6c64774faaa373310e21886ba979f253898b8c Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 8 Dec 2021 13:21:11 +0100 Subject: [PATCH 265/306] nimble/ll: Fix supported commands bitmask --- nimble/controller/src/ble_ll_supp_cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/controller/src/ble_ll_supp_cmd.c b/nimble/controller/src/ble_ll_supp_cmd.c index cae9eb7dd1..6ceeaebb02 100644 --- a/nimble/controller/src/ble_ll_supp_cmd.c +++ b/nimble/controller/src/ble_ll_supp_cmd.c @@ -483,9 +483,9 @@ /* Octet 44 */ #if MYNEWT_VAL(BLE_VERSION) >= 52 -#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 0) +#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 1) #else -#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 0) +#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 1) #endif #define BLE_LL_SUPP_CMD_OCTET_44 \ ( \ From 3b029a774bc09ba092924421534691212c43af58 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 8 Dec 2021 13:07:38 +0100 Subject: [PATCH 266/306] nimble/ll: Always send hci_cs for unknown command Core 5.3, Vol 4, Part E, 4.5 states that sending hci_cc vs. hci_cs is vendor specific so we always send hci_cs for all commands since we already do this for LE commands. --- nimble/controller/src/ble_ll_hci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index e3e558e612..7bbc6774c5 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -1266,11 +1266,8 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, * This code is here because we add 256 to the return code to denote * that the reply to this command should be command status (as opposed to * command complete). - * - * For unknown HCI command let us return always command status as per - * specification Bluetooth 5, Vol. 2, Chapter 4.4 */ - if (ble_ll_hci_le_cmd_send_cmd_status(ocf) || rc == BLE_ERR_UNKNOWN_HCI_CMD) { + if (ble_ll_hci_le_cmd_send_cmd_status(ocf)) { rc += (BLE_ERR_MAX + 1); } @@ -1602,6 +1599,13 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) break; } + /* We always send command status for unknown command + * ref: Core 5.3, Vol 4, Part E, 4.5 + */ + if (rc == BLE_ERR_UNKNOWN_HCI_CMD) { + rc += (BLE_ERR_MAX + 1); + } + /* If no response is generated, we free the buffers */ BLE_LL_ASSERT(rc >= 0); if (rc <= BLE_ERR_MAX) { From a6009432de27b9e0ea5e1f95dba4d82d5412ac9f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 25 Nov 2021 12:45:23 +0100 Subject: [PATCH 267/306] nimble/ll: Add missing scan resume Need to always resume scan on rx_pkt_in... --- nimble/controller/src/ble_ll_scan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 47b7d0bd7f..6e78f3245d 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -1942,6 +1942,7 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd } #endif if (ptype > max_pdu_type) { + ble_ll_scan_chk_resume(); return; } From 67d30b63b373f6d16f1d1caf22a9af73415be229 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 25 Nov 2021 12:45:46 +0100 Subject: [PATCH 268/306] nimble/phy/nrf: Move rx_end to disabled event This moves handling of PDU RX end from EVENT_END to EVENT_DISABLED. This will allow to run our phy on BabbleSim and also seems to simplify code a bit. EVENT_DISABLED happens almost immediately after EVENT_END, so on real it happens while ble_phy_isr is being executed and is simply ignored. However, on BabbleSim code is executed as if time was paused which means that no other event can occur when ble_phy_isr is being executed, i.e. it will be called after we return from isr and simulation code can trigger subsequent events. If rx_end configures transition to TX and thus enables interrupt on EVENT_DISABLED, we will handle that during an event that is triggered for RX - basically we handle tx_end before TX even started. Using EVENT_DISABLED for both TX and RX resolves this issue. We still use timer capture on EVENT_END for transition timing so this has no effect on that calculations, and since EVENT_DISABLED occurs just a fraction of microsecond after EVENT_END, execution timings are also not affected. --- nimble/drivers/nrf52/src/ble_phy.c | 61 +++++++++++++----------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c index 7085e78c68..6aa898b327 100644 --- a/nimble/drivers/nrf52/src/ble_phy.c +++ b/nimble/drivers/nrf52/src/ble_phy.c @@ -730,9 +730,6 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) /* Enable wait for response PPI */ NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); - /* Enable the disabled interrupt so we time out on events compare */ - NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; - /* * It may happen that if CPU is halted for a brief moment (e.g. during flash * erase or write), TIMER0 already counted past CC[3] and thus wfr will not @@ -860,7 +857,8 @@ ble_phy_rx_xcvr_setup(void) RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk; - NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk; + NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk | + RADIO_INTENSET_DISABLED_Msk; } /** @@ -874,7 +872,6 @@ ble_phy_tx_end_isr(void) uint8_t was_encrypted; uint8_t transition; uint32_t rx_time; - uint32_t wfr_time; /* Store PHY on which we've just transmitted smth */ tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode; @@ -886,13 +883,6 @@ ble_phy_tx_end_isr(void) /* Better be in TX state! */ assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); - /* Clear events and clear interrupt on disabled event */ - NRF_RADIO->EVENTS_DISABLED = 0; - NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; - NRF_RADIO->EVENTS_END = 0; - wfr_time = NRF_RADIO->SHORTS; - (void)wfr_time; - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) /* * XXX: not sure what to do. We had a HW error during transmission. @@ -982,10 +972,6 @@ ble_phy_rx_end_isr(void) uint32_t tx_time; struct ble_mbuf_hdr *ble_hdr; - /* Clear events and clear interrupt */ - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk; - /* Disable automatic RXEN */ NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk; @@ -1116,9 +1102,9 @@ ble_phy_rx_start_isr(void) /* Clear events and clear interrupt */ NRF_RADIO->EVENTS_ADDRESS = 0; + NRF_RADIO->INTENCLR = RADIO_INTENCLR_ADDRESS_Msk; - /* Clear wfr timer channels and DISABLED interrupt */ - NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk; + /* Clear wfr timer channels */ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk; /* Initialize the ble mbuf header */ @@ -1210,7 +1196,6 @@ ble_phy_rx_start_isr(void) if (rc >= 0) { /* Set rx started flag and enable rx end ISR */ g_ble_phy_data.phy_rx_started = 1; - NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; } else { /* Disable PHY */ ble_phy_disable(); @@ -1256,28 +1241,36 @@ ble_phy_isr(void) } } - /* Check for disabled event. This only happens for transmits now */ + /* Handle disabled event. This is enabled for both TX and RX. On RX, we + * need to check phy_rx_started flag to make sure we actually were receiving + * a PDU, otherwise this is due to wfr. + */ if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) { - if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) { - NRF_RADIO->EVENTS_DISABLED = 0; - ble_ll_wfr_timer_exp(NULL); - } else if (g_ble_phy_data.phy_state == BLE_PHY_STATE_IDLE) { - assert(0); - } else { + BLE_LL_ASSERT(NRF_RADIO->EVENTS_END || + ((g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) && + !g_ble_phy_data.phy_rx_started)); + NRF_RADIO->EVENTS_END = 0; + NRF_RADIO->EVENTS_DISABLED = 0; + NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; + + switch (g_ble_phy_data.phy_state) { + case BLE_PHY_STATE_RX: + if (g_ble_phy_data.phy_rx_started) { + ble_phy_rx_end_isr(); + } else { + ble_ll_wfr_timer_exp(NULL); + } + break; + case BLE_PHY_STATE_TX: ble_phy_tx_end_isr(); + break; + default: + BLE_LL_ASSERT(0); } } - /* Receive packet end (we dont enable this for transmit) */ - if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) { - ble_phy_rx_end_isr(); - } - g_ble_phy_data.phy_transition_late = 0; - /* Ensures IRQ is cleared */ - irq_en = NRF_RADIO->SHORTS; - /* Count # of interrupts */ STATS_INC(ble_phy_stats, phy_isrs); From e744a88bf8f106f45492066b635b21985d3ebc07 Mon Sep 17 00:00:00 2001 From: Marceau Fillon Date: Wed, 24 Nov 2021 17:49:16 +1100 Subject: [PATCH 269/306] host/ble_att_svr: Reset handles index on attributes reset. --- nimble/host/src/ble_att_svr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index 9af0e0d043..468768ac02 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -2671,6 +2671,8 @@ ble_att_svr_reset(void) ble_att_svr_entry_free(entry); } + ble_att_svr_id = 0; + /* Note: prep entries do not get freed here because it is assumed there are * no established connections. */ From 1969ca31127775a1895f2767d4bb3c4f53493662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 19 Nov 2021 08:04:52 +0100 Subject: [PATCH 270/306] host/l2cap: disconnect peer that sends L2CAP packets with hdr len > mtu Rest of the checks disconnects peer if SDU size exceeds MTU, but value in header is OK. We should also disconnect if PDU lenght in L2CAP packet header exceeds it, regardles of how much data it actually contains, not just return error. This is affecting L2CAP/LE/CFC/BV-26-C and L2CAP/ECFC/BV-33-C --- nimble/host/src/ble_l2cap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nimble/host/src/ble_l2cap.c b/nimble/host/src/ble_l2cap.c index 2bc50e0e93..bfbdadfcd6 100644 --- a/nimble/host/src/ble_l2cap.c +++ b/nimble/host/src/ble_l2cap.c @@ -393,8 +393,11 @@ ble_l2cap_rx(struct ble_hs_conn *conn, } if (l2cap_hdr.len > ble_l2cap_get_mtu(chan)) { - /* More data then we expected on the channel */ + /* More data than we expected on the channel. + * Disconnect peer with invalid behaviour + */ rc = BLE_HS_EBADDATA; + ble_l2cap_disconnect(chan); goto err; } From de56c3a41af98d26e56a21a7902bc6e6a54dd10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 25 Nov 2021 09:34:20 +0100 Subject: [PATCH 271/306] host/l2cap_sig: do not permit duplicated CID in connect response If peer sends L2CAP connect response with duplicated DCID connection should not be created on that channel and existing channel of this CID shall be disconnected. This is affecting L2CAP/ECFC/BV-29-C --- nimble/host/src/ble_l2cap_sig.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/nimble/host/src/ble_l2cap_sig.c b/nimble/host/src/ble_l2cap_sig.c index f34c20b8bb..3033e05dd5 100644 --- a/nimble/host/src/ble_l2cap_sig.c +++ b/nimble/host/src/ble_l2cap_sig.c @@ -1048,6 +1048,7 @@ ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle, struct ble_hs_conn *conn; int rc; int i; + uint16_t duplicated_cids[5] = {}; #if !BLE_MONITOR BLE_HS_LOG(DEBUG, "L2CAP LE COC connection response received\n"); @@ -1093,6 +1094,12 @@ ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle, chan->dcid = 0; continue; } + if (ble_hs_conn_chan_find_by_dcid(conn, rsp->dcids[i])) { + duplicated_cids[i] = rsp->dcids[i]; + chan->dcid = 0; + continue; + } + chan->peer_coc_mps = le16toh(rsp->mps); chan->dcid = le16toh(rsp->dcids[i]); chan->coc_tx.mtu = le16toh(rsp->mtu); @@ -1104,6 +1111,16 @@ ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle, ble_hs_unlock(); done: + for (i = 0; i < 5; i++){ + if (duplicated_cids[i] != 0){ + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + chan = ble_hs_conn_chan_find_by_dcid(conn, duplicated_cids[i]); + ble_hs_unlock(); + rc = ble_l2cap_sig_disconnect(chan); + } + } + ble_l2cap_sig_coc_connect_cb(proc, rc); ble_l2cap_sig_proc_free(proc); From d7c18041d75970a2a13af2a644a437b43a3d58c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 25 Nov 2021 09:37:09 +0100 Subject: [PATCH 272/306] apps/bttester: mark L2CAP channel as used in connect This will prevent returning same channel every time in `get_free_channel()`. --- apps/bttester/src/l2cap.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/bttester/src/l2cap.c b/apps/bttester/src/l2cap.c index b9b97ec199..35e746d5cf 100644 --- a/apps/bttester/src/l2cap.c +++ b/apps/bttester/src/l2cap.c @@ -398,7 +398,7 @@ static void connect(uint8_t *data, uint16_t len) ble_addr_t *addr = (void *) data; uint16_t mtu = htole16(cmd->mtu); int rc; - int i; + int i, j; SYS_LOG_DBG("connect: type: %d addr: %s", addr->type, bt_hex(addr->val, 6)); @@ -420,6 +420,8 @@ static void connect(uint8_t *data, uint16_t len) SYS_LOG_ERR("No free channels"); goto fail; } + /* temporarily mark channel as used to select next one */ + chan->state = 1; rp->chan_ids[i] = chan->chan_id; @@ -430,6 +432,15 @@ static void connect(uint8_t *data, uint16_t len) } } + /* mark selected channels as unused again */ + for (i = 0; i < cmd->num; i++) { + for (j = 0; j < CHANNELS; j++) { + if (rp->chan_ids[i] == channels[j].chan_id) { + channels[j].state = 0; + } + } + } + if (cmd->num == 1) { rc = ble_l2cap_connect(desc.conn_handle, htole16(cmd->psm), mtu, sdu_rx[0], From 5b6352364ba44d8fc93e1394d308f99efe782bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 25 Nov 2021 09:38:31 +0100 Subject: [PATCH 273/306] app/bttester: do not send L2CAP disconnection event if error in connect There is a little need of sending such event: created connection is confirmed connection event; if no such event is received, the connection can be considered not established. Disconnected event shall be sent only for disconnection. By removing disconnected_cb call on connect error we avoid calling it for not established channel, for example when DCID in connection response was a duplicate of already connected one. This would trigger the assert `assert(channel != NULL);`. --- apps/bttester/src/l2cap.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/bttester/src/l2cap.c b/apps/bttester/src/l2cap.c index 35e746d5cf..27cc6a9a6e 100644 --- a/apps/bttester/src/l2cap.c +++ b/apps/bttester/src/l2cap.c @@ -259,8 +259,6 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg) if (event->connect.status) { console_printf("LE COC error: %d\n", event->connect.status); - disconnected_cb(event->connect.conn_handle, - event->connect.chan, &chan_info, arg); return 0; } From 8c6f70425ba2d697044d4b12201744b26cc47a92 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 22 Nov 2021 14:12:34 +0100 Subject: [PATCH 274/306] apps: Update transport selection method Transport package should not be included directly. Instead, nimble/transport should be included and BLE_HCI_TRANSPORT syscfg value should specify transport, and this will include correct package. This commit changes nimble/transport/ram to nimble/transport in all applications that still have deprecated way of transport selection. Default value of BLE_HCI_TRANSPORT is ram so syscfg.yml for targets does not need to be updated. --- apps/blehr/pkg.yml | 2 +- apps/blemesh/pkg.yml | 2 +- apps/blemesh_light/pkg.yml | 2 +- apps/blemesh_models_example_1/pkg.yml | 2 +- apps/blemesh_models_example_2/pkg.yml | 2 +- apps/blemesh_shell/pkg.yml | 2 +- apps/blestress/pkg.yml | 2 +- apps/bttester/pkg.yml | 2 +- apps/ext_advertiser/pkg.yml | 2 +- apps/mesh_badge/pkg.yml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/blehr/pkg.yml b/apps/blehr/pkg.yml index b91ba3775b..395134faba 100644 --- a/apps/blehr/pkg.yml +++ b/apps/blehr/pkg.yml @@ -37,4 +37,4 @@ pkg.deps: - nimble/host/services/gap - nimble/host/services/gatt - nimble/host/store/config - - nimble/transport/ram + - nimble/transport diff --git a/apps/blemesh/pkg.yml b/apps/blemesh/pkg.yml index c70565423c..8a2af6874c 100644 --- a/apps/blemesh/pkg.yml +++ b/apps/blemesh/pkg.yml @@ -34,4 +34,4 @@ pkg.deps: - nimble/host/services/gap - nimble/host/services/gatt - nimble/host/store/config - - nimble/transport/ram + - nimble/transport diff --git a/apps/blemesh_light/pkg.yml b/apps/blemesh_light/pkg.yml index 75a60df7bb..bfc1ad233a 100644 --- a/apps/blemesh_light/pkg.yml +++ b/apps/blemesh_light/pkg.yml @@ -34,4 +34,4 @@ pkg.deps: - nimble/host/services/gap - nimble/host/services/gatt - nimble/host/store/config - - nimble/transport/ram + - nimble/transport diff --git a/apps/blemesh_models_example_1/pkg.yml b/apps/blemesh_models_example_1/pkg.yml index 451f37a11c..cd11834c5f 100644 --- a/apps/blemesh_models_example_1/pkg.yml +++ b/apps/blemesh_models_example_1/pkg.yml @@ -31,4 +31,4 @@ pkg.deps: - nimble/host - nimble/host/services/gap - nimble/host/services/gatt - - nimble/transport/ram + - nimble/transport diff --git a/apps/blemesh_models_example_2/pkg.yml b/apps/blemesh_models_example_2/pkg.yml index ee2be6da2a..684d85bad8 100644 --- a/apps/blemesh_models_example_2/pkg.yml +++ b/apps/blemesh_models_example_2/pkg.yml @@ -33,7 +33,7 @@ pkg.deps: - nimble/host - nimble/host/services/gap - nimble/host/services/gatt - - nimble/transport/ram + - nimble/transport pkg.lflags: - -DFLOAT_SUPPORT diff --git a/apps/blemesh_shell/pkg.yml b/apps/blemesh_shell/pkg.yml index e4852f6fa5..2e7064cf90 100644 --- a/apps/blemesh_shell/pkg.yml +++ b/apps/blemesh_shell/pkg.yml @@ -34,4 +34,4 @@ pkg.deps: - nimble/host/services/gap - nimble/host/services/gatt - nimble/host/store/config - - nimble/transport/ram + - nimble/transport diff --git a/apps/blestress/pkg.yml b/apps/blestress/pkg.yml index b23358c564..d4c52d247c 100644 --- a/apps/blestress/pkg.yml +++ b/apps/blestress/pkg.yml @@ -36,4 +36,4 @@ pkg.deps: - "@apache-mynewt-nimble/nimble/host/services/gap" - "@apache-mynewt-nimble/nimble/host/services/gatt" - "@apache-mynewt-nimble/nimble/host/store/config" - - "@apache-mynewt-nimble/nimble/transport/ram" + - "@apache-mynewt-nimble/nimble/transport" diff --git a/apps/bttester/pkg.yml b/apps/bttester/pkg.yml index ba2b7fb1be..39405aa051 100644 --- a/apps/bttester/pkg.yml +++ b/apps/bttester/pkg.yml @@ -38,7 +38,7 @@ pkg.deps: - "@apache-mynewt-nimble/nimble/host/services/gatt" - "@apache-mynewt-nimble/nimble/host/services/dis" - "@apache-mynewt-nimble/nimble/host/store/config" - - "@apache-mynewt-nimble/nimble/transport/ram" + - "@apache-mynewt-nimble/nimble/transport" - "@apache-mynewt-core/hw/drivers/uart" - "@apache-mynewt-core/hw/drivers/rtt" diff --git a/apps/ext_advertiser/pkg.yml b/apps/ext_advertiser/pkg.yml index 097764b206..b9f9e54728 100644 --- a/apps/ext_advertiser/pkg.yml +++ b/apps/ext_advertiser/pkg.yml @@ -31,7 +31,7 @@ pkg.deps: - nimble/host/services/gap - nimble/host/services/gatt - nimble/host/store/config - - nimble/transport/ram + - nimble/transport - "@apache-mynewt-core/kernel/os" - "@apache-mynewt-core/sys/console/full" - "@apache-mynewt-core/sys/log/full" diff --git a/apps/mesh_badge/pkg.yml b/apps/mesh_badge/pkg.yml index 0718236f6a..802b86bab4 100644 --- a/apps/mesh_badge/pkg.yml +++ b/apps/mesh_badge/pkg.yml @@ -36,4 +36,4 @@ pkg.deps: - nimble/host/services/gap - nimble/host/services/gatt - nimble/host/store/config - - nimble/transport/ram + - nimble/transport From d3a1acd3ffe9d2eaae8bed26630553d4bff1fc53 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 17 Dec 2021 15:23:37 +0100 Subject: [PATCH 275/306] nimble/ll: Compile out not enabled GAP roles This gives some FLASH and RAM savings for applications that use only subset of GAP roles. LL features are also tuned depending on selected GAP roles. Examples of FLASH and RAM usage: BLE_ROLE_CENTRAL: 1 BLE_ROLE_PERIPHERAL: 1 BLE_ROLE_BROADCASTER: 1 BLE_ROLE_OBSERVER: 1 56122 19661 @apache-mynewt-nimble_nimble_controller.a BLE_ROLE_CENTRAL: 0 BLE_ROLE_PERIPHERAL: 1 BLE_ROLE_BROADCASTER: 1 BLE_ROLE_OBSERVER: 1 51344 19589 @apache-mynewt-nimble_nimble_controller.a BLE_ROLE_CENTRAL: 0 BLE_ROLE_PERIPHERAL: 1 BLE_ROLE_BROADCASTER: 1 BLE_ROLE_OBSERVER: 0 35694 15232 @apache-mynewt-nimble_nimble_controller.a BLE_ROLE_CENTRAL: 1 BLE_ROLE_PERIPHERAL: 0 BLE_ROLE_BROADCASTER: 1 BLE_ROLE_OBSERVER: 1 53338 19593 @apache-mynewt-nimble_nimble_controller.a BLE_ROLE_CENTRAL: 1 BLE_ROLE_PERIPHERAL: 0 BLE_ROLE_BROADCASTER: 0 BLE_ROLE_OBSERVER: 1 42040 12925 @apache-mynewt-nimble_nimble_controller.a BLE_ROLE_CENTRAL: 0 BLE_ROLE_PERIPHERAL: 0 BLE_ROLE_BROADCASTER: 1 BLE_ROLE_OBSERVER: 1 34800 12525 @apache-mynewt-nimble_nimble_controller.a BLE_ROLE_CENTRAL: 0 BLE_ROLE_PERIPHERAL: 0 BLE_ROLE_BROADCASTER: 1 BLE_ROLE_OBSERVER: 0 19126 8168 @apache-mynewt-nimble_nimble_controller.a --- nimble/controller/include/controller/ble_ll.h | 18 ++ .../include/controller/ble_ll_conn.h | 14 ++ .../include/controller/ble_ll_scan.h | 8 + nimble/controller/src/ble_ll.c | 114 ++++++++-- nimble/controller/src/ble_ll_adv.c | 52 ++++- nimble/controller/src/ble_ll_conn.c | 154 +++++++++++--- nimble/controller/src/ble_ll_conn_hci.c | 67 +++++- nimble/controller/src/ble_ll_conn_priv.h | 2 + nimble/controller/src/ble_ll_ctrl.c | 196 ++++++++++++++---- nimble/controller/src/ble_ll_hci.c | 51 ++++- nimble/controller/src/ble_ll_resolv.c | 25 ++- nimble/controller/src/ble_ll_scan.c | 58 +++++- nimble/controller/src/ble_ll_scan_aux.c | 19 +- nimble/controller/src/ble_ll_sched.c | 87 ++++++-- nimble/controller/src/ble_ll_supp_cmd.c | 87 +++++++- nimble/controller/src/ble_ll_sync.c | 2 +- nimble/controller/src/ble_ll_whitelist.c | 18 +- nimble/controller/syscfg.yml | 36 +++- nimble/syscfg.yml | 1 + nimble/transport/uart/src/ble_hci_uart.c | 2 + 20 files changed, 860 insertions(+), 151 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index dfda8cfeb4..898907a19d 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -108,11 +108,13 @@ struct ble_ll_obj /* Current Link Layer state */ uint8_t ll_state; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* Number of ACL data packets supported */ uint8_t ll_num_acl_pkts; /* ACL data packet size */ uint16_t ll_acl_pkt_size; +#endif /* Preferred PHY's */ uint8_t ll_pref_tx_phys; @@ -129,14 +131,18 @@ struct ble_ll_obj struct ble_ll_pkt_q ll_rx_pkt_q; /* Packet transmit queue */ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) struct ble_npl_event ll_tx_pkt_ev; +#endif struct ble_ll_pkt_q ll_tx_pkt_q; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* Data buffer overflow event */ struct ble_npl_event ll_dbuf_overflow_ev; /* Number of completed packets event */ struct ble_npl_event ll_comp_pkt_ev; +#endif /* HW error callout */ struct ble_npl_callout ll_hw_err_timer; @@ -214,12 +220,24 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; /* States */ #define BLE_LL_STATE_STANDBY (0) +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #define BLE_LL_STATE_ADV (1) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) #define BLE_LL_STATE_SCANNING (2) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_LL_STATE_CONNECTION (4) +#endif +#if MYNEWT_VAL(BLE_LL_DTM) #define BLE_LL_STATE_DTM (5) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) #define BLE_LL_STATE_SYNC (6) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) #define BLE_LL_STATE_SCAN_AUX (7) +#endif /* LL Features */ #define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001) diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h index 7128dcb966..c3073c6e7d 100644 --- a/nimble/controller/include/controller/ble_ll_conn.h +++ b/nimble/controller/include/controller/ble_ll_conn.h @@ -34,8 +34,13 @@ extern "C" { /* Roles */ #define BLE_LL_CONN_ROLE_NONE (0) + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_LL_CONN_ROLE_MASTER (1) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) #define BLE_LL_CONN_ROLE_SLAVE (2) +#endif /* Connection states */ #define BLE_LL_CONN_STATE_IDLE (0) @@ -370,8 +375,17 @@ struct ble_ll_conn_sm #define CONN_F_AUX_CONN_REQ(csm) ((csm)->csmflags.cfbit.aux_conn_req) /* Role */ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define CONN_IS_MASTER(csm) (csm->conn_role == BLE_LL_CONN_ROLE_MASTER) +#else +#define CONN_IS_MASTER(csm) (false) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) #define CONN_IS_SLAVE(csm) (csm->conn_role == BLE_LL_CONN_ROLE_SLAVE) +#else +#define CONN_IS_SLAVE(csm) (false) +#endif /* * Given a handle, returns an active connection state machine (or NULL if the diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h index 77f9fa4265..a44e431379 100644 --- a/nimble/controller/include/controller/ble_ll_scan.h +++ b/nimble/controller/include/controller/ble_ll_scan.h @@ -152,14 +152,18 @@ struct ble_ll_scan_sm struct ble_ll_scan_phy *scanp_next; struct ble_ll_scan_phy scan_phys[BLE_LL_SCAN_PHY_NUMBER]; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* Connection sm for initiator scan */ struct ble_ll_conn_sm *connsm; +#endif }; /* Scan types */ #define BLE_SCAN_TYPE_PASSIVE (BLE_HCI_SCAN_TYPE_PASSIVE) #define BLE_SCAN_TYPE_ACTIVE (BLE_HCI_SCAN_TYPE_ACTIVE) +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SCAN_TYPE_INITIATE (2) +#endif /*---- HCI ----*/ /* Set scanning parameters */ @@ -219,7 +223,11 @@ uint8_t *ble_ll_scan_get_local_rpa(void); void ble_ll_scan_sm_stop(int chk_disable); /* Resume scanning */ +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) void ble_ll_scan_chk_resume(void); +#else +static inline void ble_ll_scan_chk_resume(void) { }; +#endif /* Called when wait for response timer expires in scanning mode */ void ble_ll_scan_wfr_timer_exp(void); diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index b5a527abb8..0560b61da4 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -226,8 +226,10 @@ STATS_NAME_START(ble_ll_stats) STATS_NAME_END(ble_ll_stats) static void ble_ll_event_rx_pkt(struct ble_npl_event *ev); +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static void ble_ll_event_tx_pkt(struct ble_npl_event *ev); static void ble_ll_event_dbuf_overflow(struct ble_npl_event *ev); +#endif #if MYNEWT @@ -579,10 +581,23 @@ ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext) * Test specification extends this also to initiating. */ - if (g_ble_ll_conn_create_sm.connsm || ble_ll_scan_enabled() || - (!hci_adv_ext && ble_ll_adv_enabled())) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + if (g_ble_ll_conn_create_sm.connsm) { + return BLE_ERR_CMD_DISALLOWED; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + if (ble_ll_scan_enabled()){ return BLE_ERR_CMD_DISALLOWED; } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + if (!hci_adv_ext && ble_ll_adv_enabled()) { + return BLE_ERR_CMD_DISALLOWED; + } +#endif if (!ble_ll_is_valid_random_addr(cmd->addr)) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -591,12 +606,14 @@ ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext) memcpy(g_random_addr, cmd->addr, BLE_DEV_ADDR_LEN); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) /* For instance 0 we need same address if legacy advertising might be * used. If extended advertising is in use than this command doesn't * affect instance 0. */ if (!hci_adv_ext) ble_ll_adv_set_random_addr(cmd->addr, 0); +#endif #endif return BLE_ERR_SUCCESS; @@ -670,18 +687,23 @@ ble_ll_wfr_timer_exp(void *arg) /* If we have started a reception, there is nothing to do here */ if (!rx_start) { switch (lls) { +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_LL_STATE_ADV: ble_ll_adv_wfr_timer_exp(); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_STATE_CONNECTION: ble_ll_conn_wfr_timer_exp(); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_LL_STATE_SCANNING: ble_ll_scan_wfr_timer_exp(); break; -#if MYNEWT_VAL(BLE_LL_DTM) - case BLE_LL_STATE_DTM: - ble_ll_dtm_wfr_timer_exp(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + case BLE_LL_STATE_SCAN_AUX: + ble_ll_scan_aux_wfr_timer_exp(); break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) @@ -689,9 +711,10 @@ ble_ll_wfr_timer_exp(void *arg) ble_ll_sync_wfr_timer_exp(); break; #endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - case BLE_LL_STATE_SCAN_AUX: - ble_ll_scan_aux_wfr_timer_exp(); +#endif +#if MYNEWT_VAL(BLE_LL_DTM) + case BLE_LL_STATE_DTM: + ble_ll_dtm_wfr_timer_exp(); break; #endif default: @@ -708,6 +731,7 @@ ble_ll_wfr_timer_exp(void *arg) * Context: Link layer task * */ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static void ble_ll_tx_pkt_in(void) { @@ -747,6 +771,7 @@ ble_ll_tx_pkt_in(void) ble_ll_conn_tx_pkt_in(om, handle, length); } } +#endif /** * Count Link Layer statistics for received PDUs @@ -763,7 +788,12 @@ ble_ll_count_rx_stats(struct ble_mbuf_hdr *hdr, uint16_t len, uint8_t pdu_type) bool connection_data; crcok = BLE_MBUF_HDR_CRC_OK(hdr); + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) connection_data = (BLE_MBUF_HDR_RX_STATE(hdr) == BLE_LL_STATE_CONNECTION); +#else + connection_data = false; +#endif #if MYNEWT_VAL(BLE_LL_DTM) /* Reuse connection stats for DTM */ @@ -830,22 +860,22 @@ ble_ll_rx_pkt_in(void) /* Process the data or advertising pdu */ /* Process the PDU */ switch (BLE_MBUF_HDR_RX_STATE(ble_hdr)) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_STATE_CONNECTION: ble_ll_conn_rx_data_pdu(m, ble_hdr); /* m is going to be free by function above */ m = NULL; break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_LL_STATE_ADV: ble_ll_adv_rx_pkt_in(pdu_type, rxbuf, ble_hdr); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_LL_STATE_SCANNING: ble_ll_scan_rx_pkt_in(pdu_type, m, ble_hdr); break; -#if MYNEWT_VAL(BLE_LL_DTM) - case BLE_LL_STATE_DTM: - ble_ll_dtm_rx_pkt_in(m, ble_hdr); - break; -#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) case BLE_LL_STATE_SYNC: ble_ll_sync_rx_pkt_in(m, ble_hdr); @@ -855,6 +885,12 @@ ble_ll_rx_pkt_in(void) case BLE_LL_STATE_SCAN_AUX: ble_ll_scan_aux_rx_pkt_in(m, ble_hdr); break; +#endif +#endif +#if MYNEWT_VAL(BLE_LL_DTM) + case BLE_LL_STATE_DTM: + ble_ll_dtm_rx_pkt_in(m, ble_hdr); + break; #endif default: /* Any other state should never occur */ @@ -883,6 +919,7 @@ ble_ll_rx_pdu_in(struct os_mbuf *rxpdu) ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev); } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /** * Called to put a packet on the Link Layer transmit packet queue. * @@ -913,6 +950,7 @@ ble_ll_data_buffer_overflow(void) { ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev); } +#endif /** * Called when a HW error occurs. @@ -970,20 +1008,20 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) pdu_type); switch (g_ble_ll_data.ll_state) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_STATE_CONNECTION: rc = ble_ll_conn_rx_isr_start(rxhdr, ble_phy_access_addr_get()); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTERL) case BLE_LL_STATE_ADV: rc = ble_ll_adv_rx_isr_start(pdu_type); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_LL_STATE_SCANNING: rc = ble_ll_scan_rx_isr_start(pdu_type, &rxhdr->rxinfo.flags); break; -#if MYNEWT_VAL(BLE_LL_DTM) - case BLE_LL_STATE_DTM: - rc = ble_ll_dtm_rx_isr_start(rxhdr, ble_phy_access_addr_get()); - break; -#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) case BLE_LL_STATE_SYNC: rc = ble_ll_sync_rx_isr_start(pdu_type, rxhdr); @@ -993,6 +1031,12 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) case BLE_LL_STATE_SCAN_AUX: rc = ble_ll_scan_aux_rx_isr_start(pdu_type, rxhdr); break; +#endif +#endif +#if MYNEWT_VAL(BLE_LL_DTM) + case BLE_LL_STATE_DTM: + rc = ble_ll_dtm_rx_isr_start(rxhdr, ble_phy_access_addr_get()); + break; #endif default: /* Should not be in this state! */ @@ -1044,12 +1088,14 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) } #endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_CONNECTION) { rc = ble_ll_conn_rx_isr_end(rxbuf, rxhdr); return rc; } +#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_SYNC) { rc = ble_ll_sync_rx_isr_end(rxbuf, rxhdr); return rc; @@ -1097,6 +1143,7 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) /* Hand packet to the appropriate state machine (if crc ok) */ rxpdu = NULL; switch (BLE_MBUF_HDR_RX_STATE(rxhdr)) { +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_LL_STATE_ADV: if (!badpkt) { rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); @@ -1106,6 +1153,8 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) } rc = ble_ll_adv_rx_isr_end(pdu_type, rxpdu, crcok); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_LL_STATE_SCANNING: if (!badpkt) { rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN); @@ -1125,6 +1174,7 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) } rc = ble_ll_scan_aux_rx_isr_end(rxpdu, crcok); break; +#endif #endif default: rc = -1; @@ -1181,6 +1231,7 @@ ble_ll_event_rx_pkt(struct ble_npl_event *ev) ble_ll_rx_pkt_in(); } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static void ble_ll_event_tx_pkt(struct ble_npl_event *ev) { @@ -1198,6 +1249,7 @@ ble_ll_event_comp_pkts(struct ble_npl_event *ev) { ble_ll_conn_num_comp_pkts_event_send(NULL); } +#endif /** * Link Layer task. @@ -1314,9 +1366,11 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) { return BLE_ERR_CMD_DISALLOWED; } +#endif if ((cmd->bit_num > 0x3F) || (cmd->val > 1)) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -1423,19 +1477,23 @@ ble_ll_reset(void) OS_ENTER_CRITICAL(sr); ble_phy_disable(); ble_ll_sched_stop(); +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) ble_ll_scan_reset(); +#endif ble_ll_rfmgmt_reset(); OS_EXIT_CRITICAL(sr); +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) /* Stop any advertising */ ble_ll_adv_reset(); +#endif #if MYNEWT_VAL(BLE_LL_DTM) ble_ll_dtm_reset(); #endif /* Stop sync */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) ble_ll_sync_reset(); #endif @@ -1450,8 +1508,10 @@ ble_ll_reset(void) g_ble_ll_data.ll_pref_tx_phys = 0; g_ble_ll_data.ll_pref_rx_phys = 0; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* Reset connection module */ ble_ll_conn_module_reset(); +#endif /* All this does is re-initialize the event masks so call the hci init */ ble_ll_hci_init(); @@ -1612,9 +1672,11 @@ ble_ll_init(void) /* Get pointer to global data object */ lldata = &g_ble_ll_data; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* Set acl pkt size and number */ lldata->ll_num_acl_pkts = MYNEWT_VAL(BLE_ACL_BUF_COUNT); lldata->ll_acl_pkt_size = MYNEWT_VAL(BLE_ACL_BUF_SIZE); +#endif /* Initialize eventq */ ble_npl_eventq_init(&lldata->ll_evq); @@ -1625,11 +1687,15 @@ ble_ll_init(void) /* Initialize transmit (from host) and receive packet (from phy) event */ ble_npl_event_init(&lldata->ll_rx_pkt_ev, ble_ll_event_rx_pkt, NULL); +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) ble_npl_event_init(&lldata->ll_tx_pkt_ev, ble_ll_event_tx_pkt, NULL); +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* Initialize data buffer overflow event and completed packets */ ble_npl_event_init(&lldata->ll_dbuf_overflow_ev, ble_ll_event_dbuf_overflow, NULL); ble_npl_event_init(&lldata->ll_comp_pkt_ev, ble_ll_event_comp_pkts, NULL); +#endif /* Initialize the HW error timer */ ble_npl_callout_init(&g_ble_ll_data.ll_hw_err_timer, @@ -1643,14 +1709,20 @@ ble_ll_init(void) /* Init the scheduler */ ble_ll_sched_init(); +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) /* Initialize advertiser */ ble_ll_adv_init(); +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) /* Initialize a scanner */ ble_ll_scan_init(); +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* Initialize the connection module */ ble_ll_conn_module_init(); +#endif /* Set the supported features. NOTE: we always support extended reject. */ features = BLE_LL_FEAT_EXTENDED_REJ; @@ -1696,8 +1768,10 @@ ble_ll_init(void) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) features |= BLE_LL_FEAT_PERIODIC_ADV; +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) ble_ll_sync_init(); #endif +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) features |= BLE_LL_FEAT_SYNC_TRANS_RECV; diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 64a3b4034c..8a6cd1fe56 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -42,6 +42,8 @@ #include "controller/ble_ll_rfmgmt.h" #include "ble_ll_conn_priv.h" +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + /* XXX: TODO * 1) Need to look at advertising and scan request PDUs. Do I allocate these * once? Do I use a different pool for smaller ones? Do I statically declare @@ -118,7 +120,9 @@ struct ble_ll_adv_sm struct os_mbuf *new_adv_data; struct os_mbuf *scan_rsp_data; struct os_mbuf *new_scan_rsp_data; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) uint8_t *conn_comp_ev; +#endif struct ble_npl_event adv_txdone_ev; struct ble_ll_sched_item adv_sch; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) @@ -954,6 +958,7 @@ struct aux_conn_rsp_data { * * @param advsm */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static uint8_t ble_ll_adv_aux_conn_rsp_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) @@ -1002,6 +1007,7 @@ ble_ll_adv_aux_conn_rsp_pdu_make(uint8_t *dptr, void *pducb_arg, return pdulen; } #endif +#endif /** * Called to indicate the advertising event is over. @@ -1750,6 +1756,7 @@ ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len) adv_filter_policy = cmd->filter_policy; switch (cmd->type) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD: adv_filter_policy = BLE_HCI_ADV_FILT_NONE; memcpy(advsm->peer_addr, cmd->peer_addr, BLE_DEV_ADDR_LEN); @@ -1769,6 +1776,7 @@ ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len) case BLE_HCI_ADV_TYPE_ADV_IND: props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND; break; +#endif case BLE_HCI_ADV_TYPE_ADV_NONCONN_IND: props = BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN; break; @@ -1935,11 +1943,13 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); #endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* If there is an event buf we need to free it */ if (advsm->conn_comp_ev) { ble_hci_trans_buf_free(advsm->conn_comp_ev); advsm->conn_comp_ev = NULL; } +#endif ble_ll_adv_active_chanset_clear(advsm); @@ -1962,6 +1972,7 @@ ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm *advsm) } #endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* * For high duty directed advertising we need to send connection * complete event with proper status @@ -1971,6 +1982,7 @@ ble_ll_adv_sm_stop_timeout(struct ble_ll_adv_sm *advsm) advsm->conn_comp_ev, advsm); advsm->conn_comp_ev = NULL; } +#endif /* Disable advertising */ ble_ll_adv_sm_stop(advsm); @@ -1992,11 +2004,13 @@ ble_ll_adv_sm_stop_limit_reached(struct ble_ll_adv_sm *advsm) * be used if HD directed advertising was terminated before timeout due to * events count limit. For now just use same code as with duration timeout. */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO, advsm->conn_comp_ev, advsm); advsm->conn_comp_ev = NULL; } +#endif /* Disable advertising */ ble_ll_adv_sm_stop(advsm); @@ -2629,7 +2643,6 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) { uint8_t adv_chan; uint8_t *addr; - uint8_t *evbuf; uint32_t start_delay_us; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) uint32_t access_addr; @@ -2657,16 +2670,17 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) * Get an event with which to send the connection complete event if * this is connectable */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { /* We expect this to be NULL but if not we wont allocate one... */ if (advsm->conn_comp_ev == NULL) { - evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); - if (!evbuf) { + advsm->conn_comp_ev = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + if (!advsm->conn_comp_ev) { return BLE_ERR_MEM_CAPACITY; } - advsm->conn_comp_ev = evbuf; } } +#endif /* Set advertising address */ if ((advsm->own_addr_type & 1) == 0) { @@ -3282,9 +3296,11 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, /* if legacy bit is set possible values are limited */ switch (props) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND: case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR: case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR: +#endif case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN: case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN: break; @@ -3293,6 +3309,12 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, goto done; } } else { +#if !MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } +#endif /* HD directed advertising allowed only on legacy PDUs */ if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { rc = BLE_ERR_INV_HCI_CMD_PARMS; @@ -4096,6 +4118,7 @@ ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len, * @param [in] addr_type Public address (0) or random address (1). * @return Return 1 if already connected, 0 otherwise. */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static int ble_ll_adv_already_connected(const uint8_t* addr, uint8_t addr_type) { @@ -4118,6 +4141,7 @@ ble_ll_adv_already_connected(const uint8_t* addr, uint8_t addr_type) return 0; } +#endif /** * Called when the LL receives a scan request or connection request @@ -4143,9 +4167,11 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) uint8_t *peer; struct ble_mbuf_hdr *ble_hdr; struct ble_ll_adv_sm *advsm; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) struct aux_conn_rsp_data rsp_data; #endif +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) struct ble_ll_resolv_entry *rl; #endif @@ -4252,6 +4278,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) STATS_INC(ble_ll_stats, scan_rsp_txg); } } else if (pdu_type == BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* See if the device is already connected */ if (ble_ll_adv_already_connected(peer, peer_addr_type)) { return -1; @@ -4284,6 +4311,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD); STATS_INC(ble_ll_stats, aux_conn_rsp_tx); } +#endif #endif } @@ -4300,6 +4328,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu) * * @return 0: no connection started. 1: connection started */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static int ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, struct ble_ll_adv_sm *advsm) @@ -4390,6 +4419,7 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, return valid; } +#endif /** * Called on phy rx pdu end when in advertising state. @@ -4498,9 +4528,11 @@ ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr) adv_event_over = 1; if (BLE_MBUF_HDR_CRC_OK(hdr)) { if (ptype == BLE_ADV_PDU_TYPE_CONNECT_IND) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (ble_ll_adv_conn_req_rxd(rxbuf, hdr, advsm)) { adv_event_over = 0; } +#endif } else { if ((ptype == BLE_ADV_PDU_TYPE_SCAN_REQ) && (hdr->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_TXD)) { @@ -4937,11 +4969,11 @@ ble_ll_adv_can_chg_whitelist(void) * * @return uint8_t* Pointer to event buffer */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) void ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) { - uint8_t *evbuf; struct ble_ll_adv_sm *advsm; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) @@ -4950,12 +4982,11 @@ ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, advsm = &g_ble_ll_adv_sm[0]; #endif - evbuf = advsm->conn_comp_ev; - assert(evbuf != NULL); + assert(advsm->conn_comp_ev != NULL); + ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, advsm->conn_comp_ev, + advsm); advsm->conn_comp_ev = NULL; - ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, advsm); - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) ble_ll_hci_ev_le_csa(connsm); #endif @@ -4967,6 +4998,7 @@ ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm, } #endif } +#endif /** * Returns the local resolvable private address currently being using by @@ -5128,3 +5160,5 @@ ble_ll_adv_init(void) ble_ll_adv_sm_init(&g_ble_ll_adv_sm[i]); } } + +#endif diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index 30a381e1ec..2fb65869ef 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -117,6 +117,11 @@ extern void bletest_completed_pkt(uint16_t handle); * 1) The current connection event has not ended but a schedule item starts */ +/* Global LL connection parameters */ +struct ble_ll_conn_global_params g_ble_ll_conn_params; + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + /* This is a dummy structure we use for the empty PDU */ struct ble_ll_empty_pdu { @@ -130,18 +135,19 @@ struct ble_ll_empty_pdu #error "Maximum # of connections is 254" #endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* Global connection complete event. Used when initiating */ uint8_t *g_ble_ll_conn_comp_ev; - -/* Global LL connection parameters */ -struct ble_ll_conn_global_params g_ble_ll_conn_params; +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) /* Global default sync transfer params */ struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params; #endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) struct ble_ll_conn_create_sm g_ble_ll_conn_create_sm; +#endif /* Pointer to current connection */ struct ble_ll_conn_sm *g_ble_ll_conn_cur_sm; @@ -443,6 +449,7 @@ ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint32_t *itvl_ticks, * * @return uint8_t* */ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) static uint8_t * ble_ll_init_get_conn_comp_ev(void) { @@ -454,6 +461,7 @@ ble_ll_init_get_conn_comp_ev(void) return evbuf; } +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) /** @@ -701,6 +709,7 @@ ble_ll_conn_start_rx_encrypt(void *arg) !CONN_IS_MASTER(connsm)); } +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static void ble_ll_conn_start_rx_unencrypt(void *arg) { @@ -710,6 +719,7 @@ ble_ll_conn_start_rx_unencrypt(void *arg) CONN_F_ENCRYPTED(connsm) = 0; ble_phy_encrypt_disable(); } +#endif static void ble_ll_conn_txend_encrypt(void *arg) @@ -721,6 +731,7 @@ ble_ll_conn_txend_encrypt(void *arg) ble_ll_conn_current_sm_over(connsm); } +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static void ble_ll_conn_rxend_unencrypt(void *arg) { @@ -730,6 +741,7 @@ ble_ll_conn_rxend_unencrypt(void *arg) CONN_F_ENCRYPTED(connsm) = 0; ble_ll_conn_current_sm_over(connsm); } +#endif static void ble_ll_conn_continue_rx_encrypt(void *arg) @@ -978,7 +990,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) * packets can be let go. */ if (nextpkthdr && !ble_ll_ctrl_enc_allowed_pdu_tx(nextpkthdr) - && ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || + && (CONN_IS_MASTER(connsm) || !ble_ll_ctrl_is_start_enc_rsp(m))) { nextpkthdr = NULL; } @@ -1025,7 +1037,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) /* We will allow a next packet if it itself is allowed */ pkthdr = OS_MBUF_PKTHDR(connsm->cur_tx_pdu); if (nextpkthdr && !ble_ll_ctrl_enc_allowed_pdu_tx(nextpkthdr) - && ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || + && (CONN_IS_MASTER(connsm) || !ble_ll_ctrl_is_start_enc_rsp(connsm->cur_tx_pdu))) { nextpkthdr = NULL; } @@ -1094,9 +1106,11 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) ble_ll_pdu_tx_time_get(next_txlen, tx_phy_mode) + ble_ll_pdu_tx_time_get(cur_txlen, tx_phy_mode); +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { ticks += (BLE_LL_IFS + connsm->eff_max_rx_time); } +#endif ticks = os_cputime_usecs_to_ticks(ticks); if (CPUTIME_LT(os_cputime_get32() + ticks, next_event_time)) { @@ -1152,7 +1166,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) * overrun next scheduled item. */ if ((connsm->csmflags.cfbit.terminate_ind_rxd) || - ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && (md == 0) && + (CONN_IS_SLAVE(connsm) && (md == 0) && (connsm->cons_rxd_bad_crc == 0) && ((connsm->last_rxd_hdr_byte & BLE_LL_DATA_HDR_MD_MASK) == 0) && !ble_ll_ctrl_is_terminate_ind(hdr_byte, m->om_data[0]))) { @@ -1205,7 +1219,17 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) * The slave sends the PAUSE_ENC_RSP encrypted. The master sends * it unencrypted (note that link was already set unencrypted). */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: + CONN_F_ENCRYPTED(connsm) = 0; + connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; + connsm->enc_data.tx_encrypted = 0; + ble_phy_encrypt_disable(); + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: CONN_F_ENCRYPTED(connsm) = 1; connsm->enc_data.tx_encrypted = 1; ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, @@ -1217,11 +1241,11 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) } else { txend_func = ble_ll_conn_rxend_unencrypt; } - } else { - CONN_F_ENCRYPTED(connsm) = 0; - connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; - connsm->enc_data.tx_encrypted = 0; - ble_phy_encrypt_disable(); + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } } else { /* If encrypted set packet counter */ @@ -1278,7 +1302,9 @@ static int ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) { int rc; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) uint32_t usecs; +#endif uint32_t start; struct ble_ll_conn_sm *connsm; @@ -1319,7 +1345,9 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) ble_phy_mode_set(connsm->phy_data.tx_phy_mode, connsm->phy_data.rx_phy_mode); #endif - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: /* Set start time of transmission */ start = sch->start_time + g_ble_ll_sched_offset_ticks; rc = ble_phy_tx_set_start_time(start, sch->remainder); @@ -1345,7 +1373,10 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) STATS_INC(ble_ll_conn_stats, conn_ev_late); rc = BLE_LL_SCHED_STATE_DONE; } - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) if (CONN_F_ENCRYPTED(connsm)) { ble_phy_encrypt_enable(connsm->enc_data.rx_pkt_cntr, @@ -1401,6 +1432,11 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) /* Set next wakeup time to connection event end time */ rc = BLE_LL_SCHED_STATE_RUNNING; } + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } if (rc == BLE_LL_SCHED_STATE_DONE) { @@ -1432,6 +1468,7 @@ static int ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime, uint32_t add_usecs) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) int rc; uint16_t rem_bytes; uint32_t ticks; @@ -1487,6 +1524,9 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime, } return rc; +#else + return 1; +#endif } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) @@ -1527,6 +1567,7 @@ ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm) } #endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) static void ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm) { @@ -1588,6 +1629,7 @@ ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, connsm->min_ce_len = cc_params->min_ce_len; connsm->max_ce_len = cc_params->max_ce_len; } +#endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) @@ -1643,6 +1685,7 @@ ble_ll_conn_init_phy(struct ble_ll_conn_sm *connsm, int phy) #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) static void ble_ll_conn_create_set_params(struct ble_ll_conn_sm *connsm, uint8_t phy) { @@ -1658,6 +1701,7 @@ ble_ll_conn_create_set_params(struct ble_ll_conn_sm *connsm, uint8_t phy) connsm->conn_itvl_usecs = cc_params->conn_itvl_usecs; } #endif +#endif static void ble_ll_conn_set_csa(struct ble_ll_conn_sm *connsm, bool chsel) @@ -1998,8 +2042,10 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) { uint16_t latency; uint32_t itvl; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) uint32_t cur_ww; uint32_t max_ww; +#endif struct ble_ll_conn_upd_req *upd; uint32_t ticks; uint32_t usecs; @@ -2012,7 +2058,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) ble_ll_ctrl_terminate_start(connsm); } - if (CONN_F_TERMINATE_STARTED(connsm) && (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE)) { + if (CONN_F_TERMINATE_STARTED(connsm) && CONN_IS_SLAVE(connsm)) { /* Some of the devices waits whole connection interval to ACK our * TERMINATE_IND sent as a Slave. Since we are here it means we are still waiting for ACK. * Make sure we catch it in next connection event. @@ -2072,8 +2118,8 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) /* Set flag so we send connection update event */ upd = &connsm->conn_update_req; - if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) || - ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && + if (CONN_IS_MASTER(connsm) || + (CONN_IS_SLAVE(connsm) && IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) || (connsm->conn_itvl != upd->interval) || (connsm->slave_latency != upd->latency) || @@ -2208,6 +2254,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) #else itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_TICKS_PER_SLOT; #endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { cur_ww = ble_ll_utils_calc_window_widening(connsm->anchor_point, @@ -2221,6 +2268,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) connsm->slave_cur_window_widening = cur_ww; itvl += os_cputime_usecs_to_ticks(cur_ww + connsm->slave_cur_tx_win_usecs); } +#endif itvl -= g_ble_ll_sched_offset_ticks; connsm->ce_end_time = connsm->anchor_point + itvl; @@ -2246,9 +2294,13 @@ static int ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) { int rc; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) uint8_t *evbuf; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) uint32_t endtime; uint32_t usecs; +#endif /* XXX: TODO this assumes we received in 1M phy */ @@ -2273,6 +2325,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) * the transmit window offset from the end of the connection request. */ rc = 1; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { /* * With a 32.768 kHz crystal we dont care about the remaining usecs @@ -2334,6 +2387,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) } } } +#endif /* Send connection complete event to inform host of connection */ if (rc) { @@ -2350,9 +2404,9 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) CONN_F_CTRLR_PHY_UPDATE(connsm) = 1; } #endif - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - ble_ll_adv_send_conn_comp_ev(connsm, rxhdr); - } else { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: evbuf = ble_ll_init_get_conn_comp_ev(); ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, NULL); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) @@ -2368,6 +2422,16 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) * if it has some additional features to use. */ ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: + ble_ll_adv_send_conn_comp_ev(connsm, rxhdr); + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } } @@ -2676,6 +2740,7 @@ ble_ll_conn_event_halt(void) } } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) int ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu, struct ble_ll_scan_addr_data *addrd, @@ -2793,8 +2858,10 @@ ble_ll_conn_created_on_legacy(struct os_mbuf *rxpdu, ble_ll_conn_master_start(BLE_PHY_1M, csa, addrd, targeta); } +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) void ble_ll_conn_created_on_aux(struct os_mbuf *rxpdu, struct ble_ll_scan_addr_data *addrd, @@ -2814,6 +2881,7 @@ ble_ll_conn_created_on_aux(struct os_mbuf *rxpdu, ble_ll_conn_master_start(phy, 1, addrd, targeta); } +#endif #endif /* BLE_LL_CFG_FEAT_LL_EXT_ADV */ /** @@ -2984,11 +3052,13 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) * 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 MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) 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; } } +#endif /* * Discard the received PDU if the sequence number is the same @@ -3172,11 +3242,21 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) if (connsm->cons_rxd_bad_crc >= 2) { reply = 0; } else { - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: reply = CONN_F_LAST_TXD_MD(connsm); - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: /* A slave always responds with a packet */ reply = 1; + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } } } else { @@ -3290,7 +3370,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) #if (BLE_LL_BT5_PHY_SUPPORTED == 1) if (BLE_LL_LLID_IS_CTRL(hdr_byte) && - (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && + CONN_IS_SLAVE(connsm) && (opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) { connsm->phy_tx_transition = ble_ll_ctrl_phy_tx_transition_get(rxbuf[3]); @@ -3315,11 +3395,21 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) connsm->rxd_disconnect_reason = rxbuf[3]; } - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: reply = CONN_F_LAST_TXD_MD(connsm) || (hdr_byte & BLE_LL_DATA_HDR_MD_MASK); - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: /* A slave always replies */ reply = 1; + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } } @@ -3407,9 +3497,11 @@ ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, lifo = 1; break; case BLE_LL_CTRL_PAUSE_ENC_RSP: +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { lifo = 1; } +#endif break; case BLE_LL_CTRL_ENC_REQ: case BLE_LL_CTRL_ENC_RSP: @@ -3480,7 +3572,7 @@ ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t length) os_mbuf_free_chain(om); } } - +#endif /** * Called to set the global channel mask that we use for all connections. * @@ -3490,7 +3582,9 @@ ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t length) void ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) struct ble_ll_conn_sm *connsm; +#endif struct ble_ll_conn_global_params *conn_params; /* Do nothing if same channel map */ @@ -3503,14 +3597,17 @@ ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap) conn_params->num_used_chans = num_used_chans; memcpy(conn_params->master_chan_map, chanmap, BLE_LL_CONN_CHMAP_LEN); +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* Perform channel map update */ SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD); } } +#endif } +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /** * Called when a device has received a connect request while advertising and * the connect request has passed the advertising filter policy and is for @@ -3524,6 +3621,7 @@ ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap) * * @return 0: connection not started; 1 connecton started */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) int ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr, bool force_csa2) @@ -3642,6 +3740,7 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr, STATS_INC(ble_ll_conn_stats, slave_rxd_bad_conn_req_params); return 0; } +#endif #define MAX_TIME_UNCODED(_maxbytes) \ ble_ll_pdu_tx_time_get(_maxbytes + BLE_LL_DATA_MIC_LEN, \ @@ -3672,6 +3771,7 @@ ble_ll_conn_module_reset(void) ble_ll_conn_end(connsm, BLE_ERR_SUCCESS); } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* Free the global connection complete event if there is one */ if (g_ble_ll_conn_comp_ev) { ble_hci_trans_buf_free(g_ble_ll_conn_comp_ev); @@ -3680,6 +3780,7 @@ ble_ll_conn_module_reset(void) /* Reset connection we are attempting to create */ g_ble_ll_conn_create_sm.connsm = NULL; +#endif /* Now go through and end all the connections */ while (1) { @@ -3791,3 +3892,4 @@ ble_ll_conn_module_init(void) /* Call reset to finish reset of initialization */ ble_ll_conn_module_reset(); } +#endif diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index 6489af0d5b..2e50713e84 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -34,6 +34,8 @@ #include "controller/ble_ll_adv.h" #include "ble_ll_conn_priv.h" +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + /* * Used to limit the rate at which we send the number of completed packets * event to the host. This is the os time at which we can send an event. @@ -158,7 +160,9 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, enh_ev->peer_addr_type = connsm->peer_addr_type; memcpy(enh_ev->peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN); - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: if (connsm->inita_identity_used) { /* We used identity address in CONNECT_IND which can be just * fine if @@ -173,8 +177,16 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, } else { rpa = NULL; } - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: rpa = ble_ll_adv_get_local_rpa(advsm); + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } if (rpa) { @@ -189,20 +201,33 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, #endif if (enh_ev->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: rpa = ble_ll_scan_get_peer_rpa(); - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: rpa = ble_ll_adv_get_peer_rpa(advsm); + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } + memcpy(enh_ev->peer_rpa, rpa, BLE_DEV_ADDR_LEN); } enh_ev->conn_itvl = htole16(connsm->conn_itvl); enh_ev->conn_latency = htole16(connsm->slave_latency); enh_ev->supervision_timeout = htole16(connsm->supervision_tmo); +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { enh_ev->mca = connsm->master_sca; } +#endif } ble_ll_hci_event_send(hci_ev); @@ -227,9 +252,11 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, ev->conn_itvl = htole16(connsm->conn_itvl); ev->conn_latency = htole16(connsm->slave_latency); ev->supervision_timeout = htole16(connsm->supervision_tmo); +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { ev->mca = connsm->master_sca; } +#endif } ble_ll_hci_event_send(hci_ev); @@ -826,10 +853,12 @@ ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len) */ if (!connsm->csmflags.cfbit.rxd_features && !IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && !(ble_ll_read_supp_features() & BLE_LL_FEAT_SLAVE_INIT)) { return BLE_ERR_CMD_DISALLOWED; } +#endif ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); } @@ -880,9 +909,11 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) /* See if this feature is supported on both sides */ if ((connsm->conn_features & BLE_LL_FEAT_CONN_PARM_REQ) == 0) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { return BLE_ERR_UNSUPP_REM_FEATURE; } +#endif ctrl_proc = BLE_LL_CTRL_PROC_CONN_UPDATE; } else { ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ; @@ -895,14 +926,24 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) * slave. */ if (connsm->csmflags.cfbit.awaiting_host_reply) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - return BLE_ERR_LMP_COLLISION; - } else { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: connsm->csmflags.cfbit.awaiting_host_reply = 0; /* XXX: If this fails no reject ind will be sent! */ ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, BLE_ERR_LMP_COLLISION); + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: + return BLE_ERR_LMP_COLLISION; + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } } @@ -910,11 +951,13 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) * If we are a slave and the master has initiated the channel map * update procedure we should deny the slave request for now. */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->csmflags.cfbit.chanmap_update_scheduled) { if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { return BLE_ERR_DIFF_TRANS_COLL; } } +#endif /* Retrieve command data */ hcu = &connsm->conn_param_req; @@ -1301,6 +1344,7 @@ ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len, *rsplen = sizeof(*rsp); return rc; } +#endif /** * Called when the host issues the LE command "set host channel classification" @@ -1334,6 +1378,8 @@ ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_SUCCESS; } +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) int ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, @@ -1421,8 +1467,10 @@ ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len) connsm = ble_ll_conn_find_active_conn(le16toh(cmd->conn_handle)); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) } else if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { rc = BLE_ERR_UNSPECIFIED; +#endif } else if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) { /* * The specification does not say what to do here but the host should @@ -1475,11 +1523,13 @@ ble_ll_conn_hci_le_ltk_reply(const uint8_t *cmdbuf, uint8_t len, goto ltk_key_cmd_complete; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* Should never get this if we are a master! */ if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { rc = BLE_ERR_UNSPECIFIED; goto ltk_key_cmd_complete; } +#endif /* The connection should be awaiting a reply. If not, just discard */ if (connsm->enc_data.enc_state != CONN_ENC_S_LTK_REQ_WAIT) { @@ -1532,11 +1582,13 @@ ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len, goto ltk_key_cmd_complete; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* Should never get this if we are a master! */ if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { rc = BLE_ERR_UNSPECIFIED; goto ltk_key_cmd_complete; } +#endif /* The connection should be awaiting a reply. If not, just discard */ if (connsm->enc_data.enc_state != CONN_ENC_S_LTK_REQ_WAIT) { @@ -1916,3 +1968,4 @@ ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_SUCCESS; } #endif +#endif diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h index d1a4a3e884..73e4106074 100644 --- a/nimble/controller/src/ble_ll_conn_priv.h +++ b/nimble/controller/src/ble_ll_conn_priv.h @@ -64,6 +64,7 @@ struct ble_ll_conn_global_params { uint8_t master_chan_map[BLE_LL_CONN_CHMAP_LEN]; uint8_t num_used_chans; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) uint8_t supp_max_tx_octets; uint8_t supp_max_rx_octets; uint8_t conn_init_max_tx_octets; @@ -74,6 +75,7 @@ struct ble_ll_conn_global_params uint16_t conn_init_max_tx_time_coded; uint16_t supp_max_tx_time; uint16_t supp_max_rx_time; +#endif }; extern struct ble_ll_conn_global_params g_ble_ll_conn_params; diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c index 94d73a9bb5..432045e675 100644 --- a/nimble/controller/src/ble_ll_ctrl.c +++ b/nimble/controller/src/ble_ll_ctrl.c @@ -31,6 +31,8 @@ #include "controller/ble_ll_sync.h" #include "ble_ll_conn_priv.h" +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + /* To use spec sample data for testing */ #undef BLE_LL_ENCRYPT_USE_TEST_DATA @@ -314,8 +316,7 @@ ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr, * update the connection parameters. This means that the previous * check is all we need for a master (when receiving a request). */ - if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) || - (opcode == BLE_LL_CTRL_CONN_PARM_RSP)) { + if (CONN_IS_SLAVE(connsm) || (opcode == BLE_LL_CTRL_CONN_PARM_RSP)) { /* * Not sure what to do about the slave. It is possible that the * current connection parameters are not the same ones as the local host @@ -488,11 +489,13 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t * break; case BLE_LL_CTRL_CONN_PARM_REQ: BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_CONN_PARM_REQ); +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL); connsm->reject_reason = BLE_ERR_SUCCESS; return BLE_LL_CTRL_CONN_UPDATE_IND; } +#endif /* note: fall-through intentional */ case BLE_LL_CTRL_CONN_PARM_RSP: ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ; @@ -674,6 +677,7 @@ ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm) } } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /** * * There is probably a better way for the controller to choose which PHY use. @@ -713,6 +717,7 @@ ble_ll_ctrl_find_new_phy(uint8_t phy_mask_prefs) * @param ctrdata: Pointer to where CtrData of UPDATE_IND pdu starts * @param slave_req flag denoting if slave requested this. 0: no 1:yes */ + static void ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *ctrdata, int slave_req) @@ -729,10 +734,12 @@ ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, rx_phys = dptr[1]; /* If we are master, check if slave requested symmetric PHY */ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { is_slave_sym = tx_phys == rx_phys; is_slave_sym &= __builtin_popcount(tx_phys) == 1; } +#endif /* Get m_to_s and s_to_m masks */ if (slave_req) { @@ -818,6 +825,7 @@ ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, ctrdata[1] = s_to_m; put_le16(ctrdata + 2, instant); } +#endif /** * Create a LL_PHY_REQ or LL_PHY_RSP pdu @@ -872,7 +880,9 @@ ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req, err = ble_ll_ctrl_proc_with_instant_initiated(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: if (err) { ble_ll_ctrl_rej_ext_ind_make(BLE_LL_CTRL_PHY_REQ, err, rsp); rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; @@ -885,7 +895,10 @@ ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req, ble_ll_ctrl_phy_update_ind_make(connsm, req, rsp, 1); rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND; } - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: /* XXX: deal with other control procedures that we need to stop */ if (err) { if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) { @@ -913,7 +926,13 @@ ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req, /* Start response timer */ connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE; ble_ll_ctrl_start_rsp_timer(connsm); + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } + return rsp_opcode; } @@ -933,7 +952,10 @@ ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t rsp_opcode; rsp_opcode = BLE_ERR_MAX; - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) { ble_ll_ctrl_phy_update_ind_make(connsm, dptr, rsp, 0); ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer); @@ -946,8 +968,16 @@ ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, * * XXX: TODO count some stat? */ - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP; + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } /* NOTE: slave should never receive one of these */ @@ -976,9 +1006,11 @@ ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) uint16_t instant; uint16_t delta; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { return BLE_LL_CTRL_UNKNOWN_RSP; } +#endif /* * Reception stops the procedure response timer but does not @@ -1434,9 +1466,11 @@ static uint8_t ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspdata) { - if (connsm->conn_role != BLE_LL_CONN_ROLE_SLAVE) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { return BLE_LL_CTRL_UNKNOWN_RSP; } +#endif connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_TO_BE_SENT; @@ -1479,15 +1513,27 @@ ble_ll_ctrl_rx_start_enc_req(struct ble_ll_conn_sm *connsm) /* Only master should receive start enc request */ rc = BLE_ERR_MAX; - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: /* We only want to send a START_ENC_RSP if we havent yet */ if (connsm->enc_data.enc_state == CONN_ENC_S_START_ENC_REQ_WAIT) { connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_RSP_WAIT; rc = BLE_LL_CTRL_START_ENC_RSP; } - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: rc = BLE_LL_CTRL_UNKNOWN_RSP; + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } + return rc; } @@ -1502,7 +1548,7 @@ ble_ll_ctrl_rx_pause_enc_req(struct ble_ll_conn_sm *connsm) * ignore it... */ rc = BLE_ERR_MAX; - if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && + if (CONN_IS_SLAVE(connsm) && (connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED)) { rc = BLE_LL_CTRL_PAUSE_ENC_RSP; } else { @@ -1525,16 +1571,28 @@ ble_ll_ctrl_rx_pause_enc_rsp(struct ble_ll_conn_sm *connsm) { int rc; - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: rc = BLE_LL_CTRL_PAUSE_ENC_RSP; - } else if (connsm->enc_data.enc_state == CONN_ENC_S_PAUSE_ENC_RSP_WAIT) { - /* Master sends back unencrypted LL_PAUSE_ENC_RSP. - * From this moment encryption is paused. - */ - rc = BLE_ERR_MAX; - connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; - } else { - rc = BLE_LL_CTRL_UNKNOWN_RSP; + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: + if (connsm->enc_data.enc_state == CONN_ENC_S_PAUSE_ENC_RSP_WAIT) { + /* Master sends back unencrypted LL_PAUSE_ENC_RSP. + * From this moment encryption is paused. + */ + rc = BLE_ERR_MAX; + connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; + } else { + rc = BLE_LL_CTRL_UNKNOWN_RSP; + } + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } return rc; @@ -1559,9 +1617,9 @@ ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm) return BLE_ERR_MAX; } - /* If master, we are done. Stop control procedure and sent event to host */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { - + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT); /* We are encrypted */ @@ -1570,7 +1628,10 @@ ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm) ble_ll_conn_auth_pyld_timer_start(connsm); #endif rc = BLE_ERR_MAX; - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: /* Procedure has completed but slave needs to send START_ENC_RSP */ rc = BLE_LL_CTRL_START_ENC_RSP; @@ -1578,6 +1639,11 @@ ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm) if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) { ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT); } + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } /* @@ -1692,14 +1758,24 @@ ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, uint8_t *rsp, { uint8_t rsp_opcode; - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - /* Create a connection parameter response */ - ble_ll_ctrl_conn_param_pdu_make(connsm, rsp + 1, req); - rsp_opcode = BLE_LL_CTRL_CONN_PARM_RSP; - } else { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: /* Create a connection update pdu */ ble_ll_ctrl_conn_upd_make(connsm, rsp + 1, req); rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND; + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: + /* Create a connection parameter response */ + ble_ll_ctrl_conn_param_pdu_make(connsm, rsp + 1, req); + rsp_opcode = BLE_LL_CTRL_CONN_PARM_RSP; + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } return rsp_opcode; @@ -1732,14 +1808,24 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, switch (connsm->cur_ctrl_proc) { case BLE_LL_CTRL_PROC_CONN_PARAM_REQ: if (opcode == BLE_LL_CTRL_REJECT_IND_EXT) { - /* As a master we should send connection update indication in this point */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { + #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: + /* As a master we should send connection update indication in this point */ rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND; ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL); connsm->reject_reason = BLE_ERR_SUCCESS; - } else { + break; + #endif + #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); ble_ll_hci_ev_conn_update(connsm, ble_error); + break; + #endif + default: + BLE_LL_ASSERT(0); + break; } } break; @@ -1792,9 +1878,11 @@ ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr) struct ble_ll_conn_upd_req *reqdata; /* Only a slave should receive this */ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { return BLE_LL_CTRL_UNKNOWN_RSP; } +#endif /* Retrieve parameters */ reqdata = &connsm->conn_update_req; @@ -1913,12 +2001,12 @@ ble_ll_ctrl_rx_feature_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, * requests if we are a slave. */ if (opcode == BLE_LL_CTRL_SLAVE_FEATURE_REQ) { - if (connsm->conn_role != BLE_LL_CONN_ROLE_MASTER) { + if (!CONN_IS_MASTER(connsm)) { return BLE_LL_CTRL_UNKNOWN_RSP; } } else { /* XXX: not sure this is correct but do it anyway */ - if (connsm->conn_role != BLE_LL_CONN_ROLE_SLAVE) { + if (!CONN_IS_SLAVE(connsm)) { return BLE_LL_CTRL_UNKNOWN_RSP; } } @@ -2018,15 +2106,24 @@ ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, * transaction collision error code. */ if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) { - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); - ble_ll_hci_ev_conn_update(connsm, BLE_ERR_LMP_COLLISION); - } else { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: /* The master sends reject ind ext w/error code 0x23 */ rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ; rspbuf[2] = BLE_ERR_LMP_COLLISION; return rsp_opcode; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: + ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ); + ble_ll_hci_ev_conn_update(connsm, BLE_ERR_LMP_COLLISION); + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } } @@ -2034,6 +2131,7 @@ ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, * If we are a master and we currently performing a channel map * update procedure we need to return an error */ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) && (connsm->csmflags.cfbit.chanmap_update_scheduled)) { rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; @@ -2041,6 +2139,7 @@ ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, rspbuf[2] = BLE_ERR_DIFF_TRANS_COLL; return rsp_opcode; } +#endif /* Process the received connection parameter request */ rsp_opcode = ble_ll_ctrl_conn_param_pdu_proc(connsm, dptr, rspbuf, @@ -2055,9 +2154,11 @@ ble_ll_ctrl_rx_conn_param_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t rsp_opcode; /* A slave should never receive this response */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { return BLE_LL_CTRL_UNKNOWN_RSP; } +#endif /* * This case should never happen! It means that the slave initiated a @@ -2131,9 +2232,11 @@ ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr) uint16_t instant; uint16_t conn_events; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { return BLE_LL_CTRL_UNKNOWN_RSP; } +#endif /* If instant is in the past, we have to end the connection */ instant = get_le16(dptr + BLE_LL_CONN_CHMAP_LEN); @@ -2188,10 +2291,20 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc) ble_ll_ctrl_chanmap_req_make(connsm, ctrdata); break; case BLE_LL_CTRL_PROC_FEATURE_XCHG: - if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: opcode = BLE_LL_CTRL_FEATURE_REQ; - } else { + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: opcode = BLE_LL_CTRL_SLAVE_FEATURE_REQ; + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } put_le64(ctrdata, ble_ll_read_supp_features()); break; @@ -2849,6 +2962,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT; connsm->csmflags.cfbit.send_ltk_req = 1; break; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CTRL_START_ENC_RSP: if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED; @@ -2863,7 +2977,9 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) } break; #endif +#endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CTRL_PHY_REQ: if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { connsm->phy_tx_transition = @@ -2871,6 +2987,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) connsm->phy_data.req_pref_tx_phys_mask); } break; +#endif case BLE_LL_CTRL_PHY_UPDATE_IND: connsm->phy_tx_transition = ble_ll_ctrl_phy_tx_transition_get(txpdu->om_data[2]); @@ -2890,3 +3007,4 @@ ble_ll_ctrl_init_conn_sm(struct ble_ll_conn_sm *connsm) ble_npl_callout_init(&connsm->ctrl_proc_rsp_timer, &g_ble_ll_data.ll_evq, ble_ll_ctrl_proc_rsp_timer_cb, connsm); } +#endif diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 7bbc6774c5..d368672914 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -322,8 +322,14 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen) { struct ble_hci_le_rd_buf_size_rp *rp = (void *) rspbuf; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size); rp->data_packets = g_ble_ll_data.ll_num_acl_pkts; +#else + /* TODO check if can just not support this command */ + rp->data_len = 0; + rp->data_packets = 0; +#endif *rsplen = sizeof(*rp); return BLE_ERR_SUCCESS; @@ -410,6 +416,7 @@ ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys, * * @return int */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) static int ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) { @@ -426,6 +433,7 @@ ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) return rc; } #endif +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) /** @@ -658,6 +666,7 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) /** HCI LE read maximum advertising data length command. Returns the controllers * max supported advertising data length; * @@ -695,6 +704,7 @@ ble_ll_adv_rd_sup_adv_sets(uint8_t *rspbuf, uint8_t *rsplen) *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; } +#endif static bool ble_ll_is_valid_adv_mode(uint8_t ocf) @@ -887,6 +897,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_set_random_addr(cmdbuf, len, false); #endif break; +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_HCI_OCF_LE_SET_ADV_PARAMS: rc = ble_ll_adv_set_adv_params(cmdbuf, len); break; @@ -904,12 +915,15 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, case BLE_HCI_OCF_LE_SET_ADV_ENABLE: rc = ble_ll_hci_adv_set_enable(cmdbuf, len); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_HCI_OCF_LE_SET_SCAN_PARAMS: rc = ble_ll_scan_hci_set_params(cmdbuf, len); break; case BLE_HCI_OCF_LE_SET_SCAN_ENABLE: rc = ble_ll_scan_hci_set_enable(cmdbuf, len); break; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_CREATE_CONN: rc = ble_ll_conn_hci_create(cmdbuf, len); break; @@ -918,6 +932,8 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_conn_create_cancel(cb); } break; +#endif +#endif case BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE: if (len == 0) { rc = ble_ll_whitelist_read_size(rspbuf, rsplen); @@ -934,18 +950,22 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, case BLE_HCI_OCF_LE_RMV_WHITE_LIST: rc = ble_ll_whitelist_rmv(cmdbuf, len); break; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_CONN_UPDATE: rc = ble_ll_conn_hci_update(cmdbuf, len); break; +#endif case BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS: rc = ble_ll_conn_hci_set_chan_class(cmdbuf, len); break; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_RD_CHAN_MAP: rc = ble_ll_conn_hci_rd_chan_map(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_RD_REM_FEAT: rc = ble_ll_conn_hci_read_rem_features(cmdbuf, len); break; +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) case BLE_HCI_OCF_LE_ENCRYPT: rc = ble_ll_hci_le_encrypt(cmdbuf, len, rspbuf, rsplen); @@ -957,15 +977,19 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, } break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_START_ENCRYPT: rc = ble_ll_conn_hci_le_start_encrypt(cmdbuf, len); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY: rc = ble_ll_conn_hci_le_ltk_reply(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY: rc = ble_ll_conn_hci_le_ltk_neg_reply(cmdbuf, len, rspbuf, rsplen); break; +#endif #endif case BLE_HCI_OCF_LE_RD_SUPP_STATES : if (len == 0) { @@ -985,12 +1009,14 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, } break; #endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_REM_CONN_PARAM_RR: rc = ble_ll_conn_hci_param_rr(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR: rc = ble_ll_conn_hci_param_nrr(cmdbuf, len, rspbuf, rsplen); break; +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) case BLE_HCI_OCF_LE_SET_DATA_LEN: rc = ble_ll_conn_hci_set_data_len(cmdbuf, len, rspbuf, rsplen); @@ -1042,6 +1068,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, break; #endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_RD_PHY: rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, len, rspbuf, rsplen); break; @@ -1052,6 +1079,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_conn_hci_le_set_phy(cmdbuf, len); break; #endif +#endif #if MYNEWT_VAL(BLE_LL_DTM) case BLE_HCI_OCF_LE_RX_TEST_V2: rc = ble_ll_hci_dtm_rx_test_v2(cmdbuf, len); @@ -1060,6 +1088,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_hci_dtm_tx_test_v2(cmdbuf, len); break; #endif +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR: rc = ble_ll_adv_hci_set_random_addr(cmdbuf, len); @@ -1106,6 +1135,8 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, break; #endif #endif +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM: rc = ble_ll_scan_hci_set_ext_params(cmdbuf, len); @@ -1113,10 +1144,12 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE: rc = ble_ll_scan_hci_set_ext_enable(cmdbuf, len); break; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_EXT_CREATE_CONN: rc = ble_ll_conn_hci_ext_create(cmdbuf, len); break; #endif +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: rc = ble_ll_sync_create(cmdbuf, len); @@ -1150,6 +1183,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_sync_receive_enable(cmdbuf, len); break; #endif +#endif #endif case BLE_HCI_OCF_LE_RD_TRANSMIT_POWER: if (len == 0) { @@ -1170,12 +1204,16 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER: rc = ble_ll_sync_transfer(cmdbuf, len, rspbuf, rsplen); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_HCI_OCF_LE_PERIODIC_ADV_SET_INFO_TRANSFER: rc = ble_ll_adv_periodic_set_info_transfer(cmdbuf, len, rspbuf, rsplen); break; +#endif case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS: rc = ble_ll_set_sync_transfer_params(cmdbuf, len, rspbuf, rsplen); break; @@ -1274,6 +1312,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, return rc; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) static int ble_ll_hci_disconnect(const uint8_t *cmdbuf, uint8_t len) { @@ -1293,6 +1332,7 @@ ble_ll_hci_disconnect(const uint8_t *cmdbuf, uint8_t len) return ble_ll_conn_hci_disconnect_cmd(cmd); } +#endif /** * Process a link control command sent from the host to the controller. The HCI @@ -1313,18 +1353,18 @@ ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf) int rc; switch (ocf) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_HCI_OCF_DISCONNECT_CMD: rc = ble_ll_hci_disconnect(cmdbuf, len); /* Send command status instead of command complete */ rc += (BLE_ERR_MAX + 1); break; - case BLE_HCI_OCF_RD_REM_VER_INFO: rc = ble_ll_conn_hci_rd_rem_ver_cmd(cmdbuf, len); /* Send command status instead of command complete */ rc += (BLE_ERR_MAX + 1); break; - +#endif default: rc = BLE_ERR_UNKNOWN_HCI_CMD; break; @@ -1518,9 +1558,11 @@ ble_ll_hci_status_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, int rc; switch (ocf) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_RD_RSSI: rc = ble_ll_conn_hci_rd_rssi(cmdbuf, len, rspbuf, rsplen); break; +#endif default: rc = BLE_ERR_UNKNOWN_HCI_CMD; break; @@ -1705,7 +1747,12 @@ ble_ll_hci_cmd_rx(uint8_t *cmdbuf, void *arg) int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg) { +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) ble_ll_acl_data_in(om); +#else + /* host should never send ACL in that case but if it does just ignore it */ + os_mbuf_free_chain(om); +#endif return 0; } diff --git a/nimble/controller/src/ble_ll_resolv.c b/nimble/controller/src/ble_ll_resolv.c index f85e26a8ad..86f8ea7830 100644 --- a/nimble/controller/src/ble_ll_resolv.c +++ b/nimble/controller/src/ble_ll_resolv.c @@ -50,14 +50,31 @@ struct ble_ll_resolv_entry g_ble_ll_resolv_list[MYNEWT_VAL(BLE_LL_RESOLV_LIST_SI static int ble_ll_is_controller_busy(void) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) if (ble_ll_sync_enabled()) { return 1; } #endif - return ble_ll_adv_enabled() || ble_ll_scan_enabled() || - g_ble_ll_conn_create_sm.connsm; +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + if (ble_ll_adv_enabled()) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + if (ble_ll_scan_enabled()) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + if (g_ble_ll_conn_create_sm.connsm) { + return 1; + } +#endif + + return 0; } /** * Called to determine if a change is allowed to the resolving list at this @@ -155,7 +172,9 @@ ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev) ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, g_ble_ll_resolv_data.rpa_tmo); +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) ble_ll_adv_rpa_timeout(); +#endif } /** diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 6e78f3245d..987ab463ff 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -43,6 +43,8 @@ #include "controller/ble_ll_sync.h" #include "ble_ll_conn_priv.h" +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + /* * XXX: * 1) I think I can guarantee that we dont process things out of order if @@ -879,7 +881,9 @@ ble_ll_scan_sm_stop(int chk_disable) OS_ENTER_CRITICAL(sr); +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) scansm->connsm = NULL; +#endif /* Disable scanning state machine */ scansm->scan_enabled = 0; @@ -1087,12 +1091,20 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev) */ start_scan = inside_window; switch (ble_ll_state_get()) { +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_LL_STATE_ADV: +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_STATE_CONNECTION: +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) case BLE_LL_STATE_SYNC: +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) case BLE_LL_STATE_SCAN_AUX: start_scan = false; break; +#endif case BLE_LL_STATE_SCANNING: /* Must disable PHY since we will move to a new channel */ ble_phy_disable(); @@ -1184,6 +1196,7 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags) } break; #endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_SCAN_TYPE_INITIATE: if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND)) { @@ -1197,6 +1210,7 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags) } #endif break; +#endif default: break; } @@ -1342,6 +1356,7 @@ ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, return 0; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) int ble_ll_scan_rx_check_init(struct ble_ll_scan_addr_data *addrd) { @@ -1364,6 +1379,7 @@ ble_ll_scan_rx_check_init(struct ble_ll_scan_addr_data *addrd) return 0; } +#endif static int ble_ll_scan_rx_isr_end_on_adv(uint8_t pdu_type, uint8_t *rxbuf, @@ -1388,6 +1404,7 @@ ble_ll_scan_rx_isr_end_on_adv(uint8_t pdu_type, uint8_t *rxbuf, return 0; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if ((scanp->scan_type == BLE_SCAN_TYPE_INITIATE) && !(scansm->scan_filt_policy & 0x01)) { rc = ble_ll_scan_rx_check_init(addrd); @@ -1395,6 +1412,7 @@ ble_ll_scan_rx_isr_end_on_adv(uint8_t pdu_type, uint8_t *rxbuf, return 0; } } +#endif rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) @@ -1415,10 +1433,19 @@ ble_ll_scan_rx_isr_end_on_adv(uint8_t pdu_type, uint8_t *rxbuf, /* Allow responding to all PDUs when initiating since unwanted PDUs were * already filtered out in isr_start. */ - return ((scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && - ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || - (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND))) || - (scanp->scan_type == BLE_SCAN_TYPE_INITIATE); + if ((scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) && + ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) || + (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND))) { + return 1; + } + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + if (scanp->scan_type == BLE_SCAN_TYPE_INITIATE) { + return 1; + } +#endif + + return 0; } static int @@ -1599,12 +1626,14 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) return 0; } break; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_SCAN_TYPE_INITIATE: if (ble_ll_conn_send_connect_req(rxpdu, &addrd, 0) == 0) { hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONNECT_IND_TXD; return 0; } break; +#endif } } @@ -1924,14 +1953,15 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om, void ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hdr) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) struct ble_mbuf_hdr_rxinfo *rxinfo; + uint8_t *targeta; +#endif struct ble_ll_scan_sm *scansm; struct ble_ll_scan_addr_data addrd; - uint8_t *targeta; uint8_t max_pdu_type; scansm = &g_ble_ll_scan_sm; - rxinfo = &hdr->rxinfo; /* Ignore PDUs we do not expect here */ max_pdu_type = BLE_ADV_PDU_TYPE_ADV_SCAN_IND; @@ -1954,7 +1984,10 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd } #endif - if (scansm->scanp->scan_type == BLE_SCAN_TYPE_INITIATE) { + switch (scansm->scanp->scan_type) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_SCAN_TYPE_INITIATE: + rxinfo = &hdr->rxinfo; if (rxinfo->flags & BLE_MBUF_HDR_F_CONNECT_IND_TXD) { /* We need to keep original TargetA in case it was resolved, so rl * can be updated properly. @@ -1967,8 +2000,11 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd ble_ll_conn_created_on_legacy(om, &addrd, targeta); return; } - } else { + break; +#endif + default: ble_ll_scan_rx_pkt_in_on_legacy(ptype, om, hdr, &addrd); + break; } ble_ll_scan_chk_resume(); @@ -2290,6 +2326,7 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, /* if already enable we just need to update parameters */ if (scansm->scan_enabled) { /* Controller does not allow initiating and scanning.*/ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { scanp_phy = &scansm->scan_phys[i]; if (scanp_phy->configured && @@ -2297,6 +2334,7 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, return BLE_ERR_CMD_DISALLOWED; } } +#endif #if MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS) /* update filter policy */ @@ -2426,6 +2464,7 @@ ble_ll_scan_can_chg_whitelist(void) return rc; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) int ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext, struct ble_ll_conn_create_scan *cc_scan) @@ -2504,6 +2543,7 @@ ble_ll_scan_initiator_start(struct ble_ll_conn_sm *connsm, uint8_t ext, return rc; } +#endif /** * Checks to see if the scanner is enabled. @@ -2679,3 +2719,5 @@ ble_ll_scan_init(void) ble_ll_scan_aux_init(); #endif } + +#endif diff --git a/nimble/controller/src/ble_ll_scan_aux.c b/nimble/controller/src/ble_ll_scan_aux.c index f1e56bd3eb..69ab10cde9 100644 --- a/nimble/controller/src/ble_ll_scan_aux.c +++ b/nimble/controller/src/ble_ll_scan_aux.c @@ -19,7 +19,7 @@ #include -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) #include #include @@ -670,9 +670,11 @@ ble_ll_scan_aux_break_ev(struct ble_npl_event *ev) void ble_ll_scan_aux_break(struct ble_ll_scan_aux_data *aux) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) { ble_ll_conn_send_connect_req_cancel(); } +#endif ble_npl_event_init(&aux->break_ev, ble_ll_scan_aux_break_ev, aux); ble_ll_event_send(&aux->break_ev); @@ -1069,9 +1071,11 @@ ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm, aux->adi = adi; aux->flags |= BLE_LL_SCAN_AUX_F_HAS_ADI; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (aux->scan_type == BLE_SCAN_TYPE_INITIATE) { aux->flags |= BLE_LL_SCAN_AUX_F_CONNECTABLE; } +#endif if (do_match) { aux->flags |= BLE_LL_SCAN_AUX_F_MATCHED; @@ -1304,6 +1308,7 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) goto done; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if ((aux->scan_type == BLE_SCAN_TYPE_INITIATE) && !(scan_filt_policy & 0x01)) { rc = ble_ll_scan_rx_check_init(&addrd); @@ -1312,6 +1317,7 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) goto done; } } +#endif aux->flags |= BLE_LL_SCAN_AUX_F_MATCHED; @@ -1330,6 +1336,7 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) return 0; } break; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_SCAN_TYPE_INITIATE: if (ble_ll_conn_send_connect_req(rxpdu, &addrd, 1) == 0) { /* AUX_CONNECT_REQ sent, keep PHY enabled to continue */ @@ -1341,6 +1348,9 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; } break; +#endif + default: + break; } done: @@ -1456,7 +1466,7 @@ ble_ll_scan_aux_sync_check(struct os_mbuf *rxpdu, } #endif - +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) static int ble_ll_scan_aux_check_connect_rsp(uint8_t *rxbuf, struct ble_ll_scan_pdu_data *pdu_data, @@ -1586,6 +1596,7 @@ ble_ll_scan_aux_rx_pkt_in_for_initiator(struct os_mbuf *rxpdu, } ble_ll_scan_aux_free(aux); } +#endif void ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr) @@ -1604,10 +1615,12 @@ ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr) BLE_LL_ASSERT(aux); +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (aux->scan_type == BLE_SCAN_TYPE_INITIATE) { ble_ll_scan_aux_rx_pkt_in_for_initiator(rxpdu, rxhdr); return; } +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) sync_check = ble_ll_sync_enabled() && @@ -1745,4 +1758,4 @@ ble_ll_scan_aux_init(void) BLE_LL_ASSERT(err == 0); } -#endif /* BLE_LL_CFG_FEAT_LL_EXT_ADV */ \ No newline at end of file +#endif /* BLE_LL_CFG_FEAT_LL_EXT_ADV */ diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index 0a9be9c8ae..fe47dbc620 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -112,7 +112,9 @@ ble_ll_sched_preempt(struct ble_ll_sched_item *sch, { struct ble_ll_sched_item *entry; struct ble_ll_sched_item *next; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) struct ble_ll_conn_sm *connsm; +#endif entry = first; @@ -123,25 +125,33 @@ ble_ll_sched_preempt(struct ble_ll_sched_item *sch, entry->enqueued = 0; switch (entry->sched_type) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_SCHED_TYPE_CONN: connsm = (struct ble_ll_conn_sm *)entry->cb_arg; ble_ll_event_send(&connsm->conn_ev_end); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_LL_SCHED_TYPE_ADV: ble_ll_adv_event_rmvd_from_sched(entry->cb_arg); break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_LL_SCHED_TYPE_SCAN_AUX: ble_ll_scan_aux_break(entry->cb_arg); break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_LL_SCHED_TYPE_PERIODIC: ble_ll_adv_periodic_rmvd_from_sched(entry->cb_arg); break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_LL_SCHED_TYPE_SYNC: ble_ll_sync_rmvd_from_sched(entry->cb_arg); break; #endif +#endif #endif default: BLE_LL_ASSERT(0); @@ -302,16 +312,17 @@ ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1, static int ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch) { - int rc; + int rc = 0; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) uint32_t ce_end_time; - rc = 0; if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) { ce_end_time = ble_ll_conn_get_ce_end_time(); if (CPUTIME_GT(ce_end_time, sch->start_time)) { rc = 1; } } +#endif return rc; } @@ -334,7 +345,9 @@ int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) { struct ble_ll_sched_item *sch; +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) uint32_t usecs; +#endif os_sr_t sr; int rc; @@ -343,13 +356,24 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm) /* Set schedule start and end times */ sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks; - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + switch (connsm->conn_role) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_LL_CONN_ROLE_MASTER: + sch->remainder = connsm->anchor_point_usecs; + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_CONN_ROLE_SLAVE: usecs = connsm->slave_cur_window_widening; sch->start_time -= (os_cputime_usecs_to_ticks(usecs) + 1); sch->remainder = 0; - } else { - sch->remainder = connsm->anchor_point_usecs; + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } + sch->end_time = connsm->ce_end_time; /* Better be past current time or we just leave */ @@ -802,7 +826,7 @@ usecs_to_ticks_fast(uint32_t usecs) } #endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) /* * Determines if the schedule item overlaps the currently running schedule * item. This function cares about connection and sync. @@ -815,9 +839,11 @@ ble_ll_sched_sync_overlaps_current(struct ble_ll_sched_item *sch) state = ble_ll_state_get(); switch (state) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_STATE_CONNECTION: end_time = ble_ll_conn_get_ce_end_time(); break; +#endif case BLE_LL_STATE_SYNC: end_time = ble_ll_sync_get_event_end_time(); break; @@ -1037,10 +1063,24 @@ ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch) OS_ENTER_CRITICAL(sr); lls = ble_ll_state_get(); - if ((lls == BLE_LL_STATE_ADV) || (lls == BLE_LL_STATE_CONNECTION) || - (lls == BLE_LL_STATE_SYNC)) { + switch(lls) { +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + case BLE_LL_STATE_ADV: OS_EXIT_CRITICAL(sr); return -1; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_STATE_CONNECTION: + OS_EXIT_CRITICAL(sr); + return -1; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + case BLE_LL_STATE_SYNC: + OS_EXIT_CRITICAL(sr); + return -1; +#endif + default: + break; } rc = ble_ll_sched_insert(sch, 0, preempt_none); @@ -1161,25 +1201,40 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) /* We have to disable the PHY no matter what */ ble_phy_disable(); - if (lls == BLE_LL_STATE_SCANNING) { + switch (lls) { +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + case BLE_LL_STATE_SCANNING: ble_ll_state_set(BLE_LL_STATE_STANDBY); ble_ll_scan_halt(); - } else if (lls == BLE_LL_STATE_ADV) { - STATS_INC(ble_ll_stats, sched_state_adv_errs); - ble_ll_adv_halt(); + break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - } else if (lls == BLE_LL_STATE_SYNC) { + case BLE_LL_STATE_SYNC: STATS_INC(ble_ll_stats, sched_state_sync_errs); ble_ll_sync_halt(); + break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - } else if (lls == BLE_LL_STATE_SCAN_AUX) { + case BLE_LL_STATE_SCAN_AUX: ble_ll_state_set(BLE_LL_STATE_STANDBY); ble_ll_scan_aux_halt(); + break; #endif - } else { +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + case BLE_LL_STATE_ADV: + STATS_INC(ble_ll_stats, sched_state_adv_errs); + ble_ll_adv_halt(); + break; +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + case BLE_LL_STATE_CONNECTION: STATS_INC(ble_ll_stats, sched_state_conn_errs); ble_ll_conn_event_halt(); + break; +#endif + default: + BLE_LL_ASSERT(0); + break; } sched: diff --git a/nimble/controller/src/ble_ll_supp_cmd.c b/nimble/controller/src/ble_ll_supp_cmd.c index 6ceeaebb02..2fc0d7d3af 100644 --- a/nimble/controller/src/ble_ll_supp_cmd.c +++ b/nimble/controller/src/ble_ll_supp_cmd.c @@ -27,7 +27,11 @@ #include "controller/ble_ll_hci.h" /* Octet 0 */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_DISCONNECT (1 << 5) +#else +#define BLE_SUPP_CMD_DISCONNECT (0 << 5) +#endif #define BLE_LL_SUPP_CMD_OCTET_0 (BLE_SUPP_CMD_DISCONNECT) /* Octet 5 */ @@ -64,7 +68,12 @@ /* Octet 15 */ #define BLE_SUPP_CMD_RD_BD_ADDR (1 << 1) + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_RD_RSSI (1 << 5) +#else +#define BLE_SUPP_CMD_RD_RSSI (0 << 5) +#endif #define BLE_LL_SUPP_CMD_OCTET_15 \ ( \ @@ -77,9 +86,15 @@ #define BLE_SUPP_CMD_LE_RD_BUF_SIZE (1 << 1) #define BLE_SUPP_CMD_LE_RD_LOC_FEAT (1 << 2) #define BLE_SUPP_CMD_LE_SET_RAND_ADDR (1 << 4) +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (1 << 5) #define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (1 << 6) #define BLE_SUPP_CMD_LE_SET_ADV_DATA (1 << 7) +#else +#define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (0 << 5) +#define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (0 << 6) +#define BLE_SUPP_CMD_LE_SET_ADV_DATA (0 << 7) +#endif #define BLE_LL_SUPP_CMD_OCTET_25 \ ( \ @@ -93,12 +108,28 @@ ) /* Octet 26 */ +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (1 << 0) #define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (1 << 1) +#else +#define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (0 << 0) +#define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (0 << 1) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) #define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (1 << 2) #define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (1 << 3) +#else +#define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (0 << 2) +#define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (0 << 3) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_LE_CREATE_CONN (1 << 4) #define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (1 << 5) +#else +#define BLE_SUPP_CMD_LE_CREATE_CONN (0 << 4) +#define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (0 << 5) + +#endif #define BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE (1 << 6) #define BLE_SUPP_CMD_LE_CLR_WHITELIST (1 << 7) @@ -117,10 +148,19 @@ /* Octet 27 */ #define BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST (1 << 0) #define BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST (1 << 1) +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_LE_CONN_UPDATE (1 << 2) +#else +#define BLE_SUPP_CMD_LE_CONN_UPDATE (0 << 2) +#endif #define BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS (1 << 3) +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_LE_RD_CHAN_MAP (1 << 4) #define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (1 << 5) +#else +#define BLE_SUPP_CMD_LE_RD_CHAN_MAP (0 << 4) +#define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (0 << 5) +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) #define BLE_SUPP_CMD_LE_ENCRYPT (1 << 6) #else @@ -142,10 +182,19 @@ /* Octet 28 */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_LE_START_ENCRYPT (1 << 0) +#else +#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) #define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (1 << 1) #define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (1 << 2) #else +#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1) +#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2) +#endif +#else #define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0) #define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1) #define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2) @@ -175,6 +224,7 @@ ) /* Octet 33 */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_LE_REM_CONN_PRR (1 << 4) #define BLE_SUPP_CMD_LE_REM_CONN_PRNR (1 << 5) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) @@ -184,6 +234,13 @@ #define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6) #define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7) #endif +#else +#define BLE_SUPP_CMD_LE_REM_CONN_PRR (0 << 4) +#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (0 << 5) +#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6) +#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7) +#endif + #define BLE_LL_SUPP_CMD_OCTET_33 \ ( \ @@ -194,11 +251,15 @@ ) /* Octet 34 */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) #define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (1 << 0) #else #define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0) #endif +#else +#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0) +#endif #define BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK (0 << 1) #define BLE_SUPP_CMD_LE_GENERATE_DH_KEY (0 << 2) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) @@ -239,6 +300,7 @@ #endif #define BLE_SUPP_CMD_LE_RD_MAX_DATALEN (1 << 3) #if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_LE_READ_PHY (1 << 4) #define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (1 << 5) #define BLE_SUPP_CMD_LE_SET_PHY (1 << 6) @@ -247,6 +309,11 @@ #define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5) #define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) #endif +#else +#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4) +#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5) +#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) +#endif #if MYNEWT_VAL(BLE_LL_DTM) #define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (1 << 7) @@ -273,7 +340,7 @@ #define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (0 << 0) #endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (1 << 1) #define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (1 << 2) #define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (1 << 3) @@ -304,14 +371,14 @@ ) /* Octet 37 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #define BLE_SUPP_CMD_LE_REMOVE_ADVS (1 << 0) #define BLE_SUPP_CMD_LE_CLEAR_ADVS (1 << 1) #else #define BLE_SUPP_CMD_LE_REMOVE_ADVS (0 << 0) #define BLE_SUPP_CMD_LE_CLEAR_ADVS (0 << 1) #endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #define BLE_SUPP_CMD_LE_SET_PADV_PARAM (1 << 2) #define BLE_SUPP_CMD_LE_SET_PADV_DATA (1 << 3) #define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (1 << 4) @@ -321,10 +388,19 @@ #define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (0 << 4) #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) #define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (1 << 5) #define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (1 << 6) +#else +#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5) +#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6) +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (1 << 7) #else +#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7) +#endif +#else #define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5) #define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6) #define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7) @@ -343,7 +419,7 @@ ) /* Octet 38 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) #define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (1 << 0) #define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (1 << 1) #define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (1 << 2) @@ -391,7 +467,8 @@ ) /* Octet 40 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_VERSION) >= 51 +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_VERSION) >= 51 && \ + MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) #define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (1 << 5) #else #define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (0 << 5) diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c index 4b2004953d..7b6208ce11 100644 --- a/nimble/controller/src/ble_ll_sync.c +++ b/nimble/controller/src/ble_ll_sync.c @@ -41,7 +41,7 @@ #include "stats/stats.h" -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) /* defines number of events that can be lost during sync establishment * before failed to be established error is reported diff --git a/nimble/controller/src/ble_ll_whitelist.c b/nimble/controller/src/ble_ll_whitelist.c index 04ec6428b5..12d841a7f8 100644 --- a/nimble/controller/src/ble_ll_whitelist.c +++ b/nimble/controller/src/ble_ll_whitelist.c @@ -48,8 +48,6 @@ struct ble_ll_whitelist_entry g_ble_ll_whitelist[BLE_LL_WHITELIST_SIZE]; static int ble_ll_whitelist_chg_allowed(void) { - int rc; - /* * This command is not allowed if: * -> advertising uses the whitelist and we are currently advertising. @@ -57,11 +55,19 @@ ble_ll_whitelist_chg_allowed(void) * -> initiating uses whitelist and a LE create connection command is in * progress */ - rc = 1; - if (!ble_ll_adv_can_chg_whitelist() || !ble_ll_scan_can_chg_whitelist()) { - rc = 0; +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + if (ble_ll_adv_can_chg_whitelist()) { + return 1; } - return rc; +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + if (ble_ll_scan_can_chg_whitelist()) { + return 1; + } +#endif + + return 0; } /** diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index 7c33242716..62c9c4ad9d 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -23,6 +23,30 @@ syscfg.defs: this setting shall not be overriden. value: 1 + BLE_LL_ROLE_CENTRAL: + description: 'Enables controller support for the Central role.' + value: MYNEWT_VAL(BLE_ROLE_CENTRAL) + restrictions: + - 'BLE_LL_ROLE_OBSERVER if 1' + + BLE_LL_ROLE_PERIPHERAL: + description: 'Enables controller support for the Peripheral role.' + value: MYNEWT_VAL(BLE_ROLE_PERIPHERAL) + restrictions: + - 'BLE_LL_ROLE_BROADCASTER if 1' + + BLE_LL_ROLE_BROADCASTER: + description: 'Enables controller support for the Broadcaster role.' + value: MYNEWT_VAL(BLE_ROLE_BROADCASTER) + restrictions: + - 'BLE_LL_ROLE_OBSERVER if 0' + + BLE_LL_ROLE_OBSERVER: + description: 'Enables controller support for the Observer role.' + value: MYNEWT_VAL(BLE_ROLE_OBSERVER) + restrictions: + - 'BLE_LL_ROLE_BROADCASTER if 0' + BLE_HW_WHITELIST_ENABLE: description: > Used to enable hardware white list @@ -184,21 +208,21 @@ syscfg.defs: description: > This option enables/disables encryption support in the controller. This option saves both both code and RAM. - value: '1' + value: 'MYNEWT_VAL_BLE_LL_ROLE_CENTRAL || MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL' BLE_LL_CFG_FEAT_CONN_PARAM_REQ: description: > This option enables/disables the connection parameter request procedure. This is implemented in the controller but is disabled by default. - value: '1' + value: 'MYNEWT_VAL_BLE_LL_ROLE_CENTRAL || MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL' BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG: description: > This option allows a slave to initiate the feature exchange procedure. This feature is implemented but currently has no impact on code or ram size - value: '1' + value: 'MYNEWT_VAL_BLE_LL_ROLE_CENTRAL || MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL' BLE_LL_CFG_FEAT_LE_PING: description: > @@ -213,7 +237,7 @@ syscfg.defs: the controller. If enabled, the controller is allowed to change the size of tx/rx pdu's used in a connection. This option has only minor impact on code size and non on RAM. - value: '1' + value: 'MYNEWT_VAL_BLE_LL_ROLE_CENTRAL || MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL' BLE_LL_CFG_FEAT_LL_PRIVACY: description: > @@ -248,8 +272,6 @@ syscfg.defs: This option is used to enable/disable support for Periodic Advertising Feature. value: MYNEWT_VAL(BLE_PERIODIC_ADV) - restrictions: - - 'BLE_LL_CFG_FEAT_LL_EXT_ADV if 1' BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT: description: > @@ -273,6 +295,8 @@ syscfg.defs: 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 + restrictions: + - '(BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL) if 1' BLE_LL_CFG_FEAT_LL_SCA_UPDATE: description: > diff --git a/nimble/syscfg.yml b/nimble/syscfg.yml index b5cfc585d6..32fbaf9872 100644 --- a/nimble/syscfg.yml +++ b/nimble/syscfg.yml @@ -67,6 +67,7 @@ syscfg.defs: value: 0 restrictions: - 'BLE_PERIODIC_ADV if 1' + - '(BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL) if 1' BLE_EXT_ADV_MAX_SIZE: description: > diff --git a/nimble/transport/uart/src/ble_hci_uart.c b/nimble/transport/uart/src/ble_hci_uart.c index 2cad55a7d9..ac49b30b07 100644 --- a/nimble/transport/uart/src/ble_hci_uart.c +++ b/nimble/transport/uart/src/ble_hci_uart.c @@ -755,7 +755,9 @@ ble_hci_uart_rx_skip_acl(uint8_t data) if (rxd_bytes == ble_hci_uart_state.rx_acl.len) { /* XXX: I dont like this but for now this denotes controller only */ #if MYNEWT_VAL(BLE_CONTROLLER) +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) ble_ll_data_buffer_overflow(); +#endif #endif ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE; } From f4dd2f34f81ddd4fc638ce31694d207d8bd788ea Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 21 Dec 2021 17:31:56 +0100 Subject: [PATCH 276/306] nimble/ll: Set LE supported states based on enabled roles This also fix claiming support for concurrent scanning and initiating which is not supported by LL yet. --- nimble/controller/src/ble_ll.c | 207 ++++++++++++++++++++++++++------- 1 file changed, 165 insertions(+), 42 deletions(-) diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 0560b61da4..56e81a6697 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -65,48 +65,171 @@ */ /* Supported states */ -#define BLE_LL_S_NCA (0x00000000001) -#define BLE_LL_S_SA (0x00000000002) -#define BLE_LL_S_CA (0x00000000004) -#define BLE_LL_S_HDCA (0x00000000008) -#define BLE_LL_S_PS (0x00000000010) -#define BLE_LL_S_AS (0x00000000020) -#define BLE_LL_S_INIT (0x00000000040) -#define BLE_LL_S_SLAVE (0x00000000080) -#define BLE_LL_S_NCA_PS (0x00000000100) -#define BLE_LL_S_SA_PS (0x00000000200) -#define BLE_LL_S_CA_PS (0x00000000400) -#define BLE_LL_S_HDCA_PS (0x00000000800) -#define BLE_LL_S_NCA_AS (0x00000001000) -#define BLE_LL_S_SA_AS (0x00000002000) -#define BLE_LL_S_CA_AS (0x00000004000) -#define BLE_LL_S_HDCA_AS (0x00000008000) -#define BLE_LL_S_NCA_INIT (0x00000010000) -#define BLE_LL_S_SA_INIT (0x00000020000) -#define BLE_LL_S_NCA_MASTER (0x00000040000) -#define BLE_LL_S_SA_MASTER (0x00000080000) -#define BLE_LL_S_NCA_SLAVE (0x00000100000) -#define BLE_LL_S_SA_SLAVE (0x00000200000) -#define BLE_LL_S_PS_INIT (0x00000400000) -#define BLE_LL_S_AS_INIT (0x00000800000) -#define BLE_LL_S_PS_MASTER (0x00001000000) -#define BLE_LL_S_AS_MASTER (0x00002000000) -#define BLE_LL_S_PS_SLAVE (0x00004000000) -#define BLE_LL_S_AS_SLAVE (0x00008000000) -#define BLE_LL_S_INIT_MASTER (0x00010000000) -#define BLE_LL_S_LDCA (0x00020000000) -#define BLE_LL_S_LDCA_PS (0x00040000000) -#define BLE_LL_S_LDCA_AS (0x00080000000) -#define BLE_LL_S_CA_INIT (0x00100000000) -#define BLE_LL_S_HDCA_INIT (0x00200000000) -#define BLE_LL_S_LDCA_INIT (0x00400000000) -#define BLE_LL_S_CA_MASTER (0x00800000000) -#define BLE_LL_S_HDCA_MASTER (0x01000000000) -#define BLE_LL_S_LDCA_MASTER (0x02000000000) -#define BLE_LL_S_CA_SLAVE (0x04000000000) -#define BLE_LL_S_HDCA_SLAVE (0x08000000000) -#define BLE_LL_S_LDCA_SLAVE (0x10000000000) -#define BLE_LL_S_INIT_SLAVE (0x20000000000) +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) +#define BLE_LL_S_NCA ((uint64_t)1 << 0) +#define BLE_LL_S_SA ((uint64_t)1 << 1) +#else +#define BLE_LL_S_NCA ((uint64_t)0 << 0) +#define BLE_LL_S_SA ((uint64_t)0 << 1) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) +#define BLE_LL_S_CA ((uint64_t)1 << 2) +#define BLE_LL_S_HDCA ((uint64_t)1 << 3) +#else +#define BLE_LL_S_CA ((uint64_t)0 << 2) +#define BLE_LL_S_HDCA ((uint64_t)0 << 3) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) +#define BLE_LL_S_PS ((uint64_t)1 << 4) +#define BLE_LL_S_AS ((uint64_t)1 << 5) +#else +#define BLE_LL_S_PS ((uint64_t)0 << 4) +#define BLE_LL_S_AS ((uint64_t)0 << 5) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +#define BLE_LL_S_INIT ((uint64_t)1 << 6) +#else +#define BLE_LL_S_INIT ((uint64_t)0 << 6) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) +#define BLE_LL_S_SLAVE ((uint64_t)1 << 7) +#else +#define BLE_LL_S_SLAVE ((uint64_t)0 << 7) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) +#define BLE_LL_S_NCA_PS ((uint64_t)1 << 8) +#define BLE_LL_S_SA_PS ((uint64_t)1 << 9) +#else +#define BLE_LL_S_NCA_PS ((uint64_t)0 << 8) +#define BLE_LL_S_SA_PS ((uint64_t)0 << 9) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) +#define BLE_LL_S_CA_PS ((uint64_t)1 << 10) +#define BLE_LL_S_HDCA_PS ((uint64_t)1 << 11) +#else +#define BLE_LL_S_CA_PS ((uint64_t)0 << 10) +#define BLE_LL_S_HDCA_PS ((uint64_t)0 << 11) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) +#define BLE_LL_S_NCA_AS ((uint64_t)1 << 12) +#define BLE_LL_S_SA_AS ((uint64_t)1 << 13) +#else +#define BLE_LL_S_NCA_AS ((uint64_t)0 << 12) +#define BLE_LL_S_SA_AS ((uint64_t)0 << 13) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) +#define BLE_LL_S_CA_AS ((uint64_t)1 << 14) +#define BLE_LL_S_HDCA_AS ((uint64_t)1 << 15) +#else +#define BLE_LL_S_CA_AS ((uint64_t)0 << 14) +#define BLE_LL_S_HDCA_AS ((uint64_t)0 << 15) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +#define BLE_LL_S_NCA_INIT ((uint64_t)1 << 16) +#define BLE_LL_S_SA_INIT ((uint64_t)1 << 17) +#define BLE_LL_S_NCA_MASTER ((uint64_t)1 << 18) +#define BLE_LL_S_SA_MASTER ((uint64_t)1 << 19) +#else +#define BLE_LL_S_NCA_INIT ((uint64_t)0 << 16) +#define BLE_LL_S_SA_INIT ((uint64_t)0 << 17) +#define BLE_LL_S_NCA_MASTER ((uint64_t)0 << 18) +#define BLE_LL_S_SA_MASTER ((uint64_t)0 << 19) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) +#define BLE_LL_S_NCA_SLAVE ((uint64_t)1 << 20) +#define BLE_LL_S_SA_SLAVE ((uint64_t)1 << 21) +#else +#define BLE_LL_S_NCA_SLAVE ((uint64_t)0 << 20) +#define BLE_LL_S_SA_SLAVE ((uint64_t)0 << 21) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) && MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +/* We do not support passive scanning while initiating yet */ +#define BLE_LL_S_PS_INIT ((uint64_t)0 << 22) +/* We do not support active scanning while initiating yet */ +#define BLE_LL_S_AS_INIT ((uint64_t)0 << 23) +#define BLE_LL_S_PS_MASTER ((uint64_t)1 << 24) +#define BLE_LL_S_AS_MASTER ((uint64_t)1 << 25) +#else +#define BLE_LL_S_PS_INIT ((uint64_t)0 << 22) +#define BLE_LL_S_AS_INIT ((uint64_t)0 << 23) +#define BLE_LL_S_PS_MASTER ((uint64_t)0 << 24) +#define BLE_LL_S_AS_MASTER ((uint64_t)0 << 25) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) && MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) +#define BLE_LL_S_PS_SLAVE ((uint64_t)1 << 26) +#define BLE_LL_S_AS_SLAVE ((uint64_t)1 << 27) +#else +#define BLE_LL_S_PS_SLAVE ((uint64_t)0 << 26) +#define BLE_LL_S_AS_SLAVE ((uint64_t)0 << 27) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +#define BLE_LL_S_INIT_MASTER ((uint64_t)1 << 28) +#else +#define BLE_LL_S_INIT_MASTER ((uint64_t)0 << 28) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) +#define BLE_LL_S_LDCA ((uint64_t)1 << 29) +#else +#define BLE_LL_S_LDCA ((uint64_t)0 << 29) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) +#define BLE_LL_S_LDCA_PS ((uint64_t)1 << 30) +#define BLE_LL_S_LDCA_AS ((uint64_t)1 << 31) +#else +#define BLE_LL_S_LDCA_PS ((uint64_t)0 << 30) +#define BLE_LL_S_LDCA_AS ((uint64_t)0 << 31) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) && MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +#define BLE_LL_S_CA_INIT ((uint64_t)1 << 32) +#define BLE_LL_S_HDCA_INIT ((uint64_t)1 << 33) +#define BLE_LL_S_LDCA_INIT ((uint64_t)1 << 34) +#else +#define BLE_LL_S_CA_INIT ((uint64_t)0 << 32) +#define BLE_LL_S_HDCA_INIT ((uint64_t)0 << 33) +#define BLE_LL_S_LDCA_INIT ((uint64_t)0 << 34) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +#define BLE_LL_S_CA_MASTER ((uint64_t)1 << 35) +#define BLE_LL_S_HDCA_MASTER ((uint64_t)1 << 36) +#define BLE_LL_S_LDCA_MASTER ((uint64_t)1 << 37) +#else +#define BLE_LL_S_CA_MASTER ((uint64_t)0 << 35) +#define BLE_LL_S_HDCA_MASTER ((uint64_t)0 << 36) +#define BLE_LL_S_LDCA_MASTER ((uint64_t)0 << 37) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) +#define BLE_LL_S_CA_SLAVE ((uint64_t)1 << 38) +#define BLE_LL_S_HDCA_SLAVE ((uint64_t)1 << 39) +#define BLE_LL_S_LDCA_SLAVE ((uint64_t)1 << 40) +#else +#define BLE_LL_S_CA_SLAVE ((uint64_t)0 << 38) +#define BLE_LL_S_HDCA_SLAVE ((uint64_t)0 << 39) +#define BLE_LL_S_LDCA_SLAVE ((uint64_t)0 << 40) +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) && MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +#define BLE_LL_S_INIT_SLAVE ((uint64_t)1 << 41) +#else +#define BLE_LL_S_INIT_SLAVE ((uint64_t)0 << 41) +#endif #define BLE_LL_SUPPORTED_STATES \ ( \ From ee6ba614c81cb83f4f6ae3b559e142344e8ec0ef Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 14 Dec 2021 15:18:33 +0100 Subject: [PATCH 277/306] nimble: Allow to configure BLE version 5.3 Core Specification 5.3 is available for some time already. --- nimble/include/nimble/hci_common.h | 6 +++++- nimble/syscfg.yml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index b6f9869a71..7369518874 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -1828,6 +1828,7 @@ struct ble_hci_ev_le_subev_biginfo_adv_report { #define BLE_HCI_VER_BCS_5_0 (9) #define BLE_HCI_VER_BCS_5_1 (10) #define BLE_HCI_VER_BCS_5_2 (11) +#define BLE_HCI_VER_BCS_5_3 (12) #define BLE_LMP_VER_BCS_1_0b (0) #define BLE_LMP_VER_BCS_1_1 (1) @@ -1841,6 +1842,7 @@ struct ble_hci_ev_le_subev_biginfo_adv_report { #define BLE_LMP_VER_BCS_5_0 (9) #define BLE_LMP_VER_BCS_5_1 (10) #define BLE_LMP_VER_BCS_5_2 (11) +#define BLE_LMP_VER_BCS_5_3 (12) /* selected HCI and LMP version */ #if MYNEWT_VAL(BLE_VERSION) == 50 @@ -1852,7 +1854,9 @@ struct ble_hci_ev_le_subev_biginfo_adv_report { #elif MYNEWT_VAL(BLE_VERSION) == 52 #define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_5_2 #define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_5_2 - +#elif MYNEWT_VAL(BLE_VERSION) == 53 +#define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_5_3 +#define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_5_3 #endif #define BLE_HCI_DATA_HDR_SZ 4 diff --git a/nimble/syscfg.yml b/nimble/syscfg.yml index 32fbaf9872..0e87c0647d 100644 --- a/nimble/syscfg.yml +++ b/nimble/syscfg.yml @@ -80,7 +80,7 @@ syscfg.defs: This allows to configure supported Bluetooth Core version. Some features may not be available if version is too low. Version is integer for easy comparison. - range: 50, 51, 52 + range: 50, 51, 52, 53 value: 50 BLE_ISO: description: > From f771348a4ee7b5fd757aec810ebb0766cc300efc Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 6 Dec 2021 16:30:45 +0100 Subject: [PATCH 278/306] ports: Build NimBLE with 32-bit environment Some code in NimBLE assumes that pointers are 4 bytes. Until this is properly fixed build with -m32 to make sure resulting binary is no misbehaving. --- .travis.yml | 1 + porting/examples/dummy/Makefile | 3 ++- porting/examples/linux/Makefile | 2 +- porting/examples/linux_blemesh/Makefile | 2 +- porting/nimble/Makefile.defs | 5 ++++- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0b59e7a862..185ca35507 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,7 @@ _addons: &addon_conf packages: - gcc-multilib - gcc-7-multilib + - g++-multilib go: - "1.16" diff --git a/porting/examples/dummy/Makefile b/porting/examples/dummy/Makefile index 861934f7f0..1c38ac4a3c 100644 --- a/porting/examples/dummy/Makefile +++ b/porting/examples/dummy/Makefile @@ -60,6 +60,7 @@ OBJ := $(SRC:.c=.o) TINYCRYPT_OBJ := $(TINYCRYPT_SRC:.c=.o) CFLAGS := $(NIMBLE_CFLAGS) +LDFLAGS := $(NIMBLE_LDFLAGS) .PHONY: all clean .DEFAULT: all @@ -76,4 +77,4 @@ $(TINYCRYPT_OBJ): CFLAGS+=$(TINYCRYPT_CFLAGS) $(CC) -c $(addprefix -I, $(INC)) $(CFLAGS) -o $@ $< dummy: $(OBJ) $(TINYCRYPT_OBJ) - $(CC) -o $@ $^ + $(CC) -o $@ $^ $(LDFLAGS) diff --git a/porting/examples/linux/Makefile b/porting/examples/linux/Makefile index 11f4ebc308..c3eee16cb5 100644 --- a/porting/examples/linux/Makefile +++ b/porting/examples/linux/Makefile @@ -81,7 +81,7 @@ CFLAGS = \ -D_GNU_SOURCE \ $(NULL) -LIBS := -lrt -lpthread -lstdc++ +LIBS := $(NIMBLE_LDFLAGS) -lrt -lpthread -lstdc++ .PHONY: all clean .DEFAULT: all diff --git a/porting/examples/linux_blemesh/Makefile b/porting/examples/linux_blemesh/Makefile index c1518e0e4d..67783f2766 100644 --- a/porting/examples/linux_blemesh/Makefile +++ b/porting/examples/linux_blemesh/Makefile @@ -83,7 +83,7 @@ CFLAGS = \ -D_GNU_SOURCE \ $(NULL) -LIBS := -lrt -lpthread -lstdc++ +LIBS := $(NIMBLE_LDFLAGS) -lrt -lpthread -lstdc++ .PHONY: all clean .DEFAULT: all diff --git a/porting/nimble/Makefile.defs b/porting/nimble/Makefile.defs index 5bab893fde..78f73fbc9b 100644 --- a/porting/nimble/Makefile.defs +++ b/porting/nimble/Makefile.defs @@ -19,7 +19,10 @@ ifeq (,$(NIMBLE_ROOT)) $(error NIMBLE_ROOT shall be defined) endif -NIMBLE_CFLAGS := +# For now this is required as there are places in NimBLE +# assumingthat pointer is 4 bytes long. +NIMBLE_CFLAGS := -m32 +NIMBLE_LDFLAGS := -m32 NIMBLE_INCLUDE := \ $(NIMBLE_ROOT)/nimble/include \ From 605ade16f7793e6c691b73436538ac588d7d0754 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 23 Dec 2021 14:26:36 +0100 Subject: [PATCH 279/306] nimble/ports: Use native BSP for test targets Dummy BSP could be getting out of sync with Mynewt BSP leading to compile errors. --- porting/targets/dummy_bsp/bsp.yml | 56 --------------------- porting/targets/dummy_bsp/include/bsp/bsp.h | 31 ------------ porting/targets/dummy_bsp/pkg.yml | 27 ---------- porting/targets/linux/target.yml | 2 +- porting/targets/linux_blemesh/target.yml | 2 +- porting/targets/nuttx/target.yml | 2 +- porting/targets/porting_default/syscfg.yml | 3 ++ porting/targets/porting_default/target.yml | 2 +- 8 files changed, 7 insertions(+), 118 deletions(-) delete mode 100644 porting/targets/dummy_bsp/bsp.yml delete mode 100644 porting/targets/dummy_bsp/include/bsp/bsp.h delete mode 100644 porting/targets/dummy_bsp/pkg.yml create mode 100644 porting/targets/porting_default/syscfg.yml diff --git a/porting/targets/dummy_bsp/bsp.yml b/porting/targets/dummy_bsp/bsp.yml deleted file mode 100644 index ecd1d42041..0000000000 --- a/porting/targets/dummy_bsp/bsp.yml +++ /dev/null @@ -1,56 +0,0 @@ -# -# 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. -# - -bsp.name: "dummy" -bsp.url: -bsp.maker: -bsp.arch: dummy -bsp.compiler: "@apache-mynewt-core/compiler/sim" - -bsp.flash_map: - areas: - # System areas. - FLASH_AREA_BOOTLOADER: - device: 0 - offset: 0x00000000 - size: 32kB - FLASH_AREA_IMAGE_0: - device: 0 - offset: 0x0000c000 - size: 472kB - FLASH_AREA_IMAGE_1: - device: 0 - offset: 0x00082000 - size: 472kB - FLASH_AREA_IMAGE_SCRATCH: - device: 0 - offset: 0x000f8000 - size: 16kB - - # User areas. - FLASH_AREA_REBOOT_LOG: - user_id: 0 - device: 0 - offset: 0x00008000 - size: 16kB - FLASH_AREA_NFFS: - user_id: 1 - device: 0 - offset: 0x000fc000 - size: 16kB diff --git a/porting/targets/dummy_bsp/include/bsp/bsp.h b/porting/targets/dummy_bsp/include/bsp/bsp.h deleted file mode 100644 index 69e8b1cfbb..0000000000 --- a/porting/targets/dummy_bsp/include/bsp/bsp.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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_BSP_H -#define H_BSP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_BSP_H */ diff --git a/porting/targets/dummy_bsp/pkg.yml b/porting/targets/dummy_bsp/pkg.yml deleted file mode 100644 index 8b8484960a..0000000000 --- a/porting/targets/dummy_bsp/pkg.yml +++ /dev/null @@ -1,27 +0,0 @@ -# -# 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. -# - -pkg.name: porting/targets/dummy_bsp -pkg.type: bsp -pkg.description: A dummy BSP definition -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: -pkg.cflags: -pkg.deps: diff --git a/porting/targets/linux/target.yml b/porting/targets/linux/target.yml index 9ab4152c9d..7145d70386 100644 --- a/porting/targets/linux/target.yml +++ b/porting/targets/linux/target.yml @@ -16,5 +16,5 @@ # under the License. # target.app: "porting/targets/dummy_app" -target.bsp: "porting/targets/dummy_bsp" +target.bsp: "@apache-mynewt-core/hw/bsp/native" target.build_profile: "debug" diff --git a/porting/targets/linux_blemesh/target.yml b/porting/targets/linux_blemesh/target.yml index 83eb415886..4b9a4dab8b 100644 --- a/porting/targets/linux_blemesh/target.yml +++ b/porting/targets/linux_blemesh/target.yml @@ -17,5 +17,5 @@ # target.app: "porting/targets/dummy_app" -target.bsp: "porting/targets/dummy_bsp" +target.bsp: "@apache-mynewt-core/hw/bsp/native" target.build_profile: "debug" diff --git a/porting/targets/nuttx/target.yml b/porting/targets/nuttx/target.yml index 9ab4152c9d..7145d70386 100644 --- a/porting/targets/nuttx/target.yml +++ b/porting/targets/nuttx/target.yml @@ -16,5 +16,5 @@ # under the License. # target.app: "porting/targets/dummy_app" -target.bsp: "porting/targets/dummy_bsp" +target.bsp: "@apache-mynewt-core/hw/bsp/native" target.build_profile: "debug" diff --git a/porting/targets/porting_default/syscfg.yml b/porting/targets/porting_default/syscfg.yml new file mode 100644 index 0000000000..d0aff807f2 --- /dev/null +++ b/porting/targets/porting_default/syscfg.yml @@ -0,0 +1,3 @@ +syscfg.vals: + BLE_SOCK_USE_TCP: 0 + BLE_SOCK_USE_LINUX_BLUE: 1 diff --git a/porting/targets/porting_default/target.yml b/porting/targets/porting_default/target.yml index 83eb415886..4b9a4dab8b 100644 --- a/porting/targets/porting_default/target.yml +++ b/porting/targets/porting_default/target.yml @@ -17,5 +17,5 @@ # target.app: "porting/targets/dummy_app" -target.bsp: "porting/targets/dummy_bsp" +target.bsp: "@apache-mynewt-core/hw/bsp/native" target.build_profile: "debug" From 4a008c8344d74e8a25edecd1a6c518238e01d474 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 23 Dec 2021 14:29:55 +0100 Subject: [PATCH 280/306] nimble/mesh: Fix bt_mesh_beacon_auth declaration net_id is 8 bytes long. --- nimble/host/mesh/src/crypto.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/crypto.h b/nimble/host/mesh/src/crypto.h index 637d13e724..dbdedf1fd6 100644 --- a/nimble/host/mesh/src/crypto.h +++ b/nimble/host/mesh/src/crypto.h @@ -70,7 +70,7 @@ static inline int bt_mesh_beacon_key(const uint8_t net_key[16], } int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags, - const uint8_t net_id[16], uint32_t iv_index, + const uint8_t net_id[8], uint32_t iv_index, uint8_t auth[8]); static inline int bt_mesh_app_id(const uint8_t app_key[16], uint8_t app_id[1]) From c79a7abbbdcc091136efba684380ada38d1e0ab2 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 23 Dec 2021 14:30:30 +0100 Subject: [PATCH 281/306] nimble/mesh: Fix bt_mesh_keys_resolve declaration app_key is expected to be a pointer to pointer and not artay of pointers. --- nimble/host/mesh/src/app_keys.c | 2 +- nimble/host/mesh/src/app_keys.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nimble/host/mesh/src/app_keys.c b/nimble/host/mesh/src/app_keys.c index acc51f2a60..cfe82576ab 100644 --- a/nimble/host/mesh/src/app_keys.c +++ b/nimble/host/mesh/src/app_keys.c @@ -495,7 +495,7 @@ ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max, int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx, struct bt_mesh_subnet **sub, - const uint8_t *app_key[16], uint8_t *aid) + const uint8_t **app_key, uint8_t *aid) { struct app_key *app = NULL; diff --git a/nimble/host/mesh/src/app_keys.h b/nimble/host/mesh/src/app_keys.h index 3ef9ce7c8f..40df664506 100644 --- a/nimble/host/mesh/src/app_keys.h +++ b/nimble/host/mesh/src/app_keys.h @@ -41,7 +41,7 @@ int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx, */ int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx, struct bt_mesh_subnet **sub, - const uint8_t *app_key[16], uint8_t *aid); + const uint8_t **app_key, uint8_t *aid); /** @brief Iterate through all matching application keys and call @c cb on each. * From a724f0b9befa398a17337a979d07f26a8be60d27 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 23 Dec 2021 14:31:42 +0100 Subject: [PATCH 282/306] nimble/mesh: Fix garbage in debug log meta was used uninitialed in this log. --- nimble/host/mesh/src/friend.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index c7603a8d94..4ce0bbdece 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -438,9 +438,6 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, return 0; } - BT_DBG("Re-encrypting friend pdu (SeqNum %06x -> %06x)", - meta.crypto.seq_num, bt_mesh.seq); - err = unseg_app_sdu_unpack(frnd, buf, &meta); if (err) { return err; From 984566d9760c6f71ee2121ffdbf99ba6ad6de8f7 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 23 Dec 2021 14:32:42 +0100 Subject: [PATCH 283/306] nimble/transport: Fix unused variable in socket transport btaddr is not used anywhere in ble_hci_sock_cmdevt_tx function. --- nimble/transport/socket/src/ble_hci_socket.c | 1 - 1 file changed, 1 deletion(-) diff --git a/nimble/transport/socket/src/ble_hci_socket.c b/nimble/transport/socket/src/ble_hci_socket.c index 44de8fed53..b444a24032 100644 --- a/nimble/transport/socket/src/ble_hci_socket.c +++ b/nimble/transport/socket/src/ble_hci_socket.c @@ -333,7 +333,6 @@ ble_hci_sock_acl_tx(struct os_mbuf *om) static int ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type) { - uint8_t btaddr[6]; struct msghdr msg; struct iovec iov[8]; int len; From 3a6ab21ad4f9e731f69e380f5422d98c9ad296b8 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 23 Dec 2021 14:33:46 +0100 Subject: [PATCH 284/306] nimble/ports: Refresh syscfg --- .../examples/linux/include/logcfg/logcfg.h | 9 +- .../examples/linux/include/syscfg/syscfg.h | 143 ++++-- .../linux/include/sysflash/sysflash.h | 2 +- .../linux_blemesh/include/logcfg/logcfg.h | 72 +-- .../linux_blemesh/include/syscfg/syscfg.h | 451 +++++++++++------- .../linux_blemesh/include/sysflash/sysflash.h | 2 +- .../examples/nuttx/include/logcfg/logcfg.h | 9 +- .../examples/nuttx/include/syscfg/syscfg.h | 191 ++++---- .../nuttx/include/sysflash/sysflash.h | 2 +- porting/nimble/include/logcfg/logcfg.h | 9 +- porting/nimble/include/syscfg/syscfg.h | 149 ++++-- porting/nimble/include/sysflash/sysflash.h | 2 +- porting/npl/riot/include/logcfg/logcfg.h | 9 +- porting/npl/riot/include/syscfg/syscfg.h | 103 +--- porting/npl/riot/include/sysflash/sysflash.h | 2 +- 15 files changed, 689 insertions(+), 466 deletions(-) diff --git a/porting/examples/linux/include/logcfg/logcfg.h b/porting/examples/linux/include/logcfg/logcfg.h index 837cdeac1f..fab4d812fc 100644 --- a/porting/examples/linux/include/logcfg/logcfg.h +++ b/porting/examples/linux/include/logcfg/logcfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_LOGCFG_ @@ -22,11 +22,4 @@ #define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__) #define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__) -#define MFG_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_INFO(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_WARN(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_ERROR(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_CRITICAL(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_DISABLED(...) MODLOG_DISABLED(128, __VA_ARGS__) - #endif diff --git a/porting/examples/linux/include/syscfg/syscfg.h b/porting/examples/linux/include/syscfg/syscfg.h index 8363336eed..fc9ef468fc 100644 --- a/porting/examples/linux/include/syscfg/syscfg.h +++ b/porting/examples/linux/include/syscfg/syscfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSCFG_ @@ -28,11 +28,20 @@ #define MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG (0) #endif +/*** @apache-mynewt-core/hw/bsp/native */ +#ifndef MYNEWT_VAL_BSP_SIMULATED +#define MYNEWT_VAL_BSP_SIMULATED (1) +#endif + /*** @apache-mynewt-core/hw/hal */ #ifndef MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS #define MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS (1) #endif +#ifndef MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT +#define MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT (0) +#endif + #ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ #define MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ (16) #endif @@ -45,10 +54,47 @@ #define MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES (0) #endif +#ifndef MYNEWT_VAL_HAL_SBRK +#define MYNEWT_VAL_HAL_SBRK (1) +#endif + #ifndef MYNEWT_VAL_HAL_SYSTEM_RESET_CB #define MYNEWT_VAL_HAL_SYSTEM_RESET_CB (0) #endif +/*** @apache-mynewt-core/hw/mcu/native */ +#ifndef MYNEWT_VAL_I2C_0 +#define MYNEWT_VAL_I2C_0 (0) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE +#define MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_STYLE_NORDIC +#define MYNEWT_VAL_MCU_FLASH_STYLE_NORDIC (0) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_STYLE_ST +#define MYNEWT_VAL_MCU_FLASH_STYLE_ST (1) +#endif + +#ifndef MYNEWT_VAL_MCU_NATIVE +#define MYNEWT_VAL_MCU_NATIVE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_NATIVE_USE_SIGNALS +#define MYNEWT_VAL_MCU_NATIVE_USE_SIGNALS (1) +#endif + +#ifndef MYNEWT_VAL_MCU_TIMER_POLLER_PRIO +#define MYNEWT_VAL_MCU_TIMER_POLLER_PRIO (0) +#endif + +#ifndef MYNEWT_VAL_MCU_UART_POLLER_PRIO +#define MYNEWT_VAL_MCU_UART_POLLER_PRIO (1) +#endif + /*** @apache-mynewt-core/kernel/os */ #ifndef MYNEWT_VAL_FLOAT_USER #define MYNEWT_VAL_FLOAT_USER (0) @@ -94,6 +140,10 @@ #define MYNEWT_VAL_OS_COREDUMP (0) #endif +#ifndef MYNEWT_VAL_OS_COREDUMP_CB +#define MYNEWT_VAL_OS_COREDUMP_CB (0) +#endif + #ifndef MYNEWT_VAL_OS_CPUTIME_FREQ #define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) #endif @@ -102,8 +152,9 @@ #define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_CRASH_FILE_LINE -#define MYNEWT_VAL_OS_CRASH_FILE_LINE (0) +#define MYNEWT_VAL_OS_CRASH_FILE_LINE (1) #endif #ifndef MYNEWT_VAL_OS_CRASH_LOG @@ -142,8 +193,9 @@ #define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MAX (600000) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN -#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (100) +#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (1) #endif #ifndef MYNEWT_VAL_OS_MAIN_STACK_SIZE @@ -210,6 +262,11 @@ #define MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME (0) #endif +/* Overridden by @apache-mynewt-core/hw/mcu/native (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC +#define MYNEWT_VAL_OS_TICKS_PER_SEC (100) +#endif + #ifndef MYNEWT_VAL_OS_TIME_DEBUG #define MYNEWT_VAL_OS_TIME_DEBUG (0) #endif @@ -226,6 +283,33 @@ #define MYNEWT_VAL_WATCHDOG_INTERVAL (30000) #endif +/*** @apache-mynewt-core/net/ip/native_sockets */ +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_MAX +#define MYNEWT_VAL_NATIVE_SOCKETS_MAX (8) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_MAX_UDP +#define MYNEWT_VAL_NATIVE_SOCKETS_MAX_UDP (2048) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_POLL_INTERVAL_MS +#define MYNEWT_VAL_NATIVE_SOCKETS_POLL_INTERVAL_MS (200) +#endif + +#undef MYNEWT_VAL_NATIVE_SOCKETS_POLL_ITVL + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_PRIO +#define MYNEWT_VAL_NATIVE_SOCKETS_PRIO (2) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_STACK_SZ +#define MYNEWT_VAL_NATIVE_SOCKETS_STACK_SZ (4096) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_SYSINIT_STAGE +#define MYNEWT_VAL_NATIVE_SOCKETS_SYSINIT_STAGE (200) +#endif + /*** @apache-mynewt-core/sys/console/stub */ #ifndef MYNEWT_VAL_CONSOLE_UART_BAUD #define MYNEWT_VAL_CONSOLE_UART_BAUD (115200) @@ -244,8 +328,12 @@ #define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10) #endif +#ifndef MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG +#define MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG (0) +#endif + #ifndef MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE -#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (2) +#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (9) #endif /*** @apache-mynewt-core/sys/log/common */ @@ -300,23 +388,6 @@ #define MYNEWT_VAL_LOG_LEVEL (0) #endif -/*** @apache-mynewt-core/sys/mfg */ -#ifndef MYNEWT_VAL_MFG_LOG_LVL -#define MYNEWT_VAL_MFG_LOG_LVL (15) -#endif - -#ifndef MYNEWT_VAL_MFG_LOG_MODULE -#define MYNEWT_VAL_MFG_LOG_MODULE (128) -#endif - -#ifndef MYNEWT_VAL_MFG_MAX_MMRS -#define MYNEWT_VAL_MFG_MAX_MMRS (2) -#endif - -#ifndef MYNEWT_VAL_MFG_SYSINIT_STAGE -#define MYNEWT_VAL_MFG_SYSINIT_STAGE (100) -#endif - /*** @apache-mynewt-core/sys/sys */ #ifndef MYNEWT_VAL_DEBUG_PANIC_ENABLED #define MYNEWT_VAL_DEBUG_PANIC_ENABLED (1) @@ -344,12 +415,14 @@ #define MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT (1) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/sys/sysinit) */ #ifndef MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE -#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (0) +#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (1) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/sys/sysinit) */ #ifndef MYNEWT_VAL_SYSINIT_PANIC_MESSAGE -#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (0) +#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (1) #endif /*** @apache-mynewt-core/util/rwlock */ @@ -366,6 +439,10 @@ #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) #endif +#ifndef MYNEWT_VAL_BLE_HCI_VS +#define MYNEWT_VAL_BLE_HCI_VS (0) +#endif + #ifndef MYNEWT_VAL_BLE_ISO #define MYNEWT_VAL_BLE_ISO (0) #endif @@ -735,16 +812,16 @@ #define MYNEWT_VAL_BLE_SM_SC (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY -#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS +#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif #ifndef MYNEWT_VAL_BLE_SM_SC_LVL #define MYNEWT_VAL_BLE_SM_SC_LVL (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS -#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) #endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST @@ -993,19 +1070,19 @@ #endif #ifndef MYNEWT_VAL_ARCH_NAME -#define MYNEWT_VAL_ARCH_NAME ("dummy") +#define MYNEWT_VAL_ARCH_NAME ("sim") #endif -#ifndef MYNEWT_VAL_ARCH_dummy -#define MYNEWT_VAL_ARCH_dummy (1) +#ifndef MYNEWT_VAL_ARCH_sim +#define MYNEWT_VAL_ARCH_sim (1) #endif #ifndef MYNEWT_VAL_BSP_NAME -#define MYNEWT_VAL_BSP_NAME ("dummy_bsp") +#define MYNEWT_VAL_BSP_NAME ("native") #endif -#ifndef MYNEWT_VAL_BSP_dummy_bsp -#define MYNEWT_VAL_BSP_dummy_bsp (1) +#ifndef MYNEWT_VAL_BSP_native +#define MYNEWT_VAL_BSP_native (1) #endif #ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG diff --git a/porting/examples/linux/include/sysflash/sysflash.h b/porting/examples/linux/include/sysflash/sysflash.h index ab1341b25d..28391ca66a 100644 --- a/porting/examples/linux/include/sysflash/sysflash.h +++ b/porting/examples/linux/include/sysflash/sysflash.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSFLASH_ diff --git a/porting/examples/linux_blemesh/include/logcfg/logcfg.h b/porting/examples/linux_blemesh/include/logcfg/logcfg.h index 798418dabb..c3b5cdf400 100644 --- a/porting/examples/linux_blemesh/include/logcfg/logcfg.h +++ b/porting/examples/linux_blemesh/include/logcfg/logcfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_LOGCFG_ @@ -50,6 +50,13 @@ #define BLE_MESH_FRIEND_LOG_CRITICAL(...) MODLOG_CRITICAL(14, __VA_ARGS__) #define BLE_MESH_FRIEND_LOG_DISABLED(...) MODLOG_DISABLED(14, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_INFO(...) MODLOG_INFO(26, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_WARN(...) MODLOG_WARN(26, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_ERROR(...) MODLOG_ERROR(26, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_CRITICAL(...) MODLOG_CRITICAL(26, __VA_ARGS__) +#define BLE_MESH_HEARTBEAT_LOG_DISABLED(...) MODLOG_DISABLED(26, __VA_ARGS__) + #define BLE_MESH_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_MESH_LOG_INFO(...) MODLOG_INFO(9, __VA_ARGS__) #define BLE_MESH_LOG_WARN(...) MODLOG_WARN(9, __VA_ARGS__) @@ -71,6 +78,13 @@ #define BLE_MESH_MODEL_LOG_CRITICAL(...) MODLOG_CRITICAL(16, __VA_ARGS__) #define BLE_MESH_MODEL_LOG_DISABLED(...) MODLOG_DISABLED(16, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_INFO(...) MODLOG_INFO(23, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_WARN(...) MODLOG_WARN(23, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_ERROR(...) MODLOG_ERROR(23, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_CRITICAL(...) MODLOG_CRITICAL(23, __VA_ARGS__) +#define BLE_MESH_NET_KEYS_LOG_DISABLED(...) MODLOG_DISABLED(23, __VA_ARGS__) + #define BLE_MESH_NET_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_MESH_NET_LOG_INFO(...) MODLOG_INFO(17, __VA_ARGS__) #define BLE_MESH_NET_LOG_WARN(...) MODLOG_WARN(17, __VA_ARGS__) @@ -78,6 +92,20 @@ #define BLE_MESH_NET_LOG_CRITICAL(...) MODLOG_CRITICAL(17, __VA_ARGS__) #define BLE_MESH_NET_LOG_DISABLED(...) MODLOG_DISABLED(17, __VA_ARGS__) +#define BLE_MESH_PROVISIONER_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_PROVISIONER_LOG_INFO(...) MODLOG_INFO(25, __VA_ARGS__) +#define BLE_MESH_PROVISIONER_LOG_WARN(...) MODLOG_WARN(25, __VA_ARGS__) +#define BLE_MESH_PROVISIONER_LOG_ERROR(...) MODLOG_ERROR(25, __VA_ARGS__) +#define BLE_MESH_PROVISIONER_LOG_CRITICAL(...) MODLOG_CRITICAL(25, __VA_ARGS__) +#define BLE_MESH_PROVISIONER_LOG_DISABLED(...) MODLOG_DISABLED(25, __VA_ARGS__) + +#define BLE_MESH_PROV_DEVICE_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_INFO(...) MODLOG_INFO(24, __VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_WARN(...) MODLOG_WARN(24, __VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_ERROR(...) MODLOG_ERROR(24, __VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_CRITICAL(...) MODLOG_CRITICAL(24, __VA_ARGS__) +#define BLE_MESH_PROV_DEVICE_LOG_DISABLED(...) MODLOG_DISABLED(24, __VA_ARGS__) + #define BLE_MESH_PROV_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_MESH_PROV_LOG_INFO(...) MODLOG_INFO(18, __VA_ARGS__) #define BLE_MESH_PROV_LOG_WARN(...) MODLOG_WARN(18, __VA_ARGS__) @@ -92,6 +120,13 @@ #define BLE_MESH_PROXY_LOG_CRITICAL(...) MODLOG_CRITICAL(19, __VA_ARGS__) #define BLE_MESH_PROXY_LOG_DISABLED(...) MODLOG_DISABLED(19, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_MESH_RPL_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_MESH_RPL_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #define BLE_MESH_SETTINGS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_MESH_SETTINGS_LOG_INFO(...) MODLOG_INFO(20, __VA_ARGS__) #define BLE_MESH_SETTINGS_LOG_WARN(...) MODLOG_WARN(20, __VA_ARGS__) @@ -106,34 +141,6 @@ #define BLE_MESH_TRANS_LOG_CRITICAL(...) MODLOG_CRITICAL(21, __VA_ARGS__) #define BLE_MESH_TRANS_LOG_DISABLED(...) MODLOG_DISABLED(21, __VA_ARGS__) -#define BLE_MESH_RPL_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define BLE_MESH_RPL_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) -#define BLE_MESH_RPL_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) -#define BLE_MESH_RPL_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) -#define BLE_MESH_RPL_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) -#define BLE_MESH_RPL_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) - -#define BLE_MESH_NET_KEYS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define BLE_MESH_NET_KEYS_LOG_INFO(...) MODLOG_INFO(23, __VA_ARGS__) -#define BLE_MESH_NET_KEYS_LOG_WARN(...) MODLOG_WARN(23, __VA_ARGS__) -#define BLE_MESH_NET_KEYS_LOG_ERROR(...) MODLOG_ERROR(23, __VA_ARGS__) -#define BLE_MESH_NET_KEYS_LOG_CRITICAL(...) MODLOG_CRITICAL(23, __VA_ARGS__) -#define BLE_MESH_NET_KEYS_LOG_DISABLED(...) MODLOG_DISABLED(23, __VA_ARGS__) - -#define BLE_MESH_PROV_DEVICE_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define BLE_MESH_PROV_DEVICE_LOG_INFO(...) MODLOG_INFO(24, __VA_ARGS__) -#define BLE_MESH_PROV_DEVICE_LOG_WARN(...) MODLOG_WARN(24, __VA_ARGS__) -#define BLE_MESH_PROV_DEVICE_LOG_ERROR(...) MODLOG_ERROR(24, __VA_ARGS__) -#define BLE_MESH_PROV_DEVICE_LOG_CRITICAL(...) MODLOG_CRITICAL(24, __VA_ARGS__) -#define BLE_MESH_PROV_DEVICE_LOG_DISABLED(...) MODLOG_DISABLED(24, __VA_ARGS__) - -#define BLE_MESH_HEARTBEAT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define BLE_MESH_HEARTBEAT_LOG_INFO(...) MODLOG_INFO(25, __VA_ARGS__) -#define BLE_MESH_HEARTBEAT_LOG_WARN(...) MODLOG_WARN(25, __VA_ARGS__) -#define BLE_MESH_HEARTBEAT_LOG_ERROR(...) MODLOG_ERROR(25, __VA_ARGS__) -#define BLE_MESH_HEARTBEAT_LOG_CRITICAL(...) MODLOG_CRITICAL(25, __VA_ARGS__) -#define BLE_MESH_HEARTBEAT_LOG_DISABLED(...) MODLOG_DISABLED(25, __VA_ARGS__) - #define DFLT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define DFLT_LOG_INFO(...) MODLOG_INFO(0, __VA_ARGS__) #define DFLT_LOG_WARN(...) MODLOG_WARN(0, __VA_ARGS__) @@ -141,11 +148,4 @@ #define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__) #define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__) -#define MFG_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_INFO(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_WARN(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_ERROR(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_CRITICAL(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_DISABLED(...) MODLOG_DISABLED(128, __VA_ARGS__) - #endif diff --git a/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/porting/examples/linux_blemesh/include/syscfg/syscfg.h index 5d21359010..3f9258d896 100644 --- a/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSCFG_ @@ -28,11 +28,20 @@ #define MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG (0) #endif +/*** @apache-mynewt-core/hw/bsp/native */ +#ifndef MYNEWT_VAL_BSP_SIMULATED +#define MYNEWT_VAL_BSP_SIMULATED (1) +#endif + /*** @apache-mynewt-core/hw/hal */ #ifndef MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS #define MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS (1) #endif +#ifndef MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT +#define MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT (0) +#endif + #ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ #define MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ (16) #endif @@ -45,10 +54,47 @@ #define MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES (0) #endif +#ifndef MYNEWT_VAL_HAL_SBRK +#define MYNEWT_VAL_HAL_SBRK (1) +#endif + #ifndef MYNEWT_VAL_HAL_SYSTEM_RESET_CB #define MYNEWT_VAL_HAL_SYSTEM_RESET_CB (0) #endif +/*** @apache-mynewt-core/hw/mcu/native */ +#ifndef MYNEWT_VAL_I2C_0 +#define MYNEWT_VAL_I2C_0 (0) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE +#define MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_STYLE_NORDIC +#define MYNEWT_VAL_MCU_FLASH_STYLE_NORDIC (0) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_STYLE_ST +#define MYNEWT_VAL_MCU_FLASH_STYLE_ST (1) +#endif + +#ifndef MYNEWT_VAL_MCU_NATIVE +#define MYNEWT_VAL_MCU_NATIVE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_NATIVE_USE_SIGNALS +#define MYNEWT_VAL_MCU_NATIVE_USE_SIGNALS (1) +#endif + +#ifndef MYNEWT_VAL_MCU_TIMER_POLLER_PRIO +#define MYNEWT_VAL_MCU_TIMER_POLLER_PRIO (0) +#endif + +#ifndef MYNEWT_VAL_MCU_UART_POLLER_PRIO +#define MYNEWT_VAL_MCU_UART_POLLER_PRIO (1) +#endif + /*** @apache-mynewt-core/kernel/os */ #ifndef MYNEWT_VAL_FLOAT_USER #define MYNEWT_VAL_FLOAT_USER (0) @@ -95,6 +141,10 @@ #define MYNEWT_VAL_OS_COREDUMP (0) #endif +#ifndef MYNEWT_VAL_OS_COREDUMP_CB +#define MYNEWT_VAL_OS_COREDUMP_CB (0) +#endif + #ifndef MYNEWT_VAL_OS_CPUTIME_FREQ #define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) #endif @@ -103,8 +153,9 @@ #define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_CRASH_FILE_LINE -#define MYNEWT_VAL_OS_CRASH_FILE_LINE (0) +#define MYNEWT_VAL_OS_CRASH_FILE_LINE (1) #endif #ifndef MYNEWT_VAL_OS_CRASH_LOG @@ -143,8 +194,9 @@ #define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MAX (600000) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN -#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (100) +#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (1) #endif #ifndef MYNEWT_VAL_OS_MAIN_STACK_SIZE @@ -211,6 +263,11 @@ #define MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME (0) #endif +/* Overridden by @apache-mynewt-core/hw/mcu/native (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC +#define MYNEWT_VAL_OS_TICKS_PER_SEC (100) +#endif + #ifndef MYNEWT_VAL_OS_TIME_DEBUG #define MYNEWT_VAL_OS_TIME_DEBUG (0) #endif @@ -227,6 +284,33 @@ #define MYNEWT_VAL_WATCHDOG_INTERVAL (30000) #endif +/*** @apache-mynewt-core/net/ip/native_sockets */ +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_MAX +#define MYNEWT_VAL_NATIVE_SOCKETS_MAX (8) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_MAX_UDP +#define MYNEWT_VAL_NATIVE_SOCKETS_MAX_UDP (2048) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_POLL_INTERVAL_MS +#define MYNEWT_VAL_NATIVE_SOCKETS_POLL_INTERVAL_MS (200) +#endif + +#undef MYNEWT_VAL_NATIVE_SOCKETS_POLL_ITVL + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_PRIO +#define MYNEWT_VAL_NATIVE_SOCKETS_PRIO (2) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_STACK_SZ +#define MYNEWT_VAL_NATIVE_SOCKETS_STACK_SZ (4096) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_SYSINIT_STAGE +#define MYNEWT_VAL_NATIVE_SOCKETS_SYSINIT_STAGE (200) +#endif + /*** @apache-mynewt-core/sys/console/stub */ #ifndef MYNEWT_VAL_CONSOLE_UART_BAUD #define MYNEWT_VAL_CONSOLE_UART_BAUD (115200) @@ -245,8 +329,12 @@ #define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10) #endif +#ifndef MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG +#define MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG (0) +#endif + #ifndef MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE -#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (2) +#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (9) #endif /*** @apache-mynewt-core/sys/log/common */ @@ -301,23 +389,6 @@ #define MYNEWT_VAL_LOG_LEVEL (0) #endif -/*** @apache-mynewt-core/sys/mfg */ -#ifndef MYNEWT_VAL_MFG_LOG_LVL -#define MYNEWT_VAL_MFG_LOG_LVL (15) -#endif - -#ifndef MYNEWT_VAL_MFG_LOG_MODULE -#define MYNEWT_VAL_MFG_LOG_MODULE (128) -#endif - -#ifndef MYNEWT_VAL_MFG_MAX_MMRS -#define MYNEWT_VAL_MFG_MAX_MMRS (2) -#endif - -#ifndef MYNEWT_VAL_MFG_SYSINIT_STAGE -#define MYNEWT_VAL_MFG_SYSINIT_STAGE (100) -#endif - /*** @apache-mynewt-core/sys/sys */ #ifndef MYNEWT_VAL_DEBUG_PANIC_ENABLED #define MYNEWT_VAL_DEBUG_PANIC_ENABLED (1) @@ -345,12 +416,14 @@ #define MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT (1) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/sys/sysinit) */ #ifndef MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE -#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (0) +#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (1) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/sys/sysinit) */ #ifndef MYNEWT_VAL_SYSINIT_PANIC_MESSAGE -#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (0) +#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (1) #endif /*** @apache-mynewt-core/util/rwlock */ @@ -367,6 +440,10 @@ #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) #endif +#ifndef MYNEWT_VAL_BLE_HCI_VS +#define MYNEWT_VAL_BLE_HCI_VS (0) +#endif + #ifndef MYNEWT_VAL_BLE_ISO #define MYNEWT_VAL_BLE_ISO (0) #endif @@ -738,16 +815,16 @@ #define MYNEWT_VAL_BLE_SM_SC (1) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY -#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS +#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif #ifndef MYNEWT_VAL_BLE_SM_SC_LVL #define MYNEWT_VAL_BLE_SM_SC_LVL (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS -#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) #endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST @@ -763,6 +840,10 @@ #endif /*** @apache-mynewt-nimble/nimble/host/mesh */ +#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG +#define MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LOG_LVL #define MYNEWT_VAL_BLE_MESH_ACCESS_LOG_LVL (1) #endif @@ -771,15 +852,23 @@ #define MYNEWT_VAL_BLE_MESH_ACCESS_LOG_MOD (10) #endif -/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ -#ifndef MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE -#define MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE (4) +#ifndef MYNEWT_VAL_BLE_MESH_ADV +#define MYNEWT_VAL_BLE_MESH_ADV (1) #endif +/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT #define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (20) #endif +#ifndef MYNEWT_VAL_BLE_MESH_ADV_EXT +#define MYNEWT_VAL_BLE_MESH_ADV_EXT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_ADV_LEGACY +#define MYNEWT_VAL_BLE_MESH_ADV_LEGACY (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_ADV_LOG_LVL #define MYNEWT_VAL_BLE_MESH_ADV_LOG_LVL (1) #endif @@ -788,6 +877,10 @@ #define MYNEWT_VAL_BLE_MESH_ADV_LOG_MOD (11) #endif +#ifndef MYNEWT_VAL_BLE_MESH_ADV_STACK_SIZE +#define MYNEWT_VAL_BLE_MESH_ADV_STACK_SIZE (768) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO #define MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO (9) #endif @@ -797,6 +890,10 @@ #define MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT (4) #endif +#ifndef MYNEWT_VAL_BLE_MESH_BEACON_ENABLED +#define MYNEWT_VAL_BLE_MESH_BEACON_ENABLED (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_BEACON_LOG_LVL #define MYNEWT_VAL_BLE_MESH_BEACON_LOG_LVL (1) #endif @@ -805,6 +902,22 @@ #define MYNEWT_VAL_BLE_MESH_BEACON_LOG_MOD (12) #endif +#ifndef MYNEWT_VAL_BLE_MESH_CDB +#define MYNEWT_VAL_BLE_MESH_CDB (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT +#define MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT +#define MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT (8) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT +#define MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT (1) +#endif + /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_CFG_CLI #define MYNEWT_VAL_BLE_MESH_CFG_CLI (1) @@ -822,6 +935,22 @@ #define MYNEWT_VAL_BLE_MESH_CRYPTO_LOG_MOD (13) #endif +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_CDB +#define MYNEWT_VAL_BLE_MESH_DEBUG_CDB (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_CFG +#define MYNEWT_VAL_BLE_MESH_DEBUG_CFG (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_USE_ID_ADDR +#define MYNEWT_VAL_BLE_MESH_DEBUG_USE_ID_ADDR (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_DEFAULT_TTL +#define MYNEWT_VAL_BLE_MESH_DEFAULT_TTL (7) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_DEVICE_NAME #define MYNEWT_VAL_BLE_MESH_DEVICE_NAME ("nimble-mesh-node") #endif @@ -835,6 +964,10 @@ #define MYNEWT_VAL_BLE_MESH_FRIEND (1) #endif +#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED +#define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_FRIEND_LOG_LVL #define MYNEWT_VAL_BLE_MESH_FRIEND_LOG_LVL (1) #endif @@ -863,19 +996,43 @@ #define MYNEWT_VAL_BLE_MESH_FRIEND_SUB_LIST_SIZE (3) #endif +#ifndef MYNEWT_VAL_BLE_MESH_GATT +#define MYNEWT_VAL_BLE_MESH_GATT (1) +#endif + /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY #define MYNEWT_VAL_BLE_MESH_GATT_PROXY (1) #endif +#ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED +#define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_GATT_SERVER +#define MYNEWT_VAL_BLE_MESH_GATT_SERVER (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_HEALTH_CLI #define MYNEWT_VAL_BLE_MESH_HEALTH_CLI (0) #endif +#ifndef MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_LVL +#define MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_MOD +#define MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_MOD (26) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_IVU_DIVIDER #define MYNEWT_VAL_BLE_MESH_IVU_DIVIDER (4) #endif +#ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT +#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT (0x800000) +#endif + /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST #define MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST (1) @@ -894,6 +1051,10 @@ #define MYNEWT_VAL_BLE_MESH_LOG_MOD (9) #endif +#ifndef MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS +#define MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS (3) +#endif + /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_LOW_POWER #define MYNEWT_VAL_BLE_MESH_LOW_POWER (1) @@ -924,10 +1085,6 @@ #define MYNEWT_VAL_BLE_MESH_LPN_GROUPS (10) #endif -#ifndef MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR -#define MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR (1) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT #define MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT (MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT) #endif @@ -960,6 +1117,10 @@ #define MYNEWT_VAL_BLE_MESH_LPN_SCAN_LATENCY (10) #endif +#ifndef MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR +#define MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR (0) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_MODEL_EXTENSIONS #define MYNEWT_VAL_BLE_MESH_MODEL_EXTENSIONS (0) #endif @@ -981,10 +1142,35 @@ #define MYNEWT_VAL_BLE_MESH_MODEL_LOG_MOD (16) #endif +/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE +#define MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE #define MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE (10) #endif +#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT +#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT (2) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL +#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL (20) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE +#define MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE (4) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_LVL +#define MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_MOD +#define MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_MOD (23) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_NET_LOG_LVL #define MYNEWT_VAL_BLE_MESH_NET_LOG_LVL (1) #endif @@ -993,10 +1179,6 @@ #define MYNEWT_VAL_BLE_MESH_NET_LOG_MOD (17) #endif -#ifndef MYNEWT_VAL_BLE_MESH_NODE_COUNT -#define MYNEWT_VAL_BLE_MESH_NODE_COUNT (1) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_NODE_ID_TIMEOUT #define MYNEWT_VAL_BLE_MESH_NODE_ID_TIMEOUT (60) #endif @@ -1017,75 +1199,51 @@ #define MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_SIZE (4) #endif -#ifndef MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN -#if MYNEWT_VAL_BLE_MESH_PB_GATT -#define MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN (66) -#elif MYNEWT_VAL_BLE_MESH_GATT_PROXY -#define MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN (33) -#endif -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE -#define MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG -#define MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT -#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT (0x800000) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY -#define MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY (0) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_ADV_EXT -#define MYNEWT_VAL_BLE_MESH_ADV_EXT (0) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_ADV_LEGACY -#define MYNEWT_VAL_BLE_MESH_ADV_LEGACY (1) -#endif - -#ifndef MYNEWT_VAL_BSP_NRF51 -#define MYNEWT_VAL_BSP_NRF51 (0) -#endif - /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_PB_ADV #define MYNEWT_VAL_BLE_MESH_PB_ADV (1) #endif +#ifndef MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT (500) +#endif + /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_PB_GATT #define MYNEWT_VAL_BLE_MESH_PB_GATT (1) #endif +#ifndef MYNEWT_VAL_BLE_MESH_PB_GATT_USE_DEVICE_NAME +#define MYNEWT_VAL_BLE_MESH_PB_GATT_USE_DEVICE_NAME (1) +#endif + /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_PROV #define MYNEWT_VAL_BLE_MESH_PROV (1) #endif #ifndef MYNEWT_VAL_BLE_MESH_PROVISIONER -#define MYNEWT_VAL_BLE_MESH_PROVISIONER (0) +#define MYNEWT_VAL_BLE_MESH_PROVISIONER (1) #endif -#ifndef MYNEWT_VAL_BLE_MESH_CDB -#define MYNEWT_VAL_BLE_MESH_CDB (0) +#ifndef MYNEWT_VAL_BLE_MESH_PROVISIONER_LOG_LVL +#define MYNEWT_VAL_BLE_MESH_PROVISIONER_LOG_LVL (1) #endif -#ifndef MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT -#define MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT (1) +#ifndef MYNEWT_VAL_BLE_MESH_PROVISIONER_LOG_MOD +#define MYNEWT_VAL_BLE_MESH_PROVISIONER_LOG_MOD (25) #endif -#ifndef MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT -#define MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT (8) +#ifndef MYNEWT_VAL_BLE_MESH_PROV_DEVICE +#define MYNEWT_VAL_BLE_MESH_PROV_DEVICE (1) #endif -#ifndef MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT -#define MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT (1) +#ifndef MYNEWT_VAL_BLE_MESH_PROV_DEVICE_LOG_LVL +#define MYNEWT_VAL_BLE_MESH_PROV_DEVICE_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_PROV_DEVICE_LOG_MOD +#define MYNEWT_VAL_BLE_MESH_PROV_DEVICE_LOG_MOD (24) #endif #ifndef MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL @@ -1096,13 +1254,17 @@ #define MYNEWT_VAL_BLE_MESH_PROV_LOG_MOD (18) #endif +#ifndef MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY +#define MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY (0) +#endif + /* Overridden by @apache-mynewt-nimble/nimble/host/mesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_PROXY #define MYNEWT_VAL_BLE_MESH_PROXY (1) #endif #ifndef MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE -#define MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE (1) +#define MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE (3) #endif #ifndef MYNEWT_VAL_BLE_MESH_PROXY_LOG_LVL @@ -1113,17 +1275,43 @@ #define MYNEWT_VAL_BLE_MESH_PROXY_LOG_MOD (19) #endif +/* Overridden by @apache-mynewt-nimble/nimble/host/mesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN +#define MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN (66) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_PROXY_USE_DEVICE_NAME +#define MYNEWT_VAL_BLE_MESH_PROXY_USE_DEVICE_NAME (0) +#endif + /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_RELAY #define MYNEWT_VAL_BLE_MESH_RELAY (1) #endif -#ifndef MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT -#define MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT (5) +/* Value copied from BLE_MESH_RELAY */ +#ifndef MYNEWT_VAL_BLE_MESH_RELAY_ENABLED +#define MYNEWT_VAL_BLE_MESH_RELAY_ENABLED (1) #endif -#ifndef MYNEWT_VAL_BLE_MESH_SEG_BUFS -#define MYNEWT_VAL_BLE_MESH_SEG_BUFS (72) +#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT +#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT (2) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL +#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RPL_LOG_LVL +#define MYNEWT_VAL_BLE_MESH_RPL_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RPL_LOG_MOD +#define MYNEWT_VAL_BLE_MESH_RPL_LOG_MOD (22) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT (5) #endif #ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MAX @@ -1134,6 +1322,10 @@ #define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (2) #endif +#ifndef MYNEWT_VAL_BLE_MESH_SEG_BUFS +#define MYNEWT_VAL_BLE_MESH_SEG_BUFS (64) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_SEG_RETRANSMIT_ATTEMPTS #define MYNEWT_VAL_BLE_MESH_SEG_RETRANSMIT_ATTEMPTS (4) #endif @@ -1194,90 +1386,29 @@ #define MYNEWT_VAL_BLE_MESH_TRANS_LOG_MOD (21) #endif -/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ -#ifndef MYNEWT_VAL_BLE_MESH_RPL_LOG_LVL -#define MYNEWT_VAL_BLE_MESH_RPL_LOG_LVL (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_RPL_LOG_MOD -#define MYNEWT_VAL_BLE_MESH_RPL_LOG_MOD (22) -#endif - /* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MAX #define MYNEWT_VAL_BLE_MESH_TX_SEG_MAX (6) #endif -#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT -#define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (3) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT -#define MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT (5) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT -#define MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT (500) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT -#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (4) +#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (1) #endif #ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_COUNT #define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_COUNT (4) #endif -#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST -#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST (400) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP #define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP (50) #endif -#ifndef MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS -#define MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS (3) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_DEFAULT_TTL -#define MYNEWT_VAL_BLE_MESH_DEFAULT_TTL (7) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT -#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT (2) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL -#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL (20) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT -#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT (2) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_BEACON_ENABLED -#define MYNEWT_VAL_BLE_MESH_BEACON_ENABLED (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED -#define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_GATT_SERVER -#define MYNEWT_VAL_BLE_MESH_GATT_SERVER (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED -#define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_RELAY_ENABLED -#define MYNEWT_VAL_BLE_MESH_RELAY_ENABLED (1) +#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST +#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST (400) #endif -#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL -#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20) +#ifndef MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT +#define MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT (5) #endif /*** @apache-mynewt-nimble/nimble/host/services/ans */ @@ -1514,19 +1645,19 @@ #endif #ifndef MYNEWT_VAL_ARCH_NAME -#define MYNEWT_VAL_ARCH_NAME ("dummy") +#define MYNEWT_VAL_ARCH_NAME ("sim") #endif -#ifndef MYNEWT_VAL_ARCH_dummy -#define MYNEWT_VAL_ARCH_dummy (1) +#ifndef MYNEWT_VAL_ARCH_sim +#define MYNEWT_VAL_ARCH_sim (1) #endif #ifndef MYNEWT_VAL_BSP_NAME -#define MYNEWT_VAL_BSP_NAME ("dummy_bsp") +#define MYNEWT_VAL_BSP_NAME ("native") #endif -#ifndef MYNEWT_VAL_BSP_dummy_bsp -#define MYNEWT_VAL_BSP_dummy_bsp (1) +#ifndef MYNEWT_VAL_BSP_native +#define MYNEWT_VAL_BSP_native (1) #endif #ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG diff --git a/porting/examples/linux_blemesh/include/sysflash/sysflash.h b/porting/examples/linux_blemesh/include/sysflash/sysflash.h index ab1341b25d..28391ca66a 100644 --- a/porting/examples/linux_blemesh/include/sysflash/sysflash.h +++ b/porting/examples/linux_blemesh/include/sysflash/sysflash.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSFLASH_ diff --git a/porting/examples/nuttx/include/logcfg/logcfg.h b/porting/examples/nuttx/include/logcfg/logcfg.h index 837cdeac1f..fab4d812fc 100644 --- a/porting/examples/nuttx/include/logcfg/logcfg.h +++ b/porting/examples/nuttx/include/logcfg/logcfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_LOGCFG_ @@ -22,11 +22,4 @@ #define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__) #define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__) -#define MFG_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_INFO(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_WARN(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_ERROR(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_CRITICAL(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_DISABLED(...) MODLOG_DISABLED(128, __VA_ARGS__) - #endif diff --git a/porting/examples/nuttx/include/syscfg/syscfg.h b/porting/examples/nuttx/include/syscfg/syscfg.h index c8ad4e4976..1f5be13597 100644 --- a/porting/examples/nuttx/include/syscfg/syscfg.h +++ b/porting/examples/nuttx/include/syscfg/syscfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSCFG_ @@ -15,86 +15,84 @@ #define MYNEWT_VAL(_name) MYNEWT_VAL_ ## _name #define MYNEWT_VAL_CHOICE(_name, _val) MYNEWT_VAL_ ## _name ## __ ## _val - -/*** Repository @apache-mynewt-core info */ -#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE ("4d75fc41bd7ead84638ebbfad4841d5effb296dd") +/*** @apache-mynewt-core/crypto/tinycrypt */ +#ifndef MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE +#define MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE (200) #endif -#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE -#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE ("0.0.1") +#ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME +#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME ("trng") #endif -/*** Repository @apache-mynewt-mcumgr info */ -#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR ("8d087a7e0e5485394419d10051606c92d68d2111") +#ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG +#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG (0) #endif -#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR -#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR ("0.0.0") +/*** @apache-mynewt-core/hw/bsp/native */ +#ifndef MYNEWT_VAL_BSP_SIMULATED +#define MYNEWT_VAL_BSP_SIMULATED (1) #endif -/*** Repository @apache-mynewt-nimble info */ -#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE ("37dceb35df57ff41a6c31f79290512df2fde7064") +/*** @apache-mynewt-core/hw/hal */ +#ifndef MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS +#define MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS (1) #endif -#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE -#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE ("0.0.0") +#ifndef MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT +#define MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT (0) #endif -/*** Repository @mcuboot info */ -#ifndef MYNEWT_VAL_REPO_HASH_MCUBOOT -#define MYNEWT_VAL_REPO_HASH_MCUBOOT ("03d96ad1f6dd77d47ffca72ade9377acb8559115-dirty") +#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ +#define MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ (16) #endif -#ifndef MYNEWT_VAL_REPO_VERSION_MCUBOOT -#define MYNEWT_VAL_REPO_VERSION_MCUBOOT ("0.0.0") +#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_ERASES +#define MYNEWT_VAL_HAL_FLASH_VERIFY_ERASES (0) #endif -/*** Repository @my_project info */ -#ifndef MYNEWT_VAL_REPO_HASH_MY_PROJECT -#define MYNEWT_VAL_REPO_HASH_MY_PROJECT ("37dceb35df57ff41a6c31f79290512df2fde7064") +#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES +#define MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES (0) #endif -#ifndef MYNEWT_VAL_REPO_VERSION_MY_PROJECT -#define MYNEWT_VAL_REPO_VERSION_MY_PROJECT ("0.0.0") +#ifndef MYNEWT_VAL_HAL_SBRK +#define MYNEWT_VAL_HAL_SBRK (1) #endif +#ifndef MYNEWT_VAL_HAL_SYSTEM_RESET_CB +#define MYNEWT_VAL_HAL_SYSTEM_RESET_CB (0) +#endif - -/*** @apache-mynewt-core/crypto/tinycrypt */ -#ifndef MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE -#define MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE (200) +/*** @apache-mynewt-core/hw/mcu/native */ +#ifndef MYNEWT_VAL_I2C_0 +#define MYNEWT_VAL_I2C_0 (0) #endif -#ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME -#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME ("trng") +#ifndef MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE +#define MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE (1) #endif -#ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG -#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG (0) +#ifndef MYNEWT_VAL_MCU_FLASH_STYLE_NORDIC +#define MYNEWT_VAL_MCU_FLASH_STYLE_NORDIC (0) #endif -/*** @apache-mynewt-core/hw/hal */ -#ifndef MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS -#define MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS (1) +#ifndef MYNEWT_VAL_MCU_FLASH_STYLE_ST +#define MYNEWT_VAL_MCU_FLASH_STYLE_ST (1) #endif -#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ -#define MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ (16) +#ifndef MYNEWT_VAL_MCU_NATIVE +#define MYNEWT_VAL_MCU_NATIVE (1) #endif -#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_ERASES -#define MYNEWT_VAL_HAL_FLASH_VERIFY_ERASES (0) +#ifndef MYNEWT_VAL_MCU_NATIVE_USE_SIGNALS +#define MYNEWT_VAL_MCU_NATIVE_USE_SIGNALS (1) #endif -#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES -#define MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES (0) +#ifndef MYNEWT_VAL_MCU_TIMER_POLLER_PRIO +#define MYNEWT_VAL_MCU_TIMER_POLLER_PRIO (0) #endif -#ifndef MYNEWT_VAL_HAL_SYSTEM_RESET_CB -#define MYNEWT_VAL_HAL_SYSTEM_RESET_CB (0) +#ifndef MYNEWT_VAL_MCU_UART_POLLER_PRIO +#define MYNEWT_VAL_MCU_UART_POLLER_PRIO (1) #endif /*** @apache-mynewt-core/kernel/os */ @@ -142,6 +140,10 @@ #define MYNEWT_VAL_OS_COREDUMP (0) #endif +#ifndef MYNEWT_VAL_OS_COREDUMP_CB +#define MYNEWT_VAL_OS_COREDUMP_CB (0) +#endif + #ifndef MYNEWT_VAL_OS_CPUTIME_FREQ #define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) #endif @@ -150,8 +152,9 @@ #define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_CRASH_FILE_LINE -#define MYNEWT_VAL_OS_CRASH_FILE_LINE (0) +#define MYNEWT_VAL_OS_CRASH_FILE_LINE (1) #endif #ifndef MYNEWT_VAL_OS_CRASH_LOG @@ -190,8 +193,9 @@ #define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MAX (600000) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN -#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (100) +#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (1) #endif #ifndef MYNEWT_VAL_OS_MAIN_STACK_SIZE @@ -258,6 +262,11 @@ #define MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME (0) #endif +/* Overridden by @apache-mynewt-core/hw/mcu/native (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC +#define MYNEWT_VAL_OS_TICKS_PER_SEC (100) +#endif + #ifndef MYNEWT_VAL_OS_TIME_DEBUG #define MYNEWT_VAL_OS_TIME_DEBUG (0) #endif @@ -274,6 +283,33 @@ #define MYNEWT_VAL_WATCHDOG_INTERVAL (30000) #endif +/*** @apache-mynewt-core/net/ip/native_sockets */ +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_MAX +#define MYNEWT_VAL_NATIVE_SOCKETS_MAX (8) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_MAX_UDP +#define MYNEWT_VAL_NATIVE_SOCKETS_MAX_UDP (2048) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_POLL_INTERVAL_MS +#define MYNEWT_VAL_NATIVE_SOCKETS_POLL_INTERVAL_MS (200) +#endif + +#undef MYNEWT_VAL_NATIVE_SOCKETS_POLL_ITVL + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_PRIO +#define MYNEWT_VAL_NATIVE_SOCKETS_PRIO (2) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_STACK_SZ +#define MYNEWT_VAL_NATIVE_SOCKETS_STACK_SZ (4096) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_SYSINIT_STAGE +#define MYNEWT_VAL_NATIVE_SOCKETS_SYSINIT_STAGE (200) +#endif + /*** @apache-mynewt-core/sys/console/stub */ #ifndef MYNEWT_VAL_CONSOLE_UART_BAUD #define MYNEWT_VAL_CONSOLE_UART_BAUD (115200) @@ -292,8 +328,12 @@ #define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10) #endif +#ifndef MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG +#define MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG (0) +#endif + #ifndef MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE -#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (2) +#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (9) #endif /*** @apache-mynewt-core/sys/log/common */ @@ -348,23 +388,6 @@ #define MYNEWT_VAL_LOG_LEVEL (2) #endif -/*** @apache-mynewt-core/sys/mfg */ -#ifndef MYNEWT_VAL_MFG_LOG_LVL -#define MYNEWT_VAL_MFG_LOG_LVL (15) -#endif - -#ifndef MYNEWT_VAL_MFG_LOG_MODULE -#define MYNEWT_VAL_MFG_LOG_MODULE (128) -#endif - -#ifndef MYNEWT_VAL_MFG_MAX_MMRS -#define MYNEWT_VAL_MFG_MAX_MMRS (2) -#endif - -#ifndef MYNEWT_VAL_MFG_SYSINIT_STAGE -#define MYNEWT_VAL_MFG_SYSINIT_STAGE (100) -#endif - /*** @apache-mynewt-core/sys/sys */ #ifndef MYNEWT_VAL_DEBUG_PANIC_ENABLED #define MYNEWT_VAL_DEBUG_PANIC_ENABLED (1) @@ -392,12 +415,14 @@ #define MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT (1) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/sys/sysinit) */ #ifndef MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE -#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (0) +#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (1) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/sys/sysinit) */ #ifndef MYNEWT_VAL_SYSINIT_PANIC_MESSAGE -#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (0) +#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (1) #endif /*** @apache-mynewt-core/util/rwlock */ @@ -414,6 +439,10 @@ #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) #endif +#ifndef MYNEWT_VAL_BLE_HCI_VS +#define MYNEWT_VAL_BLE_HCI_VS (0) +#endif + #ifndef MYNEWT_VAL_BLE_ISO #define MYNEWT_VAL_BLE_ISO (0) #endif @@ -785,16 +814,16 @@ #define MYNEWT_VAL_BLE_SM_SC (1) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY -#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS +#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif #ifndef MYNEWT_VAL_BLE_SM_SC_LVL #define MYNEWT_VAL_BLE_SM_SC_LVL (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS -#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) #endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST @@ -1023,16 +1052,10 @@ #define MYNEWT_VAL_BLE_SOCK_TCP_PORT (14433) #endif -/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/transport/socket) */ #ifndef MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE #define MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE (0) #endif -/* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/transport/socket) */ -#ifndef MYNEWT_VAL_BLE_SOCK_USE_NUTTX -#define MYNEWT_VAL_BLE_SOCK_USE_NUTTX (1) -#endif - /* Overridden by @apache-mynewt-nimble/porting/targets/nuttx (defined by @apache-mynewt-nimble/nimble/transport/socket) */ #ifndef MYNEWT_VAL_BLE_SOCK_USE_TCP #define MYNEWT_VAL_BLE_SOCK_USE_TCP (0) @@ -1048,19 +1071,19 @@ #endif #ifndef MYNEWT_VAL_ARCH_NAME -#define MYNEWT_VAL_ARCH_NAME ("dummy") +#define MYNEWT_VAL_ARCH_NAME ("sim") #endif -#ifndef MYNEWT_VAL_ARCH_dummy -#define MYNEWT_VAL_ARCH_dummy (1) +#ifndef MYNEWT_VAL_ARCH_sim +#define MYNEWT_VAL_ARCH_sim (1) #endif #ifndef MYNEWT_VAL_BSP_NAME -#define MYNEWT_VAL_BSP_NAME ("dummy_bsp") +#define MYNEWT_VAL_BSP_NAME ("native") #endif -#ifndef MYNEWT_VAL_BSP_dummy_bsp -#define MYNEWT_VAL_BSP_dummy_bsp (1) +#ifndef MYNEWT_VAL_BSP_native +#define MYNEWT_VAL_BSP_native (1) #endif #ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG diff --git a/porting/examples/nuttx/include/sysflash/sysflash.h b/porting/examples/nuttx/include/sysflash/sysflash.h index ab1341b25d..28391ca66a 100644 --- a/porting/examples/nuttx/include/sysflash/sysflash.h +++ b/porting/examples/nuttx/include/sysflash/sysflash.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSFLASH_ diff --git a/porting/nimble/include/logcfg/logcfg.h b/porting/nimble/include/logcfg/logcfg.h index 837cdeac1f..fab4d812fc 100644 --- a/porting/nimble/include/logcfg/logcfg.h +++ b/porting/nimble/include/logcfg/logcfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_LOGCFG_ @@ -22,11 +22,4 @@ #define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__) #define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__) -#define MFG_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_INFO(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_WARN(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_ERROR(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_CRITICAL(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_DISABLED(...) MODLOG_DISABLED(128, __VA_ARGS__) - #endif diff --git a/porting/nimble/include/syscfg/syscfg.h b/porting/nimble/include/syscfg/syscfg.h index cfc10edb54..a16c528191 100644 --- a/porting/nimble/include/syscfg/syscfg.h +++ b/porting/nimble/include/syscfg/syscfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSCFG_ @@ -28,11 +28,20 @@ #define MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG (0) #endif +/*** @apache-mynewt-core/hw/bsp/native */ +#ifndef MYNEWT_VAL_BSP_SIMULATED +#define MYNEWT_VAL_BSP_SIMULATED (1) +#endif + /*** @apache-mynewt-core/hw/hal */ #ifndef MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS #define MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS (1) #endif +#ifndef MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT +#define MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT (0) +#endif + #ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ #define MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ (16) #endif @@ -45,10 +54,47 @@ #define MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES (0) #endif +#ifndef MYNEWT_VAL_HAL_SBRK +#define MYNEWT_VAL_HAL_SBRK (1) +#endif + #ifndef MYNEWT_VAL_HAL_SYSTEM_RESET_CB #define MYNEWT_VAL_HAL_SYSTEM_RESET_CB (0) #endif +/*** @apache-mynewt-core/hw/mcu/native */ +#ifndef MYNEWT_VAL_I2C_0 +#define MYNEWT_VAL_I2C_0 (0) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE +#define MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_STYLE_NORDIC +#define MYNEWT_VAL_MCU_FLASH_STYLE_NORDIC (0) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_STYLE_ST +#define MYNEWT_VAL_MCU_FLASH_STYLE_ST (1) +#endif + +#ifndef MYNEWT_VAL_MCU_NATIVE +#define MYNEWT_VAL_MCU_NATIVE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_NATIVE_USE_SIGNALS +#define MYNEWT_VAL_MCU_NATIVE_USE_SIGNALS (1) +#endif + +#ifndef MYNEWT_VAL_MCU_TIMER_POLLER_PRIO +#define MYNEWT_VAL_MCU_TIMER_POLLER_PRIO (0) +#endif + +#ifndef MYNEWT_VAL_MCU_UART_POLLER_PRIO +#define MYNEWT_VAL_MCU_UART_POLLER_PRIO (1) +#endif + /*** @apache-mynewt-core/kernel/os */ #ifndef MYNEWT_VAL_FLOAT_USER #define MYNEWT_VAL_FLOAT_USER (0) @@ -94,6 +140,10 @@ #define MYNEWT_VAL_OS_COREDUMP (0) #endif +#ifndef MYNEWT_VAL_OS_COREDUMP_CB +#define MYNEWT_VAL_OS_COREDUMP_CB (0) +#endif + #ifndef MYNEWT_VAL_OS_CPUTIME_FREQ #define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) #endif @@ -102,8 +152,9 @@ #define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_CRASH_FILE_LINE -#define MYNEWT_VAL_OS_CRASH_FILE_LINE (0) +#define MYNEWT_VAL_OS_CRASH_FILE_LINE (1) #endif #ifndef MYNEWT_VAL_OS_CRASH_LOG @@ -142,8 +193,9 @@ #define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MAX (600000) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/kernel/os) */ #ifndef MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN -#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (100) +#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (1) #endif #ifndef MYNEWT_VAL_OS_MAIN_STACK_SIZE @@ -210,6 +262,11 @@ #define MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME (0) #endif +/* Overridden by @apache-mynewt-core/hw/mcu/native (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC +#define MYNEWT_VAL_OS_TICKS_PER_SEC (100) +#endif + #ifndef MYNEWT_VAL_OS_TIME_DEBUG #define MYNEWT_VAL_OS_TIME_DEBUG (0) #endif @@ -226,6 +283,33 @@ #define MYNEWT_VAL_WATCHDOG_INTERVAL (30000) #endif +/*** @apache-mynewt-core/net/ip/native_sockets */ +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_MAX +#define MYNEWT_VAL_NATIVE_SOCKETS_MAX (8) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_MAX_UDP +#define MYNEWT_VAL_NATIVE_SOCKETS_MAX_UDP (2048) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_POLL_INTERVAL_MS +#define MYNEWT_VAL_NATIVE_SOCKETS_POLL_INTERVAL_MS (200) +#endif + +#undef MYNEWT_VAL_NATIVE_SOCKETS_POLL_ITVL + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_PRIO +#define MYNEWT_VAL_NATIVE_SOCKETS_PRIO (2) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_STACK_SZ +#define MYNEWT_VAL_NATIVE_SOCKETS_STACK_SZ (4096) +#endif + +#ifndef MYNEWT_VAL_NATIVE_SOCKETS_SYSINIT_STAGE +#define MYNEWT_VAL_NATIVE_SOCKETS_SYSINIT_STAGE (200) +#endif + /*** @apache-mynewt-core/sys/console/stub */ #ifndef MYNEWT_VAL_CONSOLE_UART_BAUD #define MYNEWT_VAL_CONSOLE_UART_BAUD (115200) @@ -244,8 +328,12 @@ #define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10) #endif +#ifndef MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG +#define MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG (0) +#endif + #ifndef MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE -#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (2) +#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (9) #endif /*** @apache-mynewt-core/sys/log/common */ @@ -299,23 +387,6 @@ #define MYNEWT_VAL_LOG_LEVEL (255) #endif -/*** @apache-mynewt-core/sys/mfg */ -#ifndef MYNEWT_VAL_MFG_LOG_LVL -#define MYNEWT_VAL_MFG_LOG_LVL (15) -#endif - -#ifndef MYNEWT_VAL_MFG_LOG_MODULE -#define MYNEWT_VAL_MFG_LOG_MODULE (128) -#endif - -#ifndef MYNEWT_VAL_MFG_MAX_MMRS -#define MYNEWT_VAL_MFG_MAX_MMRS (2) -#endif - -#ifndef MYNEWT_VAL_MFG_SYSINIT_STAGE -#define MYNEWT_VAL_MFG_SYSINIT_STAGE (100) -#endif - /*** @apache-mynewt-core/sys/sys */ #ifndef MYNEWT_VAL_DEBUG_PANIC_ENABLED #define MYNEWT_VAL_DEBUG_PANIC_ENABLED (1) @@ -343,12 +414,14 @@ #define MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT (1) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/sys/sysinit) */ #ifndef MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE -#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (0) +#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (1) #endif +/* Overridden by @apache-mynewt-core/hw/bsp/native (defined by @apache-mynewt-core/sys/sysinit) */ #ifndef MYNEWT_VAL_SYSINIT_PANIC_MESSAGE -#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (0) +#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (1) #endif /*** @apache-mynewt-core/util/rwlock */ @@ -365,6 +438,10 @@ #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) #endif +#ifndef MYNEWT_VAL_BLE_HCI_VS +#define MYNEWT_VAL_BLE_HCI_VS (0) +#endif + #ifndef MYNEWT_VAL_BLE_ISO #define MYNEWT_VAL_BLE_ISO (0) #endif @@ -734,16 +811,16 @@ #define MYNEWT_VAL_BLE_SM_SC (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY -#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS +#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif #ifndef MYNEWT_VAL_BLE_SM_SC_LVL #define MYNEWT_VAL_BLE_SM_SC_LVL (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS -#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) #endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST @@ -970,12 +1047,14 @@ #define MYNEWT_VAL_BLE_SOCK_TCP_PORT (14433) #endif +/* Overridden by @apache-mynewt-nimble/porting/targets/porting_default (defined by @apache-mynewt-nimble/nimble/transport/socket) */ #ifndef MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE -#define MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE (0) +#define MYNEWT_VAL_BLE_SOCK_USE_LINUX_BLUE (1) #endif +/* Overridden by @apache-mynewt-nimble/porting/targets/porting_default (defined by @apache-mynewt-nimble/nimble/transport/socket) */ #ifndef MYNEWT_VAL_BLE_SOCK_USE_TCP -#define MYNEWT_VAL_BLE_SOCK_USE_TCP (1) +#define MYNEWT_VAL_BLE_SOCK_USE_TCP (0) #endif /*** newt */ @@ -988,19 +1067,19 @@ #endif #ifndef MYNEWT_VAL_ARCH_NAME -#define MYNEWT_VAL_ARCH_NAME ("dummy") +#define MYNEWT_VAL_ARCH_NAME ("sim") #endif -#ifndef MYNEWT_VAL_ARCH_dummy -#define MYNEWT_VAL_ARCH_dummy (1) +#ifndef MYNEWT_VAL_ARCH_sim +#define MYNEWT_VAL_ARCH_sim (1) #endif #ifndef MYNEWT_VAL_BSP_NAME -#define MYNEWT_VAL_BSP_NAME ("dummy_bsp") +#define MYNEWT_VAL_BSP_NAME ("native") #endif -#ifndef MYNEWT_VAL_BSP_dummy_bsp -#define MYNEWT_VAL_BSP_dummy_bsp (1) +#ifndef MYNEWT_VAL_BSP_native +#define MYNEWT_VAL_BSP_native (1) #endif #ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG diff --git a/porting/nimble/include/sysflash/sysflash.h b/porting/nimble/include/sysflash/sysflash.h index ab1341b25d..28391ca66a 100644 --- a/porting/nimble/include/sysflash/sysflash.h +++ b/porting/nimble/include/sysflash/sysflash.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSFLASH_ diff --git a/porting/npl/riot/include/logcfg/logcfg.h b/porting/npl/riot/include/logcfg/logcfg.h index 837cdeac1f..fab4d812fc 100644 --- a/porting/npl/riot/include/logcfg/logcfg.h +++ b/porting/npl/riot/include/logcfg/logcfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_LOGCFG_ @@ -22,11 +22,4 @@ #define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__) #define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__) -#define MFG_LOG_DEBUG(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_INFO(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_WARN(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_ERROR(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_CRITICAL(...) IGNORE(__VA_ARGS__) -#define MFG_LOG_DISABLED(...) MODLOG_DISABLED(128, __VA_ARGS__) - #endif diff --git a/porting/npl/riot/include/syscfg/syscfg.h b/porting/npl/riot/include/syscfg/syscfg.h index 24b49da51d..538c8213b4 100644 --- a/porting/npl/riot/include/syscfg/syscfg.h +++ b/porting/npl/riot/include/syscfg/syscfg.h @@ -15,81 +15,6 @@ #define MYNEWT_VAL(_name) MYNEWT_VAL_ ## _name #define MYNEWT_VAL_CHOICE(_name, _val) MYNEWT_VAL_ ## _name ## __ ## _val - -/*** Repository @apache-mynewt-core info */ -#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_CORE ("49ac781dfadbeecfd03d60bcaac15617744783b7-dirty") -#endif - -#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE -#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_CORE ("0.0.0") -#endif - -/*** Repository @apache-mynewt-mcumgr info */ -#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_MCUMGR ("b03a5d43ef6640d4f8858f59140b256a0ee4e772-dirty") -#endif - -#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR -#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_MCUMGR ("0.0.0") -#endif - -/*** Repository @apache-mynewt-nimble info */ -#ifndef MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE -#define MYNEWT_VAL_REPO_HASH_APACHE_MYNEWT_NIMBLE ("846dda1f93c05aaf38281925b256fdbd5044492d-dirty") -#endif - -#ifndef MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE -#define MYNEWT_VAL_REPO_VERSION_APACHE_MYNEWT_NIMBLE ("0.0.0") -#endif - -/*** Repository @bsim info */ -#ifndef MYNEWT_VAL_REPO_HASH_BSIM -#define MYNEWT_VAL_REPO_HASH_BSIM ("8c5297423a7602b2c0bf47c64c2ac22d55d646ac") -#endif - -#ifndef MYNEWT_VAL_REPO_VERSION_BSIM -#define MYNEWT_VAL_REPO_VERSION_BSIM ("0.0.0") -#endif - -/*** Repository @mcuboot info */ -#ifndef MYNEWT_VAL_REPO_HASH_MCUBOOT -#define MYNEWT_VAL_REPO_HASH_MCUBOOT ("d4c2d15c3ef524333abf7f1e5839265ad5055d96") -#endif - -#ifndef MYNEWT_VAL_REPO_VERSION_MCUBOOT -#define MYNEWT_VAL_REPO_VERSION_MCUBOOT ("0.0.0") -#endif - -/*** Repository @mynewt_runtime info */ -#ifndef MYNEWT_VAL_REPO_HASH_MYNEWT_RUNTIME -#define MYNEWT_VAL_REPO_HASH_MYNEWT_RUNTIME ("17c53cd08300587cb5b6e5647566799eff2de198") -#endif - -#ifndef MYNEWT_VAL_REPO_VERSION_MYNEWT_RUNTIME -#define MYNEWT_VAL_REPO_VERSION_MYNEWT_RUNTIME ("0.0.0") -#endif - -/*** Repository @onsemi info */ -#ifndef MYNEWT_VAL_REPO_HASH_ONSEMI -#define MYNEWT_VAL_REPO_HASH_ONSEMI ("a3bf406b581c1aba025b8fe9472a6d8628e94e53") -#endif - -#ifndef MYNEWT_VAL_REPO_VERSION_ONSEMI -#define MYNEWT_VAL_REPO_VERSION_ONSEMI ("0.0.0") -#endif - -/*** Repository @tinyusb info */ -#ifndef MYNEWT_VAL_REPO_HASH_TINYUSB -#define MYNEWT_VAL_REPO_HASH_TINYUSB ("aa1a5a11c7729548957e5d8baf1c18ba7a333d14") -#endif - -#ifndef MYNEWT_VAL_REPO_VERSION_TINYUSB -#define MYNEWT_VAL_REPO_VERSION_TINYUSB ("0.0.0") -#endif - - - /*** @apache-mynewt-core/compiler/arm-none-eabi-m4 */ #ifndef MYNEWT_VAL_HARDFLOAT #define MYNEWT_VAL_HARDFLOAT (0) @@ -945,7 +870,7 @@ #endif #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ -#define MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ (1) +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ (MYNEWT_VAL_BLE_LL_ROLE_CENTRAL || MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL) #endif #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL @@ -1024,7 +949,7 @@ #endif #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG -#define MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG (1) +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG (MYNEWT_VAL_BLE_LL_ROLE_CENTRAL || MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL) #endif /* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ @@ -1090,10 +1015,6 @@ #define MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_ON_ASSERT (0) #endif -#ifndef MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_STATS_ON_RESET -#define MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_STATS_ON_RESET (0) -#endif - #ifndef MYNEWT_VAL_BLE_LL_MASTER_SCA #define MYNEWT_VAL_BLE_LL_MASTER_SCA (4) #endif @@ -1143,6 +1064,26 @@ #define MYNEWT_VAL_BLE_LL_RNG_BUFSIZE (32) #endif +/* Value copied from BLE_ROLE_BROADCASTER */ +#ifndef MYNEWT_VAL_BLE_LL_ROLE_BROADCASTER +#define MYNEWT_VAL_BLE_LL_ROLE_BROADCASTER (1) +#endif + +/* Value copied from BLE_ROLE_CENTRAL */ +#ifndef MYNEWT_VAL_BLE_LL_ROLE_CENTRAL +#define MYNEWT_VAL_BLE_LL_ROLE_CENTRAL (1) +#endif + +/* Value copied from BLE_ROLE_OBSERVER */ +#ifndef MYNEWT_VAL_BLE_LL_ROLE_OBSERVER +#define MYNEWT_VAL_BLE_LL_ROLE_OBSERVER (1) +#endif + +/* Value copied from BLE_ROLE_PERIPHERAL */ +#ifndef MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL +#define MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL (1) +#endif + /* Value copied from BLE_LL_OUR_SCA */ #ifndef MYNEWT_VAL_BLE_LL_SCA #define MYNEWT_VAL_BLE_LL_SCA (60) diff --git a/porting/npl/riot/include/sysflash/sysflash.h b/porting/npl/riot/include/sysflash/sysflash.h index ab1341b25d..28391ca66a 100644 --- a/porting/npl/riot/include/sysflash/sysflash.h +++ b/porting/npl/riot/include/sysflash/sysflash.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.9.0-dev + * This file was generated by Apache newt version: 1.10.0-dev */ #ifndef H_MYNEWT_SYSFLASH_ From 52d47ada52152cf232092a60cfb7186755c44fc2 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 11 Jan 2022 00:31:03 +0100 Subject: [PATCH 285/306] nimble/ll: Fix rx in advertising state This typo caused advertising to break on 1st received req PDU... --- nimble/controller/src/ble_ll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 56e81a6697..99e8594640 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -1136,7 +1136,7 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) rc = ble_ll_conn_rx_isr_start(rxhdr, ble_phy_access_addr_get()); break; #endif -#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTERL) +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_LL_STATE_ADV: rc = ble_ll_adv_rx_isr_start(pdu_type); break; From 0741f19599f87e1818dd00182caae3c2c9343875 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Tue, 14 Dec 2021 11:19:53 +0100 Subject: [PATCH 286/306] host/gap: improve API for legacy adv for EXT_ADV:=1 The possible combination of options when setting legacy_pdu:=1 in `struct ble_gap_ext_adv_params` was not obvious to API users. This commit improves the API by i) adding accoring documentation and ii) adding a validity check into ble_gap_ext_adv_params_tx(). --- nimble/host/include/host/ble_gap.h | 14 +++++++++++++- nimble/host/src/ble_gap.c | 19 ++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index af9c978bcc..63ae900da5 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -1160,7 +1160,19 @@ struct ble_gap_ext_adv_params { /** If perform high-duty directed advertising */ unsigned int high_duty_directed:1; - /** If use legacy PDUs for advertising */ + /** If use legacy PDUs for advertising. + * + * Valid combinations of the connectable, scannable, directed, + * high_duty_directed options with the legcy_pdu flag are: + * - IND -> legacy_pdu + connectable + scannable + * - LD_DIR -> legacy_pdu + connectable + directed + * - HD_DIR -> legacy_pdu + connectable + directed + high_duty_directed + * - SCAN -> legacy_pdu + scannable + * - NONCONN -> legacy_pdu + * + * Any other combination of these options combined with the legacy_pdu flag + * are invalid. + */ unsigned int legacy_pdu:1; /** If perform anonymous advertising */ diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 8f7e5ca60a..3d8f3038ae 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -2692,15 +2692,28 @@ ble_gap_ext_adv_params_tx(uint8_t instance, if (params->high_duty_directed) { cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED; } - if (params->legacy_pdu) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; - } if (params->anonymous) { cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV; } if (params->include_tx_power) { cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR; } + if (params->legacy_pdu) { + cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; + + /* check right away if the applied configuration is valid before handing + * the command to the controller to improve error reporting */ + switch (cmd.props) { + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_SCAN: + case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN: + break; + default: + return BLE_HS_EINVAL; + } + } /* Fill optional fields if application did not specify them. */ if (params->itvl_min == 0 && params->itvl_max == 0) { From f83627a31d52bd23a63bebfa623b50484840a947 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 10 Jan 2022 10:36:22 +0100 Subject: [PATCH 287/306] nimble/include: fixed vendor command description Proper OGF for vendor specific cmd: 0x3F --- nimble/include/nimble/hci_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 7369518874..4851fd06da 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -1061,7 +1061,7 @@ struct ble_hci_le_set_host_feat_cp { uint8_t val; } __attribute__((packed)); -/* --- Vendor specific commands (OGF 0x00FF) */ +/* --- Vendor specific commands (OGF 0x003F) */ #define BLE_HCI_OCF_VS_RD_STATIC_ADDR (0x0001) struct ble_hci_vs_rd_static_addr_rp { uint8_t addr[6]; From 7e368a9e16d477f69665b19758c214ca565ecd99 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 17 Jan 2022 16:42:33 +0100 Subject: [PATCH 288/306] nimble/phy/nrf: Add support for reading Ublox BMD-345 public address The BMD-345 modules are preprogrammed from the factory with a unique public Bluetooth device address stored in the CUSTOMER[0] and CUSTOMER[1] registers of the User Information Configuration Registers (UICR). --- nimble/drivers/nrf52/src/ble_hw.c | 18 ++++++++++++++++++ nimble/drivers/nrf52/syscfg.yml | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/nimble/drivers/nrf52/src/ble_hw.c b/nimble/drivers/nrf52/src/ble_hw.c index 8ab24eba5a..79a7772852 100644 --- a/nimble/drivers/nrf52/src/ble_hw.c +++ b/nimble/drivers/nrf52/src/ble_hw.c @@ -69,6 +69,22 @@ ble_hw_get_public_addr(ble_addr_t *addr) uint32_t addr_high; uint32_t addr_low; +#if MYNEWT_VAL(BLE_PHY_UBLOX_BMD345_PUBLIC_ADDR) + /* + * The BMD-345 modules are preprogrammed from the factory with a unique public + * The Bluetooth device address stored in the CUSTOMER[0] and CUSTOMER[1] + * registers of the User Information Configuration Registers (UICR). + * The Bluetooth device address consists of the IEEE Organizationally Unique + * Identifier (OUI) combined with the hexadecimal digits that are printed on + * a 2D barcode and in human-readable text on the module label.The Bluetooth + * device address is stored in little endian format. The most significant + * bytes of the CUSTOMER[1] register are 0xFF to complete the 32-bit register. + */ + + /* Copy into device address. We can do this because we know platform */ + addr_low = NRF_UICR->CUSTOMER[0]; + addr_high = NRF_UICR->CUSTOMER[1]; +#else /* Does FICR have a public address */ if ((NRF_FICR->DEVICEADDRTYPE & 1) != 0) { return -1; @@ -77,6 +93,8 @@ ble_hw_get_public_addr(ble_addr_t *addr) /* Copy into device address. We can do this because we know platform */ addr_low = NRF_FICR->DEVICEADDR[0]; addr_high = NRF_FICR->DEVICEADDR[1]; +#endif + memcpy(addr->val, &addr_low, 4); memcpy(&addr->val[4], &addr_high, 2); addr->type = BLE_ADDR_PUBLIC; diff --git a/nimble/drivers/nrf52/syscfg.yml b/nimble/drivers/nrf52/syscfg.yml index bb6a2e1ba0..3bd49708ca 100644 --- a/nimble/drivers/nrf52/syscfg.yml +++ b/nimble/drivers/nrf52/syscfg.yml @@ -63,3 +63,10 @@ syscfg.defs: - nRF52840 Engineering C - nRF52840 Rev 1 (final silicon) value: 1 + + BLE_PHY_UBLOX_BMD345_PUBLIC_ADDR: + description: > + Ublox BMD-345 modules come with public address preprogrammed + in UICR register. If enabled public address will be read from + custom UICR instead of FICR register. + value: 0 From 567855623bacdf7f034f6a5bec2401a6bb271c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Fri, 14 Jan 2022 12:48:11 +0100 Subject: [PATCH 289/306] apps/btshell: fix build on 'native' bsp strl* methods are not always available, let's use snprintf() for string copy/concat actions in parse_dev_addr, as it allows us to keep buffer overflow control and NULL termination of string. --- apps/btshell/src/cmd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/btshell/src/cmd.c b/apps/btshell/src/cmd.c index a0452d22eb..6cb2713518 100644 --- a/apps/btshell/src/cmd.c +++ b/apps/btshell/src/cmd.c @@ -98,16 +98,19 @@ parse_dev_addr(const char *prefix, const struct kv_pair *addr_types, { char name[32]; int rc; + int written = 0; if (!prefix) { name[0] = '\0'; } else { - if (strlcpy(name, prefix, sizeof(name)) >= sizeof(name)) { + written = snprintf(name, sizeof(name) - 1, "%s", prefix); + if (written >= sizeof(name) || written < 0) { return EINVAL; } } - if (strlcat(name, "addr", sizeof(name)) >= sizeof(name)) { + written = snprintf(name + written, sizeof(name) - written - 1, "%s", "addr"); + if (written >= sizeof(name) || written < 0) { return EINVAL; } rc = parse_arg_addr(name, addr); @@ -116,7 +119,8 @@ parse_dev_addr(const char *prefix, const struct kv_pair *addr_types, return rc; } else if (rc == EAGAIN) { /* address found, but no type provided */ - if (strlcat(name, "_type", sizeof(name)) >= sizeof(name)) { + written = snprintf(name + written, sizeof(name) - written - 1, "%s", "_type"); + if (written >= sizeof(name) || written < 0) { return EINVAL; } addr->type = parse_arg_kv(name, addr_types, &rc); @@ -130,7 +134,8 @@ parse_dev_addr(const char *prefix, const struct kv_pair *addr_types, return rc; } else { /* full address found, but let's just make sure there is no type arg */ - if (strlcat(name, "_type", sizeof(name)) >= sizeof(name)) { + written = snprintf(name + written, sizeof(name) - written, "%s", "_type"); + if (written >= sizeof(name) || written < 0) { return EINVAL; } if (parse_arg_extract(name)) { From c33c87b1f3bef53e768c078d13c22d18fa89c475 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Thu, 17 Dec 2020 14:11:52 +0100 Subject: [PATCH 290/306] targets: Add blehci over USB for pca10056 --- targets/nordic_pca10056-blehci-usb/pkg.yml | 9 +++++++++ targets/nordic_pca10056-blehci-usb/syscfg.yml | 6 ++++++ targets/nordic_pca10056-blehci-usb/target.yml | 3 +++ 3 files changed, 18 insertions(+) create mode 100644 targets/nordic_pca10056-blehci-usb/pkg.yml create mode 100644 targets/nordic_pca10056-blehci-usb/syscfg.yml create mode 100644 targets/nordic_pca10056-blehci-usb/target.yml diff --git a/targets/nordic_pca10056-blehci-usb/pkg.yml b/targets/nordic_pca10056-blehci-usb/pkg.yml new file mode 100644 index 0000000000..772dd75ebe --- /dev/null +++ b/targets/nordic_pca10056-blehci-usb/pkg.yml @@ -0,0 +1,9 @@ +pkg.name: "targets/nordic_pca10056-blehci-usb" +pkg.type: target +pkg.description: +pkg.author: +pkg.homepage: + +pkg.deps: + - "@apache-mynewt-core/hw/usb/tinyusb" + - "@apache-mynewt-core/hw/usb/tinyusb/std_descriptors" diff --git a/targets/nordic_pca10056-blehci-usb/syscfg.yml b/targets/nordic_pca10056-blehci-usb/syscfg.yml new file mode 100644 index 0000000000..e664792eaa --- /dev/null +++ b/targets/nordic_pca10056-blehci-usb/syscfg.yml @@ -0,0 +1,6 @@ +syscfg.vals: + BLE_HCI_TRANSPORT: usb + USBD_BTH: 1 + + USBD_PID: 0xC01A + USBD_VID: 0xC0CA diff --git a/targets/nordic_pca10056-blehci-usb/target.yml b/targets/nordic_pca10056-blehci-usb/target.yml new file mode 100644 index 0000000000..39f4c8c447 --- /dev/null +++ b/targets/nordic_pca10056-blehci-usb/target.yml @@ -0,0 +1,3 @@ +target.app: "@apache-mynewt-nimble/apps/blehci" +target.bsp: "@apache-mynewt-core/hw/bsp/nordic_pca10056" +target.build_profile: debug From 75c1ef374941fae809801798f1dd92fd0383ab6b Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 17 Dec 2021 13:05:49 +0100 Subject: [PATCH 291/306] apps: remove use of deprecated BLE_PUBLIC_DEV_ADDR ble_hs_id_copy_addr() is used whenever deprecated value was used for getting public address. --- apps/blecsc/syscfg.yml | 2 +- apps/blehr/syscfg.yml | 2 +- apps/blestress/src/rx_stress.c | 3 ++- apps/bttester/src/gap.c | 17 ++--------------- nimble/host/mesh/src/shell.c | 5 ++--- targets/dialog_cmac/syscfg.yml | 2 +- 6 files changed, 9 insertions(+), 22 deletions(-) diff --git a/apps/blecsc/syscfg.yml b/apps/blecsc/syscfg.yml index ecf4b25f15..abf899691d 100644 --- a/apps/blecsc/syscfg.yml +++ b/apps/blecsc/syscfg.yml @@ -32,7 +32,7 @@ syscfg.vals: CONFIG_FCB: 1 # Set public device address. - BLE_PUBLIC_DEV_ADDR: ((uint8_t[6]){0xcc, 0xbb, 0xaa, 0x33, 0x22, 0x11}) + BLE_LL_PUBLIC_DEV_ADDR: 0x1122aabb33cc # Set device appearance to Cycling Speed and Cadence Sensor BLE_SVC_GAP_APPEARANCE: BLE_SVC_GAP_APPEARANCE_CYC_SPEED_AND_CADENCE_SENSOR diff --git a/apps/blehr/syscfg.yml b/apps/blehr/syscfg.yml index 5f047041e1..98cf255428 100644 --- a/apps/blehr/syscfg.yml +++ b/apps/blehr/syscfg.yml @@ -32,7 +32,7 @@ syscfg.vals: CONFIG_FCB: 1 # Set public device address. - BLE_PUBLIC_DEV_ADDR: ((uint8_t[6]){0xcc, 0xbb, 0xaa, 0x33, 0x22, 0x11}) + BLE_LL_PUBLIC_DEV_ADDR: 0x1122aabb33cc # Whether to save data to sys/config, or just keep it in RAM. BLE_STORE_CONFIG_PERSIST: 0 diff --git a/apps/blestress/src/rx_stress.c b/apps/blestress/src/rx_stress.c index 50415ea4e6..a9d9cda09a 100644 --- a/apps/blestress/src/rx_stress.c +++ b/apps/blestress/src/rx_stress.c @@ -155,7 +155,8 @@ rx_stress_simple_adv(struct rx_stress_adv_set *adv_set) assert (rc == 0); if (own_addr_type == 0) { - memcpy(addr.val, MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), 6); + rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr.val, NULL); + assert (rc == 0); } else { rc = ble_hs_id_gen_rnd(1, &addr); assert (rc == 0); diff --git a/apps/bttester/src/gap.c b/apps/bttester/src/gap.c index 63150e2877..75adeb9fc0 100644 --- a/apps/bttester/src/gap.c +++ b/apps/bttester/src/gap.c @@ -166,18 +166,6 @@ static void controller_index_list(uint8_t *data, uint16_t len) BTP_INDEX_NONE, (uint8_t *) rp, sizeof(buf)); } -static int check_pub_addr_unassigned(void) -{ -#ifdef ARCH_sim - return 0; -#else - uint8_t zero_addr[BLE_DEV_ADDR_LEN] = { 0 }; - - return memcmp(MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), - zero_addr, BLE_DEV_ADDR_LEN) == 0; -#endif -} - static void controller_info(uint8_t *data, uint16_t len) { struct gap_read_controller_info_rp rp; @@ -212,15 +200,14 @@ static void controller_info(uint8_t *data, uint16_t len) supported_settings |= BIT(GAP_SETTINGS_PRIVACY); memcpy(rp.address, addr.val, sizeof(rp.address)); } else { - if (check_pub_addr_unassigned()) { + rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, rp.address, NULL); + if (rc) { own_addr_type = BLE_OWN_ADDR_RANDOM; memcpy(rp.address, addr.val, sizeof(rp.address)); supported_settings |= BIT(GAP_SETTINGS_STATIC_ADDRESS); current_settings |= BIT(GAP_SETTINGS_STATIC_ADDRESS); } else { own_addr_type = BLE_OWN_ADDR_PUBLIC; - memcpy(rp.address, MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), - sizeof(rp.address)); } } diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index 95b1907f79..e905231081 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -707,10 +707,9 @@ static int check_pub_addr_unassigned(void) #ifdef ARCH_sim return 0; #else - uint8_t zero_addr[BLE_DEV_ADDR_LEN] = { 0 }; + uint8_t addr[BLE_DEV_ADDR_LEN]; - return memcmp(MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR), - zero_addr, BLE_DEV_ADDR_LEN) == 0; + return ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr, NULL) != 0; #endif } diff --git a/targets/dialog_cmac/syscfg.yml b/targets/dialog_cmac/syscfg.yml index b94427ac22..3a8895d7db 100644 --- a/targets/dialog_cmac/syscfg.yml +++ b/targets/dialog_cmac/syscfg.yml @@ -32,4 +32,4 @@ syscfg.vals: BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY: 150 # NOTE: set public address in target settings - # BLE_PUBLIC_DEV_ADDR: "(uint8_t[6]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff}" + # BLE_LL_PUBLIC_DEV_ADDR: 0xffffffffffff From c13d0b478ba93015e625838b33fbcb17b81e81f3 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Fri, 17 Dec 2021 13:39:07 +0100 Subject: [PATCH 292/306] apps: Remove controller direct dependency Direct dependency on controller is incorrect when controller runs on another core. --- apps/blecsc/pkg.yml | 1 - apps/blehr/pkg.yml | 1 - apps/blemesh/pkg.yml | 1 - apps/blemesh_light/pkg.yml | 1 - apps/blemesh_models_example_1/pkg.yml | 1 - apps/blemesh_models_example_2/pkg.yml | 1 - apps/blemesh_shell/pkg.yml | 1 - apps/blestress/pkg.yml | 1 - apps/bttester/pkg.yml | 1 - apps/ext_advertiser/pkg.yml | 1 - apps/mesh_badge/pkg.yml | 1 - 11 files changed, 11 deletions(-) diff --git a/apps/blecsc/pkg.yml b/apps/blecsc/pkg.yml index 828ff301ee..a2119c1b35 100644 --- a/apps/blecsc/pkg.yml +++ b/apps/blecsc/pkg.yml @@ -32,7 +32,6 @@ pkg.deps: - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/sys/sysinit" - "@apache-mynewt-core/sys/id" - - nimble/controller - nimble/host - nimble/host/services/gap - nimble/host/services/gatt diff --git a/apps/blehr/pkg.yml b/apps/blehr/pkg.yml index 395134faba..8212f8f6a2 100644 --- a/apps/blehr/pkg.yml +++ b/apps/blehr/pkg.yml @@ -32,7 +32,6 @@ pkg.deps: - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/sys/sysinit" - "@apache-mynewt-core/sys/id" - - nimble/controller - nimble/host - nimble/host/services/gap - nimble/host/services/gatt diff --git a/apps/blemesh/pkg.yml b/apps/blemesh/pkg.yml index 8a2af6874c..afe419b57b 100644 --- a/apps/blemesh/pkg.yml +++ b/apps/blemesh/pkg.yml @@ -29,7 +29,6 @@ pkg.deps: - "@apache-mynewt-core/sys/log/modlog" - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/sys/shell" - - nimble/controller - nimble/host - nimble/host/services/gap - nimble/host/services/gatt diff --git a/apps/blemesh_light/pkg.yml b/apps/blemesh_light/pkg.yml index bfc1ad233a..46b6d6c3d1 100644 --- a/apps/blemesh_light/pkg.yml +++ b/apps/blemesh_light/pkg.yml @@ -29,7 +29,6 @@ pkg.deps: - "@apache-mynewt-core/sys/log/modlog" - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/sys/shell" - - nimble/controller - nimble/host - nimble/host/services/gap - nimble/host/services/gatt diff --git a/apps/blemesh_models_example_1/pkg.yml b/apps/blemesh_models_example_1/pkg.yml index cd11834c5f..b8d77c4e47 100644 --- a/apps/blemesh_models_example_1/pkg.yml +++ b/apps/blemesh_models_example_1/pkg.yml @@ -27,7 +27,6 @@ pkg.deps: - "@apache-mynewt-core/sys/console/full" - "@apache-mynewt-core/sys/log/full" - "@apache-mynewt-core/sys/stats/full" - - nimble/controller - nimble/host - nimble/host/services/gap - nimble/host/services/gatt diff --git a/apps/blemesh_models_example_2/pkg.yml b/apps/blemesh_models_example_2/pkg.yml index 684d85bad8..020a9616da 100644 --- a/apps/blemesh_models_example_2/pkg.yml +++ b/apps/blemesh_models_example_2/pkg.yml @@ -29,7 +29,6 @@ pkg.deps: - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/encoding/base64" - "@apache-mynewt-core/sys/config" - - nimble/controller - nimble/host - nimble/host/services/gap - nimble/host/services/gatt diff --git a/apps/blemesh_shell/pkg.yml b/apps/blemesh_shell/pkg.yml index 2e7064cf90..f472fdf2aa 100644 --- a/apps/blemesh_shell/pkg.yml +++ b/apps/blemesh_shell/pkg.yml @@ -29,7 +29,6 @@ pkg.deps: - "@apache-mynewt-core/sys/log/modlog" - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/sys/shell" - - nimble/controller - nimble/host - nimble/host/services/gap - nimble/host/services/gatt diff --git a/apps/blestress/pkg.yml b/apps/blestress/pkg.yml index d4c52d247c..53f99ed944 100644 --- a/apps/blestress/pkg.yml +++ b/apps/blestress/pkg.yml @@ -30,7 +30,6 @@ pkg.deps: - "@apache-mynewt-core/sys/log/full" - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/sys/id" - - "@apache-mynewt-nimble/nimble/controller" - "@apache-mynewt-nimble/nimble/host" - "@apache-mynewt-nimble/nimble/host/util" - "@apache-mynewt-nimble/nimble/host/services/gap" diff --git a/apps/bttester/pkg.yml b/apps/bttester/pkg.yml index 39405aa051..270dc7e882 100644 --- a/apps/bttester/pkg.yml +++ b/apps/bttester/pkg.yml @@ -31,7 +31,6 @@ pkg.deps: - "@apache-mynewt-core/sys/log/modlog" - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/sys/shell" - - "@apache-mynewt-nimble/nimble/controller" - "@apache-mynewt-nimble/nimble/host" - "@apache-mynewt-nimble/nimble/host/util" - "@apache-mynewt-nimble/nimble/host/services/gap" diff --git a/apps/ext_advertiser/pkg.yml b/apps/ext_advertiser/pkg.yml index b9f9e54728..5a60b2270b 100644 --- a/apps/ext_advertiser/pkg.yml +++ b/apps/ext_advertiser/pkg.yml @@ -25,7 +25,6 @@ pkg.homepage: "http://mynewt.apache.org/" pkg.keywords: pkg.deps: - - nimble/controller - nimble/host - nimble/host/util - nimble/host/services/gap diff --git a/apps/mesh_badge/pkg.yml b/apps/mesh_badge/pkg.yml index 802b86bab4..96a42ba6a7 100644 --- a/apps/mesh_badge/pkg.yml +++ b/apps/mesh_badge/pkg.yml @@ -31,7 +31,6 @@ pkg.deps: - "@apache-mynewt-core/sys/log/modlog" - "@apache-mynewt-core/sys/stats/full" - "@apache-mynewt-core/sys/shell" - - nimble/controller - nimble/host - nimble/host/services/gap - nimble/host/services/gatt From 05538bc66db58c5fb676d1f62a9ad8f99ed6cb74 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 11 Jan 2022 15:35:35 +0100 Subject: [PATCH 293/306] nimble/ll: Add support for PA/LNA This adds some definitions for PA/LNA support. The actual support is implemented in phy and front-end driver. --- .../include/controller/ble_ll_plna.h | 45 +++++++++++++++++++ nimble/controller/pkg.yml | 4 ++ nimble/controller/src/ble_ll.c | 9 ++++ nimble/controller/syscfg.yml | 19 ++++++++ 4 files changed, 77 insertions(+) create mode 100644 nimble/controller/include/controller/ble_ll_plna.h diff --git a/nimble/controller/include/controller/ble_ll_plna.h b/nimble/controller/include/controller/ble_ll_plna.h new file mode 100644 index 0000000000..c4fb65ea98 --- /dev/null +++ b/nimble/controller/include/controller/ble_ll_plna.h @@ -0,0 +1,45 @@ +/* + * 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_PLNA_ +#define H_BLE_LL_PLNA_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "syscfg/syscfg.h" + +#if MYNEWT_VAL(BLE_LL_PA) +void ble_ll_plna_pa_init(void); +void ble_ll_plna_pa_enable(void); +void ble_ll_plna_pa_disable(void); +#endif + +#if MYNEWT_VAL(BLE_LL_LNA) +void ble_ll_plna_lna_init(void); +void ble_ll_plna_lna_enable(void); +void ble_ll_plna_lna_disable(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_PLNA_ */ diff --git a/nimble/controller/pkg.yml b/nimble/controller/pkg.yml index 96c636798b..9661bb31e8 100644 --- a/nimble/controller/pkg.yml +++ b/nimble/controller/pkg.yml @@ -29,6 +29,10 @@ pkg.req_apis: - ble_driver - ble_transport - stats +pkg.req_apis.BLE_LL_PA: + - ble_ll_pa +pkg.req_apis.BLE_LL_LNA: + - ble_ll_lna pkg.deps: - "@apache-mynewt-core/kernel/os" diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 99e8594640..f21f55ce07 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -44,6 +44,7 @@ #include "controller/ble_ll_rfmgmt.h" #include "controller/ble_ll_trace.h" #include "controller/ble_ll_sync.h" +#include "controller/ble_ll_plna.h" #include "ble_ll_conn_priv.h" #include "ble_ll_hci_priv.h" #include "ble_ll_priv.h" @@ -1656,6 +1657,14 @@ ble_ll_reset(void) ble_ll_resolv_list_reset(); #endif + +#if MYNEWT_VAL(BLE_LL_PA) + ble_ll_plna_pa_init(); +#endif +#if MYNEWT_VAL(BLE_LL_LNA) + ble_ll_plna_lna_init(); +#endif + /* Re-initialize the PHY */ rc = ble_phy_init(); diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index 62c9c4ad9d..41384cb5b4 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -375,6 +375,23 @@ syscfg.defs: line number where assertion occured. value: 0 + BLE_LL_PA: + description: Enable PA support + value: 0 + BLE_LL_PA_GPIO: + description: > + GPIO pin number to control PA. Pin is set to high state when PA + should be enabled. + value: -1 + BLE_LL_LNA: + description: Enable LNA support + value: 0 + BLE_LL_LNA_GPIO: + description: > + GPIO pin number to control LNA. Pin is set to high state when LNA + should be enabled. + value: -1 + BLE_LL_SYSINIT_STAGE: description: > Sysinit stage for the NimBLE controller. @@ -499,3 +516,5 @@ syscfg.vals.!BLE_HOST: syscfg.restrictions: - OS_CPUTIME_FREQ == 32768 - BLE_LL_PUBLIC_DEV_ADDR <= 0xffffffffffff + - BLE_LL_PA == 0 || BLE_LL_PA_GPIO >= 0 + - BLE_LL_LNA == 0 || BLE_LL_LNA_GPIO >= 0 From 9ef71450430ee0b2f3bfae902a2212fdadb8d375 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 11 Jan 2022 15:37:38 +0100 Subject: [PATCH 294/306] nimble/phy/nrf: Add support for PA/LNA on nRF52xxx This adds support for PA/LNA on nRF52 phy. PA/LNA is controlled using PPI CH6 (enable) and CH7 (disable). At the moment no separate timestamp is used to enable PA/LNA in advance, it's simply enabled just after ramp-up. This should be fine for front-end modules with short switch on time like SKY66112 (<800ns). --- nimble/drivers/nrf52/src/ble_phy.c | 144 ++++++++++++++++++++++++----- 1 file changed, 122 insertions(+), 22 deletions(-) diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c index 6aa898b327..3c7b62690b 100644 --- a/nimble/drivers/nrf52/src/ble_phy.c +++ b/nimble/drivers/nrf52/src/ble_phy.c @@ -29,6 +29,7 @@ #include "controller/ble_phy.h" #include "controller/ble_phy_trace.h" #include "controller/ble_ll.h" +#include "controller/ble_ll_plna.h" #include "nrfx.h" #if MYNEWT #include "mcu/nrf52_clock.h" @@ -49,9 +50,11 @@ * using PPI somewhere else. * * Pre-programmed channels: CH20, CH21, CH23, CH25, CH31 - * Regular channels: CH4, CH5 and optionally CH17, CH18, CH19 + * Regular channels: CH4, CH5 and optionally CH6, CH7, CH17, CH18, CH19 * - CH4 = cancel wfr timer on address match * - CH5 = disable radio on wfr timer expiry + * - CH6 = PA/LNA control (enable) + * - CH7 = PA/LNA control (disable) * - CH17 = (optional) gpio debug for radio ramp-up * - CH18 = (optional) gpio debug for wfr timer RX enabled * - CH19 = (optional) gpio debug for wfr timer radio disabled @@ -277,6 +280,27 @@ struct nrf_ccm_data struct nrf_ccm_data g_nrf_ccm_data; #endif +static int g_ble_phy_gpiote_idx; + +#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA) + +#define PLNA_SINGLE_GPIO \ + (!MYNEWT_VAL(BLE_LL_PA) || !MYNEWT_VAL(BLE_LL_LNA) || \ + (MYNEWT_VAL(BLE_LL_PA_GPIO) == MYNEWT_VAL(BLE_LL_LNA_GPIO))) + +#if PLNA_SINGLE_GPIO +static uint8_t plna_idx; +#else +#if MYNEWT_VAL(BLE_LL_PA) +static uint8_t plna_pa_idx; +#endif +#if MYNEWT_VAL(BLE_LL_LNA) +static uint8_t plna_lna_idx; +#endif +#endif + +#endif + static void ble_phy_apply_errata_102_106_107(void) { @@ -400,6 +424,36 @@ ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode) } #endif +static void +ble_phy_plna_enable_pa(void) +{ +#if MYNEWT_VAL(BLE_LL_PA) + ble_ll_plna_pa_enable(); + +#if !PLNA_SINGLE_GPIO + NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_pa_idx]); + NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_pa_idx]); +#endif + + NRF_PPI->CHENSET = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; +#endif +} + +static void +ble_phy_plna_enable_lna(void) +{ +#if MYNEWT_VAL(BLE_LL_LNA) + ble_ll_plna_lna_enable(); + +#if !PLNA_SINGLE_GPIO + NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_lna_idx]); + NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_lna_idx]); +#endif + + NRF_PPI->CHENSET = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; +#endif +} + int ble_phy_get_cur_phy(void) { @@ -925,6 +979,8 @@ ble_phy_tx_end_isr(void) NRF_TIMER0->CC[0] = rx_time; NRF_TIMER0->EVENTS_COMPARE[0] = 0; NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; + + ble_phy_plna_enable_lna(); } else { /* * XXX: not sure we need to stop the timer here all the time. Or that @@ -1053,6 +1109,8 @@ ble_phy_rx_end_isr(void) NRF_TIMER0->EVENTS_COMPARE[0] = 0; NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk; + ble_phy_plna_enable_pa(); + /* * XXX: Hack warning! * @@ -1255,6 +1313,10 @@ ble_phy_isr(void) switch (g_ble_phy_data.phy_state) { case BLE_PHY_STATE_RX: +#if MYNEWT_VAL(BLE_LL_LNA) + NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; + ble_ll_plna_lna_disable(); +#endif if (g_ble_phy_data.phy_rx_started) { ble_phy_rx_end_isr(); } else { @@ -1262,6 +1324,10 @@ ble_phy_isr(void) } break; case BLE_PHY_STATE_TX: +#if MYNEWT_VAL(BLE_LL_PA) + NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; + ble_ll_plna_pa_disable(); +#endif ble_phy_tx_end_isr(); break; default: @@ -1278,13 +1344,17 @@ ble_phy_isr(void) } #if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 -static inline void -ble_phy_dbg_time_setup_gpiote(int index, int pin) + MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ + MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 || \ + MYNEWT_VAL(BLE_LL_PA) || \ + MYNEWT_VAL(BLE_LL_LNA) +static int +ble_phy_gpiote_configure(int pin) { NRF_GPIO_Type *port; + g_ble_phy_gpiote_idx--; + #if NRF52840_XXAA port = pin > 31 ? NRF_P1 : NRF_P0; pin &= 0x1f; @@ -1296,7 +1366,7 @@ ble_phy_dbg_time_setup_gpiote(int index, int pin) port->DIRSET = (1 << pin); port->OUTCLR = (1 << pin); - NRF_GPIOTE->CONFIG[index] = + NRF_GPIOTE->CONFIG[g_ble_phy_gpiote_idx] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | ((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) | #if NRF52840_XXAA @@ -1304,13 +1374,17 @@ ble_phy_dbg_time_setup_gpiote(int index, int pin) #else 0; #endif + + BLE_LL_ASSERT(g_ble_phy_gpiote_idx >= 0); + + return g_ble_phy_gpiote_idx; } #endif static void ble_phy_dbg_time_setup(void) { - int gpiote_idx __attribute__((unused)) = 8; + int idx __attribute__((unused)); /* * We setup GPIOTE starting from last configuration index to minimize risk @@ -1319,44 +1393,41 @@ ble_phy_dbg_time_setup(void) */ #if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 - ble_phy_dbg_time_setup_gpiote(--gpiote_idx, - MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); + idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); NRF_PPI->CH[17].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); - NRF_PPI->CH[17].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); + NRF_PPI->CH[17].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]); NRF_PPI->CHENSET = PPI_CHEN_CH17_Msk; /* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */ - NRF_PPI->FORK[20].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); - NRF_PPI->FORK[21].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); + NRF_PPI->FORK[20].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]); + NRF_PPI->FORK[21].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]); #endif #if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 - ble_phy_dbg_time_setup_gpiote(--gpiote_idx, - MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); + idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); /* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */ - NRF_PPI->FORK[26].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); - NRF_PPI->FORK[27].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); + NRF_PPI->FORK[26].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]); + NRF_PPI->FORK[27].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]); #endif #if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 - ble_phy_dbg_time_setup_gpiote(--gpiote_idx, - MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); + idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); #if NRF52840_XXAA NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_RXREADY); #else NRF_PPI->CH[18].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); #endif - NRF_PPI->CH[18].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[gpiote_idx]); + NRF_PPI->CH[18].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx]); NRF_PPI->CH[19].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED); - NRF_PPI->CH[19].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); + NRF_PPI->CH[19].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]); NRF_PPI->CHENSET = PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk; /* CH[4] and CH[5] are always on for wfr */ - NRF_PPI->FORK[4].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); - NRF_PPI->FORK[5].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[gpiote_idx]); + NRF_PPI->FORK[4].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]); + NRF_PPI->FORK[5].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx]); #endif } @@ -1372,6 +1443,8 @@ ble_phy_init(void) { int rc; + g_ble_phy_gpiote_idx = 8; + /* Default phy to use is 1M */ g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M; g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M; @@ -1455,6 +1528,27 @@ ble_phy_init(void) NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]); NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE); +#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA) +#if PLNA_SINGLE_GPIO + plna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO)); + NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_idx]); + NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_idx]); +#else +#if MYNEWT_VAL(BLE_LL_PA) + plna_pa_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO)); + NRF_GPIOTE->TASKS_CLR[plna_pa_idx] = 1; +#endif +#if MYNEWT_VAL(BLE_LL_LNA) + plna_lna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_LNA_GPIO)); + NRF_GPIOTE->TASKS_CLR[plna_lna_idx] = 1; +#endif +#endif + + NRF_PPI->CH[6].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); + NRF_PPI->CH[7].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED); + NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; +#endif + /* Set isr in vector table and enable interrupt */ #ifndef RIOT_VERSION NVIC_SetPriority(RADIO_IRQn, 0); @@ -1617,7 +1711,10 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) /* Enable PPI to automatically start TXEN */ NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk; rc = 0; + + ble_phy_plna_enable_pa(); } + return rc; } @@ -1662,6 +1759,8 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) /* Enable PPI to automatically start RXEN */ NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk; + ble_phy_plna_enable_lna(); + /* Start rx */ rc = ble_phy_rx(); @@ -1959,6 +2058,7 @@ ble_phy_disable_irq_and_ppi(void) NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk; + NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; NVIC_ClearPendingIRQ(RADIO_IRQn); g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; } From 854f362c85a00d8759195c09103b18a9f0c7df5f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 11 Jan 2022 15:37:49 +0100 Subject: [PATCH 295/306] nimble/plna: Add driver for SKY66112 This adds support for SKY66112 front-end module (PA/LNA). CTX and CRX signals are controller by phy and shall be configured using LL syscfg settings for PA/LNA. Other signals can be configured via GPIO or simply driven externally to spare GPIO pins. It's possible to use PA or LNA only, in such case CPS signal has to be driven via GPIO. --- nimble/drivers/plna/sky66112/pkg.yml | 31 ++++++ nimble/drivers/plna/sky66112/src/sky66112.c | 117 ++++++++++++++++++++ nimble/drivers/plna/sky66112/syscfg.yml | 66 +++++++++++ 3 files changed, 214 insertions(+) create mode 100644 nimble/drivers/plna/sky66112/pkg.yml create mode 100644 nimble/drivers/plna/sky66112/src/sky66112.c create mode 100644 nimble/drivers/plna/sky66112/syscfg.yml diff --git a/nimble/drivers/plna/sky66112/pkg.yml b/nimble/drivers/plna/sky66112/pkg.yml new file mode 100644 index 0000000000..c3cb0fd322 --- /dev/null +++ b/nimble/drivers/plna/sky66112/pkg.yml @@ -0,0 +1,31 @@ +# +# 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. +# + +pkg.name: nimble/drivers/plna/sky66112 +pkg.description: Driver for SKY66112 front-end module +pkg.author: "Apache Mynewt " +pkg.homepage: "https://mynewt.apache.org/" +pkg.apis: + - ble_ll_pa + - ble_ll_lna +pkg.deps: + - nimble/controller + +pkg.init: + sky66112_init: 999 diff --git a/nimble/drivers/plna/sky66112/src/sky66112.c b/nimble/drivers/plna/sky66112/src/sky66112.c new file mode 100644 index 0000000000..09afe5f96e --- /dev/null +++ b/nimble/drivers/plna/sky66112/src/sky66112.c @@ -0,0 +1,117 @@ +/* + * 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 +#include "syscfg/syscfg.h" +#include "hal/hal_gpio.h" +#include "controller/ble_ll_plna.h" + +#define NO_BYPASS \ + ((MYNEWT_VAL(SKY66112_TX_BYPASS) >= 0) && \ + (MYNEWT_VAL(SKY66112_RX_BYPASS) >= 0)) + +static void +sky66112_bypass(uint8_t enabled) +{ + if (NO_BYPASS) { + return; + } + + hal_gpio_write(MYNEWT_VAL(SKY66112_PIN_CPS), enabled); +} + +void +ble_ll_plna_pa_init(void) +{ + /* Nothing to do here */ +} + +void +ble_ll_plna_pa_enable(void) +{ + if (!MYNEWT_VAL(SKY66112_TX_BYPASS)) { + sky66112_bypass(0); + } +} + +void +ble_ll_plna_pa_disable(void) +{ + if (!MYNEWT_VAL(SKY66112_TX_BYPASS)) { + sky66112_bypass(1); + } +} + +void +ble_ll_plna_lna_init(void) +{ + /* Nothing to do here */ +} + +void +ble_ll_plna_lna_enable(void) +{ + if (!MYNEWT_VAL(SKY66112_RX_BYPASS)) { + sky66112_bypass(0); + } +} + +void +ble_ll_plna_lna_disable(void) +{ + if (!MYNEWT_VAL(SKY66112_RX_BYPASS)) { + sky66112_bypass(1); + } +} + +void +sky66112_init(void) +{ + int pin; + + /* Use CRX and CTX to enable sleep mode */ + pin = MYNEWT_VAL(SKY66112_PIN_CSD); + if (pin >= 0) { + hal_gpio_init_out(pin, 1); + } + + pin = MYNEWT_VAL(SKY66112_PIN_CPS); + if (NO_BYPASS) { + /* Disable bypass */ + if (pin >= 0) { + hal_gpio_init_out(pin, 0); + } + } else { + /* Enable bypass, we'll disable it when needed */ + assert(pin >= 0); + hal_gpio_init_out(pin, 1); + } + + pin = MYNEWT_VAL(SKY66112_PIN_CHL); + if (pin >= 0) { + hal_gpio_init_out(pin, MYNEWT_VAL(SKY66112_TX_HP_MODE)); + } + + /* Select ANT1 */ + pin = MYNEWT_VAL(SKY66112_PIN_SEL); + if (pin >= 0) { + hal_gpio_init_out(pin, 0); + } +} diff --git a/nimble/drivers/plna/sky66112/syscfg.yml b/nimble/drivers/plna/sky66112/syscfg.yml new file mode 100644 index 0000000000..50434553a0 --- /dev/null +++ b/nimble/drivers/plna/sky66112/syscfg.yml @@ -0,0 +1,66 @@ +# 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. +# + +syscfg.defs: + SKY66112_PIN_CSD: + description: > + GPIO pin number to control CSD signal. + When set to '-1', pin state will not be changed and it should be + driven externally. + value: -1 + SKY66112_PIN_CPS: + description: > + GPIO pin number to control CPS signal. + When set to '-1', pin state will not be changed and it should be + driven externally. + value: -1 + SKY66112_PIN_CHL: + description: > + GPIO pin number to control CHL signal. + When set to '-1', pin state will not be changed and it should be + driven externally. + value: -1 + SKY66112_PIN_SEL: + description: > + GPIO pin number to control SEL signal. + When set to '-1', pin state will not be changed and it should be + driven externally. + value: -1 + SKY66112_TX_HP_MODE: + description: > + Enables high-power mode for TX. + Only valid if CHL signal is controller by driver. + value: 0 + SKY66112_TX_BYPASS: + description: > + Enables bypass for TX which effectively disables operation as PA. + Only valid if CPS signal is controller by driver. + value: 0 + SKY66112_RX_BYPASS: + description: > + Enables bypass for RX which effectively disables operation as PA. + Only valid if CPS signal is controller by driver. + value: 0 + +syscfg.vals.!BLE_LL_PA: + # Enable TX bypass by default if PA is disabled + SKY66112_TX_BYPASS: 1 + +syscfg.vals.!BLE_LL_LNA: + # Enable RX bypass by default if LNA is disabled + SKY66112_RX_BYPASS: 1 From 984e879f1781b0cd42ce6dc5ea4c60de3beb1776 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 14 Jan 2022 10:07:27 +0100 Subject: [PATCH 296/306] ll/nrf5340: Add support for PHY GPIO debug --- nimble/drivers/nrf5340/src/ble_phy.c | 153 +++++++++++++++++++++++++++ nimble/drivers/nrf5340/syscfg.yml | 39 +++++++ 2 files changed, 192 insertions(+) diff --git a/nimble/drivers/nrf5340/src/ble_phy.c b/nimble/drivers/nrf5340/src/ble_phy.c index e07bbaa11f..12be202db5 100644 --- a/nimble/drivers/nrf5340/src/ble_phy.c +++ b/nimble/drivers/nrf5340/src/ble_phy.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,8 @@ * DPPI somewhere else. * TODO maybe we could reduce number of used channels if we reuse same channel * for mutually exclusive events but for now make it simpler to debug. + * + * Optionally channels 6,7,8 are used for GPIO DBG. */ #define DPPI_CH_TIMER0_EVENTS_COMPARE_0 0 @@ -82,6 +85,39 @@ #define DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(_enable) ((DPPI_CH_RADIO_EVENTS_ADDRESS << CCM_SUBSCRIBE_CRYPT_CHIDX_Pos) | \ ((_enable) << CCM_SUBSCRIBE_CRYPT_EN_Pos)) +/* used for GPIO DBG */ +#define DPPI_CH_RADIO_EVENTS_READY 6 +#define DPPI_CH_RADIO_EVENTS_RXREADY 7 +#define DPPI_CH_RADIO_EVENTS_DISABLED 8 + +#define DPPI_CH_ENABLE_RADIO_EVENTS_READY DPPIC_CHEN_CH6_Msk +#define DPPI_CH_ENABLE_RADIO_EVENTS_RXREADY DPPIC_CHEN_CH7_Msk +#define DPPI_CH_ENABLE_RADIO_EVENTS_DISABLED DPPIC_CHEN_CH8_Msk + +#define DPPI_PUBLISH_RADIO_EVENTS_READY ((DPPI_CH_RADIO_EVENTS_READY << RADIO_PUBLISH_READY_CHIDX_Pos) | \ + (RADIO_PUBLISH_READY_EN_Enabled << RADIO_PUBLISH_READY_EN_Pos)) +#define DPPI_PUBLISH_RADIO_EVENTS_RXREADY ((DPPI_CH_RADIO_EVENTS_RXREADY << RADIO_PUBLISH_RXREADY_CHIDX_Pos) | \ + (RADIO_PUBLISH_RXREADY_EN_Enabled << RADIO_PUBLISH_RXREADY_EN_Pos)) +#define DPPI_PUBLISH_RADIO_EVENTS_DISABLED ((DPPI_CH_RADIO_EVENTS_DISABLED << RADIO_PUBLISH_DISABLED_CHIDX_Pos) | \ + (RADIO_PUBLISH_DISABLED_EN_Enabled << RADIO_PUBLISH_DISABLED_EN_Pos)) + +#define DPPI_SUBSCRIBE_GPIOTE_TASKS_SET_TXRXEN ((DPPI_CH_TIMER0_EVENTS_COMPARE_0 << GPIOTE_SUBSCRIBE_SET_CHIDX_Pos) | \ + (1 << GPIOTE_SUBSCRIBE_SET_EN_Pos)) +#define DPPI_SUBSCRIBE_GPIOTE_TASKS_SET_ADDRESS ((DPPI_CH_RADIO_EVENTS_ADDRESS << GPIOTE_SUBSCRIBE_SET_CHIDX_Pos) | \ + (1 << GPIOTE_SUBSCRIBE_SET_EN_Pos)) +#define DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_END ((DPPI_CH_RADIO_EVENTS_END << GPIOTE_SUBSCRIBE_CLR_CHIDX_Pos) | \ + (1 << GPIOTE_SUBSCRIBE_CLR_EN_Pos)) +#define DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_READY ((DPPI_CH_RADIO_EVENTS_READY << GPIOTE_SUBSCRIBE_CLR_CHIDX_Pos) | \ + (1 << GPIOTE_SUBSCRIBE_CLR_EN_Pos)) +#define DPPI_SUBSCRIBE_GPIOTE_TASKS_SET_RXREADY ((DPPI_CH_RADIO_EVENTS_RXREADY << GPIOTE_SUBSCRIBE_SET_CHIDX_Pos) | \ + (1 << GPIOTE_SUBSCRIBE_SET_EN_Pos)) +#define DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_DISABLED ((DPPI_CH_RADIO_EVENTS_DISABLED << GPIOTE_SUBSCRIBE_CLR_CHIDX_Pos) | \ + (1 << GPIOTE_SUBSCRIBE_CLR_EN_Pos)) +#define DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_CAPTURE3 ((DPPI_CH_TIMER0_EVENTS_COMPARE_3 << GPIOTE_SUBSCRIBE_CLR_CHIDX_Pos) | \ + (1 << GPIOTE_SUBSCRIBE_CLR_EN_Pos)) +#define DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_ADDRESS ((DPPI_CH_RADIO_EVENTS_ADDRESS << GPIOTE_SUBSCRIBE_CLR_CHIDX_Pos) | \ + (1 << GPIOTE_SUBSCRIBE_CLR_EN_Pos)) + extern uint8_t g_nrf_num_irks; extern uint32_t g_nrf_irk_list[]; @@ -1179,6 +1215,84 @@ ble_phy_isr(void) os_trace_isr_exit(); } +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \ + MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ + MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 +static inline void +ble_phy_dbg_time_setup_gpiote(int index, int pin) +{ + NRF_GPIO_Type *port; + + port = pin > 31 ? NRF_P1_NS : NRF_P0_NS; + pin &= 0x1f; + + /* Configure GPIO directly to avoid dependency to hal_gpio (for porting) */ + port->DIRSET = (1 << pin); + port->OUTCLR = (1 << pin); + + NRF_GPIOTE_NS->CONFIG[index] = + (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | + ((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) | + ((port == NRF_P1_NS) << GPIOTE_CONFIG_PORT_Pos); +} +#endif + +static void +ble_phy_dbg_time_setup(void) +{ + int gpiote_idx __attribute__((unused)) = 8; + + /* + * We setup GPIOTE starting from last configuration index to minimize risk + * of conflict with GPIO setup via hal. It's not great solution, but since + * this is just debugging code we can live with this. + */ + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 + ble_phy_dbg_time_setup_gpiote(--gpiote_idx, + MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); + + NRF_GPIOTE_NS->SUBSCRIBE_SET[gpiote_idx] = DPPI_SUBSCRIBE_GPIOTE_TASKS_SET_TXRXEN; + NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_READY; + + /* Publish RADIO->EVENTS_READY */ + NRF_RADIO_NS->PUBLISH_READY = DPPI_PUBLISH_RADIO_EVENTS_READY; + NRF_DPPIC_NS->CHENSET = DPPI_CH_ENABLE_RADIO_EVENTS_READY; + +#endif + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 + ble_phy_dbg_time_setup_gpiote(--gpiote_idx, + MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); + + NRF_GPIOTE_NS->SUBSCRIBE_SET[gpiote_idx] = DPPI_SUBSCRIBE_GPIOTE_TASKS_SET_ADDRESS; + NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_END; +#endif + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 + ble_phy_dbg_time_setup_gpiote(--gpiote_idx, + MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); + + NRF_GPIOTE_NS->SUBSCRIBE_SET[gpiote_idx] = DPPI_SUBSCRIBE_GPIOTE_TASKS_SET_RXREADY; + + /* TODO figure out how (if?) to subscribe task to multiple DPPI channels + * Currently only last one is working. Also using multiple GPIOTE for same + * PIN doesn't work... + */ + NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_DISABLED; + NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_ADDRESS; + NRF_GPIOTE_NS->SUBSCRIBE_CLR[gpiote_idx] = DPPI_SUBSCRIBE_GPIOTE_TASKS_CLR_CAPTURE3; + + /* Publish RADIO->EVENTS_RXREADY */ + NRF_RADIO_NS->PUBLISH_RXREADY = DPPI_PUBLISH_RADIO_EVENTS_RXREADY; + NRF_DPPIC_NS->CHENSET = DPPI_CH_ENABLE_RADIO_EVENTS_RXREADY; + + /* Publish RADIO->EVENTS_DISABLED */ + NRF_RADIO_NS->PUBLISH_DISABLED = DPPI_CH_ENABLE_RADIO_EVENTS_DISABLED; + NRF_DPPIC_NS->CHENSET = DPPI_CH_ENABLE_RADIO_EVENTS_DISABLED; +#endif +} + int ble_phy_init(void) { @@ -1296,6 +1410,8 @@ ble_phy_init(void) g_ble_phy_data.phy_stats_initialized = 1; } + ble_phy_dbg_time_setup(); + return 0; } @@ -1725,6 +1841,41 @@ ble_phy_restart_rx(void) ble_phy_rx(); } +static void +ble_phy_dbg_clear_pins(void) +{ +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \ + MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ + MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 + NRF_GPIO_Type *port; + int pin; + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 + pin = MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN); + port = pin > 31 ? NRF_P1_NS : NRF_P0_NS; + pin &= 0x1f; + + port->OUTCLR = (1 << pin); +#endif + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 + pin = MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN); + port = pin > 31 ? NRF_P1_NS : NRF_P0_NS; + pin &= 0x1f; + + port->OUTCLR = (1 << pin); +#endif + +#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 + pin = MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN); + port = pin > 31 ? NRF_P1_NS : NRF_P0_NS; + pin &= 0x1f; + + port->OUTCLR = (1 << pin); +#endif +#endif +} + void ble_phy_disable(void) { @@ -1732,6 +1883,8 @@ ble_phy_disable(void) ble_phy_stop_usec_timer(); ble_phy_disable_irq_and_ppi(); + + ble_phy_dbg_clear_pins(); } uint32_t diff --git a/nimble/drivers/nrf5340/syscfg.yml b/nimble/drivers/nrf5340/syscfg.yml index dd8b93047c..ed82f6d604 100644 --- a/nimble/drivers/nrf5340/syscfg.yml +++ b/nimble/drivers/nrf5340/syscfg.yml @@ -21,3 +21,42 @@ syscfg.defs: description: > Enable SystemView tracing module for radio driver. value: 0 + + BLE_PHY_DBG_TIME_TXRXEN_READY_PIN: + description: > + When set to proper GPIO pin number, this pin will be set + to high state when radio is enabled (TASKS_TXEN or TASKS_RXEN) + and back to low state on radio EVENTS_READY. + This can be used to measure radio ram-up time. + + Note: + GPIO control for selected pin needs to be assigned to Network + Core, configure IPC_NRF5340_NET_GPIO in ipc_nrf5340 driver on + Application Core. + value: -1 + + BLE_PHY_DBG_TIME_ADDRESS_END_PIN: + description: > + When set to proper GPIO pin number, this pin will be set + to high state on radio EVENTS_ADDRESS and back to low state + on radio EVENTS_END. + This can be used to measure radio pipeline delays. + + Note: + GPIO control for selected pin needs to be assigned to Network + Core, configure IPC_NRF5340_NET_GPIO in ipc_nrf5340 driver on + Application Core. + value: -1 + + BLE_PHY_DBG_TIME_WFR_PIN: + description: > + When set to proper GPIO pin number, this pin will be set + to high state on radio EVENTS_RXREADY and back to low + state when wfr timer expires. + This can be used to check if wfr is calculated properly. + + Note: + GPIO control for selected pin needs to be assigned to Network + Core, configure IPC_NRF5340_NET_GPIO in ipc_nrf5340 driver on + Application Core. + value: -1 From ff51d481cc1e2f16f124ce545a7510e42fb1b033 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 28 Dec 2021 15:12:42 +0100 Subject: [PATCH 297/306] nimble/ll: Add VS command for setting transmit power This command allows to override TX power configured with BLE_LL_TX_PWR_DBM syscfg value. If 0xff is provided BLE_LL_TX_PWR_DBM TX power is restored. --- nimble/controller/src/ble_ll.c | 4 +- nimble/controller/src/ble_ll_adv.c | 9 +-- nimble/controller/src/ble_ll_hci_vs.c | 85 +++++++++++++++++++++++++++ nimble/controller/src/ble_ll_priv.h | 2 + nimble/controller/syscfg.yml | 4 +- nimble/include/nimble/hci_common.h | 14 ++++- 6 files changed, 111 insertions(+), 7 deletions(-) diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index f21f55ce07..1e378bc61b 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -65,6 +65,8 @@ * right thing to do. */ +int8_t g_ble_ll_tx_power = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); + /* Supported states */ #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #define BLE_LL_S_NCA ((uint64_t)1 << 0) @@ -1391,7 +1393,7 @@ ble_ll_task(void *arg) ble_phy_init(); /* Set output power to 1mW (0 dBm) */ - ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); + ble_phy_txpwr_set(g_ble_ll_tx_power); /* Register callback for transport */ ble_hci_trans_cfg_ll(ble_ll_hci_cmd_rx, NULL, ble_ll_hci_acl_rx, NULL); diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c index 8a6cd1fe56..db17dc4c22 100644 --- a/nimble/controller/src/ble_ll_adv.c +++ b/nimble/controller/src/ble_ll_adv.c @@ -41,6 +41,7 @@ #include "controller/ble_ll_utils.h" #include "controller/ble_ll_rfmgmt.h" #include "ble_ll_conn_priv.h" +#include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) @@ -1023,7 +1024,7 @@ ble_ll_adv_tx_done(void *arg) struct ble_ll_adv_sm *advsm; /* reset power to max after advertising */ - ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); + ble_phy_txpwr_set(g_ble_ll_tx_power); advsm = (struct ble_ll_adv_sm *)arg; @@ -1687,7 +1688,7 @@ ble_ll_adv_halt(void) ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, advsm->adv_instance); - ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); + ble_phy_txpwr_set(g_ble_ll_tx_power); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING) { @@ -2112,8 +2113,8 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) static void ble_ll_adv_sync_tx_done(struct ble_ll_adv_sm *advsm) { - /* reset power to max after advertising */ - ble_phy_txpwr_set(MYNEWT_VAL(BLE_LL_TX_PWR_DBM)); + /* reset power to default after advertising */ + ble_phy_txpwr_set(g_ble_ll_tx_power); /* for sync we trace a no pri nor sec set */ ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance, 0); diff --git a/nimble/controller/src/ble_ll_hci_vs.c b/nimble/controller/src/ble_ll_hci_vs.c index 8903525ec9..f2057ea428 100644 --- a/nimble/controller/src/ble_ll_hci_vs.c +++ b/nimble/controller/src/ble_ll_hci_vs.c @@ -21,7 +21,12 @@ #include "syscfg/syscfg.h" #include "controller/ble_ll.h" #include "controller/ble_ll_hci.h" +#include "controller/ble_ll_sync.h" +#include "controller/ble_ll_adv.h" +#include "controller/ble_ll_scan.h" #include "controller/ble_hw.h" +#include "ble_ll_conn_priv.h" +#include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_HCI_VS) @@ -51,9 +56,89 @@ ble_ll_hci_vs_rd_static_addr(uint16_t ocf, return BLE_ERR_SUCCESS; } +/* disallow changing TX power if there is any radio activity + * note: we could allow to change it if there is no TX activity (eg only + * passive scan or sync) but lets just keep this simple for now + */ +static int +ble_ll_hci_vs_is_controller_busy(void) +{ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + struct ble_ll_conn_sm *cur; + int i = 0; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + if (ble_ll_sync_enabled()) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + if (ble_ll_adv_enabled()) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + if (ble_ll_scan_enabled()) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + if (g_ble_ll_conn_create_sm.connsm) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + STAILQ_FOREACH(cur, &g_ble_ll_conn_free_list, free_stqe) { + i++; + } + + /* check if all connection objects are free */ + if (i < MYNEWT_VAL(BLE_MAX_CONNECTIONS)) { + return 1; + } +#endif + + return 0; +} + +static int +ble_ll_hci_vs_set_tx_power(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_vs_set_tx_pwr_cp *cmd = (const void *) cmdbuf; + struct ble_hci_vs_set_tx_pwr_rp *rsp = (void *) rspbuf; + + if (cmdlen != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (ble_ll_hci_vs_is_controller_busy()) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (cmd->tx_power == 127) { + /* restore reset default */ + g_ble_ll_tx_power = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); + } else { + g_ble_ll_tx_power = ble_phy_txpower_round(cmd->tx_power); + } + + rsp->tx_power = g_ble_ll_tx_power; + *rsplen = sizeof(*rsp); + + return BLE_ERR_SUCCESS; +} + static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_RD_STATIC_ADDR, ble_ll_hci_vs_rd_static_addr), + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_TX_PWR, + ble_ll_hci_vs_set_tx_power), }; static struct ble_ll_hci_vs_cmd * diff --git a/nimble/controller/src/ble_ll_priv.h b/nimble/controller/src/ble_ll_priv.h index 900950ef64..ca8e082958 100644 --- a/nimble/controller/src/ble_ll_priv.h +++ b/nimble/controller/src/ble_ll_priv.h @@ -24,6 +24,8 @@ extern "C" { #endif +extern int8_t g_ble_ll_tx_power; + #ifdef MYNEWT #include "syscfg/syscfg.h" diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index 41384cb5b4..afb3859708 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -68,7 +68,9 @@ syscfg.defs: range: 0..500 BLE_LL_TX_PWR_DBM: - description: 'Transmit power level.' + description: > + Default Transmit power level (in dBm). Actual transmit power + may be rounded up or down depending on used radio. value: '0' BLE_LL_NUM_COMP_PKT_ITVL_MS: diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 4851fd06da..e4830833b3 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -1062,11 +1062,23 @@ struct ble_hci_le_set_host_feat_cp { } __attribute__((packed)); /* --- Vendor specific commands (OGF 0x003F) */ -#define BLE_HCI_OCF_VS_RD_STATIC_ADDR (0x0001) +/* Read Random Static Address */ +#define BLE_HCI_OCF_VS_RD_STATIC_ADDR (0x0001) struct ble_hci_vs_rd_static_addr_rp { uint8_t addr[6]; } __attribute__((packed)); +/* Set default transmit power. Actual selected TX power is returned + * in reply. Setting 0xff restores controller reset default. + */ +#define BLE_HCI_OCF_VS_SET_TX_PWR (0x0002) +struct ble_hci_vs_set_tx_pwr_cp { + int8_t tx_power; +} __attribute__((packed)); +struct ble_hci_vs_set_tx_pwr_rp { + int8_t tx_power; +} __attribute__((packed)); + /* Command Specific Definitions */ /* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */ #define BLE_HCI_CTLR_TO_HOST_FC_OFF (0) From 35a560341c294c0d626a7d5fcd17126f9e2e1b17 Mon Sep 17 00:00:00 2001 From: Yeming Li <625466940@qq.com> Date: Fri, 31 Dec 2021 15:40:18 +0800 Subject: [PATCH 298/306] nimble/ll: Adjust start time of the first anchor point of connection Set the start_time of the first anchor point of new connection to entry->end_time+1. For the 32768 Hz crystal in nrf chip, 1 tick is 30.517us. The connection state machine use anchor point to store the cpu ticks and anchor_point_usec to store the remainder. Therefore, to compensate the inaccuracy of the crystal, the ticks of anchor_point will be add with 1 once the value of anchor_point_usec exceed 31. If two connections have same connection interval, the time difference between the two start of schedule item will decreased 1, which lead to an overlap. To prevent this from happenning, we set the start_time of sch to 1 cpu tick after the end_time of entry. --- nimble/controller/src/ble_ll_sched.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c index fe47dbc620..cd60014d67 100644 --- a/nimble/controller/src/ble_ll_sched.c +++ b/nimble/controller/src/ble_ll_sched.c @@ -237,7 +237,19 @@ ble_ll_sched_insert(struct ble_ll_sched_item *sch, uint32_t max_delay, } } else { preempt_first = NULL; - sch->start_time = entry->end_time; + /* + * For the 32768 Hz crystal in nrf chip, 1 tick is 30.517us. + * The connection state machine use anchor point to store the + * cpu ticks and anchor_point_usec to store the remainder. + * Therefore, to compensate the inaccuracy of the crystal, the + * ticks of anchor_point will be add with 1 once the value of + * anchor_point_usec exceed 31. If two connections have same + * connection interval, the time difference between the two + * start of schedule item will decreased 1, which lead to + * an overlap. To prevent this from happenning, we set the + * start_time of sch to 1 cpu tick after the end_time of entry. + */ + sch->start_time = entry->end_time + 1; if ((max_delay == 0) || CPUTIME_GEQ(sch->start_time, max_start_time)) { From 63edf82b826be155e866f948b21205ce20fd1c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 2 Dec 2021 10:36:26 +0100 Subject: [PATCH 299/306] host/mesh: make bt_le_adv_start match Zephyr API During sync `duration` argument was introduced, which is not intended to be in `bt_le_adv_start` - duration of advertising is managed by events in bt_mesh_adv_queue. --- nimble/host/mesh/include/mesh/glue.h | 1 - nimble/host/mesh/src/adv_legacy.c | 5 ++--- nimble/host/mesh/src/glue.c | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 44631f3e57..58e3e2d8de 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -418,7 +418,6 @@ int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_ uint8_t *plaintext, size_t mic_size); void bt_mesh_register_gatt(void); int bt_le_adv_start(const struct ble_gap_adv_params *param, - int64_t duration, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len); diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 5bebff8960..32ebeb60d9 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -107,8 +107,7 @@ static inline void adv_send(struct os_mbuf *buf) int64_t time = k_uptime_get(); - err = bt_le_adv_start(¶m, duration, &ad, 1, NULL, 0); - + err = bt_le_adv_start(¶m, &ad, 1, NULL, 0); bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf)); if (err) { @@ -240,6 +239,6 @@ int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, const struct bt_data *sd, size_t sd_len) { adv_timeout = duration; - return bt_le_adv_start(param, duration, ad, ad_len, sd, sd_len); + return bt_le_adv_start(param, ad, ad_len, sd, sd_len); } #endif diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index 7a811210f3..c00af9477e 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -712,7 +712,6 @@ ble_adv_conf_adv_instance(const struct ble_gap_adv_params *param, int *instance) int bt_le_adv_start(const struct ble_gap_adv_params *param, - int64_t duration, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) { @@ -778,7 +777,7 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, } /*TODO: We could use duration and max events in the future */ - err = ble_gap_ext_adv_start(instance, duration, 0); + err = ble_gap_ext_adv_start(instance, 0, 0); return err; error: @@ -792,7 +791,6 @@ bt_le_adv_start(const struct ble_gap_adv_params *param, int bt_le_adv_start(const struct ble_gap_adv_params *param, - int64_t duration, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len) { From 43a74391e0407df5d37472d5697adec54759a438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Thu, 2 Dec 2021 10:38:45 +0100 Subject: [PATCH 300/306] host/mesh: fix handling of bt_mesh_adv_queue in mesh_adv_thread `ble_npl_eventq_get` is waiting for events for duration in tick units, not ms. This means that we're waiting OS_TICKS_PER_SEC times to long and catch events that are meant to be missed. --- nimble/host/mesh/src/adv_legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/host/mesh/src/adv_legacy.c b/nimble/host/mesh/src/adv_legacy.c index 32ebeb60d9..e495dd614c 100644 --- a/nimble/host/mesh/src/adv_legacy.c +++ b/nimble/host/mesh/src/adv_legacy.c @@ -154,7 +154,7 @@ mesh_adv_thread(void *args) BT_DBG("PB-GATT Advertising up to %d ms", (int) adv_timeout); } - ev = ble_npl_eventq_get(&bt_mesh_adv_queue, adv_timeout); + ev = ble_npl_eventq_get(&bt_mesh_adv_queue, ble_npl_time_ms_to_ticks32(adv_timeout)); bt_le_adv_stop(); } } else { From 30370ffb57ac10e39b0124b6d5a103f260c1f0a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kopy=C5=9Bci=C5=84ski?= Date: Tue, 18 Jan 2022 15:08:33 +0100 Subject: [PATCH 301/306] host/ble_gattc: Cancel prepered writes if data doesn't match in response If data received in ble_gattc_write_long_rx_prep() doesn't match data sent in prepare write request we need not only return error in function, but also send ATT_Execute_Write_Response with flag set to BLE_ATT_EXEC_WRITE_F_CANCEL. This is affecting GATT/CL/GAW/BI-32-C --- nimble/host/src/ble_gattc.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c index 74a2837ad7..b43a0af03c 100644 --- a/nimble/host/src/ble_gattc.c +++ b/nimble/host/src/ble_gattc.c @@ -3765,17 +3765,20 @@ ble_gattc_write_long_rx_prep(struct ble_gattc_proc *proc, proc->write_long.length) != 0) { rc = BLE_HS_EBADDATA; - goto err; - } - /* Send follow-up request. */ - proc->write_long.attr.offset += OS_MBUF_PKTLEN(om); - rc = ble_gattc_write_long_resume(proc); - if (rc != 0) { + /* if data doesn't match up send cancel write */ + ble_att_clt_tx_exec_write(proc->conn_handle, BLE_ATT_EXEC_WRITE_F_CANCEL); goto err; - } + } else { + /* Send follow-up request. */ + proc->write_long.attr.offset += OS_MBUF_PKTLEN(om); + rc = ble_gattc_write_long_resume(proc); + if (rc != 0) { + goto err; + } - return 0; + return 0; + } err: /* XXX: Might need to cancel pending writes. */ From 403ae02652075f89b71e19736b78834c7fcc1ebe Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 22 Nov 2021 09:50:16 +0100 Subject: [PATCH 302/306] transport: Add bridge transport blehci application is for controller only build with external interface. In case of dual-core MCUs (NRF5340, DA1469x) controller runs on second core that may not be able to operate on external interface. To be able to run blehci like application on dual-core systems, application side has to route traffic from external interface transport to internal transport. So far only one transport package was used, for bridge configuration application must include two transport packages. To facilitate this: - transport package has BLE_HCI_BRIDGE that is set to 1 for dual-core bridge configuration - common syscfg values defined for in all transports are moved to transport package (BLE_HCI_EVT_HI_BUF_COUNT..) - syscfg definitions present in all transport packages are converted to syscfg values - DA1469x and NRF5340 transports in bridge configuration will NOT create buffers for commands and events they relay on external transport provided buffers --- nimble/transport/da1469x/syscfg.yml | 30 +++--------- .../cmac_driver/diag/src/cmac_diag.c | 2 +- .../include/cmac_driver/cmac_shared.h | 4 +- .../transport/dialog_cmac/cmac_driver/pkg.yml | 3 ++ .../dialog_cmac/cmac_driver/src/cmac_mbox.c | 4 +- .../dialog_cmac/cmac_driver/src/cmac_rand.c | 2 +- .../dialog_cmac/cmac_driver/src/cmac_shared.c | 6 +-- .../dialog_cmac/src/ble_hci_cmac_common.c | 8 ++++ .../dialog_cmac/src/ble_hci_cmac_hs.c | 2 +- .../dialog_cmac/src/ble_hci_trans_h4.c | 10 ++-- nimble/transport/dialog_cmac/syscfg.yml | 30 +++--------- nimble/transport/emspi/syscfg.yml | 31 ++++-------- .../transport/nrf5340/src/nrf5340_ble_hci.c | 23 ++++++--- nimble/transport/nrf5340/syscfg.yml | 33 ++++--------- nimble/transport/pkg.yml | 6 +++ nimble/transport/ram/syscfg.yml | 29 +++-------- nimble/transport/socket/syscfg.yml | 27 ++++------- nimble/transport/syscfg.yml | 48 +++++++++++++++++++ nimble/transport/uart/src/ble_hci_uart.c | 16 ++++--- nimble/transport/uart/syscfg.yml | 25 +++------- nimble/transport/usb/syscfg.yml | 25 +++------- 21 files changed, 167 insertions(+), 197 deletions(-) diff --git a/nimble/transport/da1469x/syscfg.yml b/nimble/transport/da1469x/syscfg.yml index 4ea9da9b36..2ce8cd3cf2 100644 --- a/nimble/transport/da1469x/syscfg.yml +++ b/nimble/transport/da1469x/syscfg.yml @@ -16,28 +16,12 @@ # under the License. # -syscfg.defs: - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'Number of high-priority event buffers.' - value: 2 +syscfg.vals.'!BLE_HCI_BRIDGE && !BLE_EXT_ADV': + BLE_HCI_EVT_HI_BUF_COUNT: 2 + BLE_HCI_EVT_LO_BUF_COUNT: 8 + BLE_HCI_EVT_BUF_SIZE: 70 + BLE_ACL_BUF_COUNT: 4 + BLE_ACL_BUF_SIZE: 255 - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'Number of low-priority event buffers.' - value: 8 - - BLE_HCI_EVT_BUF_SIZE: - description: 'Size of each event buffer, in bytes.' - value: 70 - - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 4 - - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 255 - -syscfg.vals.BLE_EXT_ADV: +syscfg.vals.'!BLE_HCI_BRIDGE && BLE_EXT_ADV': BLE_HCI_EVT_BUF_SIZE: 274 diff --git a/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c b/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c index 4f75470654..0a4e27e6d5 100644 --- a/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c +++ b/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c @@ -20,7 +20,7 @@ #include "syscfg/syscfg.h" #include "mcu/mcu.h" -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) void cmac_diag_setup_host(void) { diff --git a/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h b/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h index 90b5827dd4..4e37bb8b82 100644 --- a/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h +++ b/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h @@ -131,7 +131,7 @@ struct cmac_shared_data { uint8_t mbox_c2s_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_C2S) ]; }; -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) extern volatile struct cmac_shared_data *g_cmac_shared_data; #elif MYNEWT_VAL(BLE_CONTROLLER) extern volatile struct cmac_shared_data g_cmac_shared_data; @@ -161,7 +161,7 @@ void cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb); void cmac_shared_init(void); void cmac_shared_sync(void); -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) #define CMAC_SHARED_LOCK_VAL 0x40000000 #elif MYNEWT_VAL(BLE_CONTROLLER) #define CMAC_SHARED_LOCK_VAL 0xc0000000 diff --git a/nimble/transport/dialog_cmac/cmac_driver/pkg.yml b/nimble/transport/dialog_cmac/cmac_driver/pkg.yml index 5b4a212914..00200b65a7 100644 --- a/nimble/transport/dialog_cmac/cmac_driver/pkg.yml +++ b/nimble/transport/dialog_cmac/cmac_driver/pkg.yml @@ -37,3 +37,6 @@ pkg.post_link_cmds.BLE_CONTROLLER: pkg.pre_link_cmds.BLE_HOST: scripts/build_libcmac.sh: 100 + +pkg.pre_link_cmds.BLE_HCI_BRIDGE: + scripts/build_libcmac.sh: 100 diff --git a/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c b/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c index 9594dbe900..88764c4dfc 100644 --- a/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c +++ b/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c @@ -49,7 +49,7 @@ cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb) int cmac_mbox_read(void) { -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_c2s; uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_c2s_buf; const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S); @@ -96,7 +96,7 @@ cmac_mbox_read(void) int cmac_mbox_write(const void *data, uint16_t len) { -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_s2c; uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_s2c_buf; const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C); diff --git a/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c b/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c index 67a315f96e..10810972ca 100644 --- a/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c +++ b/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c @@ -26,7 +26,7 @@ #include "os/os_arch.h" #include "os/os.h" -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) int cmac_rand_is_active(void) { diff --git a/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c b/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c index 24640ca475..a4f2e37f56 100644 --- a/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c +++ b/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c @@ -34,7 +34,7 @@ #define min(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #endif -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) volatile struct cmac_shared_data *g_cmac_shared_data; #include "mcu/da1469x_clock.h" #define MCU_DIAG_SER(_x) @@ -45,7 +45,7 @@ volatile struct cmac_shared_data g_cmac_shared_data __attribute__((section(" void cmac_shared_init(void) { -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) g_cmac_shared_data = (void *)(MCU_MEM_SYSRAM_START_ADDRESS + MEMCTRL->CMI_SHARED_BASE_REG); @@ -77,7 +77,7 @@ cmac_shared_sync(void) * to wait until CMAC finished initialization as otherwise host may start * sending HCI packets which will timeout as there is no one to read them. */ -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) assert(g_cmac_shared_data->magic_sys == 0); while (g_cmac_shared_data->magic_cmac != CMAC_SHARED_MAGIC_CMAC); diff --git a/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c b/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c index 665b62166b..5a41ee6313 100644 --- a/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c +++ b/nimble/transport/dialog_cmac/src/ble_hci_cmac_common.c @@ -41,6 +41,7 @@ BLE_MBUF_MEMBLOCK_OVERHEAD + \ BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT) +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) static uint8_t ble_hci_pool_cmd_mempool_buf[ OS_MEMPOOL_BYTES(HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ)]; static struct os_mempool ble_hci_pool_cmd_mempool; @@ -54,6 +55,7 @@ static uint8_t ble_hci_pool_evt_lo_mempool_buf[ OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))]; static struct os_mempool ble_hci_pool_evt_lo_mempool; +#endif static uint8_t ble_hci_pool_acl_mempool_buf[ OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_ACL_BUF_COUNT), @@ -66,6 +68,7 @@ __attribute__((weak)) void ble_hci_trans_notify_free(void); static os_mempool_put_fn *g_ble_hci_pool_acl_mempool_put_cb; static void *g_ble_hci_pool_acl_mempool_put_arg; +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) int ble_hci_trans_reset(void) { @@ -117,6 +120,7 @@ ble_hci_trans_buf_free(uint8_t *buf) ble_hci_trans_notify_free(); } +#endif struct os_mbuf * ble_hci_cmac_alloc_acl_mbuf(void) @@ -147,6 +151,7 @@ ble_hci_cmac_free_acl_cb(struct os_mempool_ext *mpe, void *data, void *arg) } +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg) { @@ -155,6 +160,7 @@ ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg) return 0; } +#endif void ble_hci_cmac_init(void) @@ -163,6 +169,7 @@ ble_hci_cmac_init(void) SYSINIT_ASSERT_ACTIVE(); +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) rc = os_mempool_init(&ble_hci_pool_cmd_mempool, HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ, ble_hci_pool_cmd_mempool_buf, "ble_hci_cmd"); @@ -179,6 +186,7 @@ ble_hci_cmac_init(void) MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE), ble_hci_pool_evt_lo_mempool_buf, "ble_hci_evt_lo"); SYSINIT_PANIC_ASSERT(rc == 0); +#endif rc = os_mempool_ext_init(&ble_hci_pool_acl_mempool, MYNEWT_VAL(BLE_ACL_BUF_COUNT), POOL_ACL_BLOCK_SIZE, diff --git a/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c b/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c index 1164fe7186..172fc87952 100644 --- a/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c +++ b/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c @@ -21,7 +21,7 @@ #include #include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) #include "cmac_driver/cmac_shared.h" #include "cmac_driver/cmac_host.h" diff --git a/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c b/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c index 74da391239..628ae75d96 100644 --- a/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c +++ b/nimble/transport/dialog_cmac/src/ble_hci_trans_h4.c @@ -64,7 +64,7 @@ ble_hci_trans_h4_rxs_start(struct ble_hci_trans_h4_rx_state *rxs, uint8_t pkt_ty case BLE_HCI_TRANS_H4_PKT_TYPE_ACL: rxs->min_len = 4; break; -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) case BLE_HCI_TRANS_H4_PKT_TYPE_EVT: rxs->min_len = 2; break; @@ -95,7 +95,7 @@ static int ble_hci_trans_h4_rx_state_w4_header(struct ble_hci_trans_h4_rx_state *rxs, struct input_buffer *ib) { -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) int pool; #endif int rc; @@ -127,7 +127,7 @@ ble_hci_trans_h4_rx_state_w4_header(struct ble_hci_trans_h4_rx_state *rxs, os_mbuf_append(rxs->om, rxs->hdr, rxs->len); rxs->expected_len = get_le16(&rxs->hdr[2]) + 4; break; -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) case BLE_HCI_TRANS_H4_PKT_TYPE_EVT: pool = BLE_HCI_TRANS_BUF_EVT_HI; if (rxs->hdr[0] == BLE_HCI_EVCODE_LE_META) { @@ -194,7 +194,7 @@ ble_hci_trans_h4_rx_state_w4_payload(struct ble_hci_trans_h4_rx_state *rxs, #if MYNEWT_VAL(BLE_CONTROLLER) case BLE_HCI_TRANS_H4_PKT_TYPE_CMD: #endif -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) case BLE_HCI_TRANS_H4_PKT_TYPE_EVT: #endif if (rxs->buf) { @@ -240,7 +240,7 @@ ble_hci_trans_h4_rx_state_completed(struct ble_hci_trans_h4_rx_state *rxs, #if MYNEWT_VAL(BLE_CONTROLLER) case BLE_HCI_TRANS_H4_PKT_TYPE_CMD: #endif -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) case BLE_HCI_TRANS_H4_PKT_TYPE_EVT: #endif if (rxs->buf) { diff --git a/nimble/transport/dialog_cmac/syscfg.yml b/nimble/transport/dialog_cmac/syscfg.yml index c44773efcd..54607fd814 100644 --- a/nimble/transport/dialog_cmac/syscfg.yml +++ b/nimble/transport/dialog_cmac/syscfg.yml @@ -16,28 +16,12 @@ # under the License. # -syscfg.defs: - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'Number of high-priority event buffers.' - value: 2 +syscfg.vals.'!BLE_HCI_BRIDGE && !(BLE_EXT_ADV || BLE_LL_CFG_FEAT_LL_EXT_ADV)': + BLE_HCI_EVT_HI_BUF_COUNT: 2 + BLE_HCI_EVT_LO_BUF_COUNT: 8 + BLE_HCI_EVT_BUF_SIZE: 70 + BLE_ACL_BUF_COUNT: 4 + BLE_ACL_BUF_SIZE: 255 - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'Number of low-priority event buffers.' - value: 8 - - BLE_HCI_EVT_BUF_SIZE: - description: 'Size of each event buffer, in bytes.' - value: 70 - - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 4 - - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 255 - -syscfg.vals.'BLE_EXT_ADV || BLE_LL_CFG_FEAT_LL_EXT_ADV': +syscfg.vals.'!BLE_HCI_BRIDGE && (BLE_EXT_ADV || BLE_LL_CFG_FEAT_LL_EXT_ADV)': BLE_HCI_EVT_BUF_SIZE: 257 diff --git a/nimble/transport/emspi/syscfg.yml b/nimble/transport/emspi/syscfg.yml index 4751271b0d..501175467a 100644 --- a/nimble/transport/emspi/syscfg.yml +++ b/nimble/transport/emspi/syscfg.yml @@ -28,28 +28,6 @@ syscfg.defs: # This is a host-only transport. - BLE_HOST - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'Number of high-priority event buffers.' - value: 2 - - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'Number of low-priority event buffers.' - value: 8 - - BLE_HCI_EVT_BUF_SIZE: - description: 'Size of each event buffer, in bytes.' - value: 70 - - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 4 - - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 255 - BLE_HCI_ACL_OUT_COUNT: description: > This count is used in creating a pool of elements used by the @@ -95,5 +73,12 @@ syscfg.defs: Sysinit stage for the EMSPI BLE transport. value: 100 -syscfg.vals.BLE_EXT_ADV: +syscfg.vals.'!BLE_HCI_BRIDGE && BLE_EXT_ADV': BLE_HCI_EVT_BUF_SIZE: 257 + +syscfg.vals.'!BLE_HCI_BRIDGE && !BLE_EXT_ADV': + BLE_HCI_EVT_HI_BUF_COUNT: 2 + BLE_HCI_EVT_LO_BUF_COUNT: 8 + BLE_HCI_EVT_BUF_SIZE: 70 + BLE_ACL_BUF_COUNT: 4 + BLE_ACL_BUF_SIZE: 255 diff --git a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c index 9bf956b56b..fe93c0fd6e 100644 --- a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c +++ b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c @@ -39,7 +39,7 @@ #define IPC_RX_CHANNEL 1 #endif -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) #define IPC_TX_CHANNEL 1 #define IPC_RX_CHANNEL 0 #endif @@ -49,7 +49,7 @@ struct nrf5340_ble_hci_api { ble_hci_trans_rx_cmd_fn *cmd_cb; void *cmd_arg; #endif -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) ble_hci_trans_rx_cmd_fn *evt_cb; void *evt_arg; #endif @@ -73,6 +73,7 @@ struct nrf5340_ble_hci_pool_cmd { bool allocated; }; +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) /* * If controller-to-host flow control is enabled we need to hold an extra command * buffer for HCI_Host_Number_Of_Completed_Packets which can be sent at any time. @@ -98,6 +99,8 @@ static uint8_t nrf5340_ble_hci_pool_evt_lo_buf[OS_MEMPOOL_BYTES( MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))]; static struct os_mempool nrf5340_ble_hci_pool_evt_lo; +#endif + /* Pool for ACL data */ static uint8_t nrf5340_ble_hci_pool_acl_buf[OS_MEMPOOL_BYTES( MYNEWT_VAL(BLE_ACL_BUF_COUNT), @@ -111,12 +114,14 @@ static struct nrf5340_ble_hci_api nrf5340_ble_hci_api; /* State of RX currently in progress (needs to reassemble frame) */ static struct nrf5340_ble_hci_rx_data nrf5340_ble_hci_rx_data; +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) int ble_hci_trans_reset(void) { /* XXX Should we do something with RF and/or BLE core? */ return 0; } +#endif static int ble_hci_trans_acl_tx(struct os_mbuf *om) @@ -177,7 +182,7 @@ ble_hci_trans_ll_acl_tx(struct os_mbuf *om) } #endif -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, void *evt_arg, ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg) @@ -212,6 +217,7 @@ ble_hci_trans_hs_acl_tx(struct os_mbuf *om) } #endif +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) uint8_t * ble_hci_trans_buf_alloc(int type) { @@ -255,12 +261,13 @@ ble_hci_trans_buf_free(uint8_t *buf) assert(rc == 0); } } +#endif static void nrf5340_ble_hci_trans_rx_process(int channel) { struct nrf5340_ble_hci_rx_data *rxd = &nrf5340_ble_hci_rx_data; -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) int pool = BLE_HCI_TRANS_BUF_EVT_HI; #endif int rc; @@ -274,7 +281,7 @@ nrf5340_ble_hci_trans_rx_process(int channel) #if MYNEWT_VAL(BLE_CONTROLLER) assert((rxd->type == HCI_PKT_ACL) || (rxd->type == HCI_PKT_CMD)); #endif -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) assert((rxd->type == HCI_PKT_ACL) || (rxd->type == HCI_PKT_EVT)); #endif break; @@ -312,7 +319,7 @@ nrf5340_ble_hci_trans_rx_process(int channel) rxd->type = HCI_PKT_NONE; break; #endif -#if MYNEWT_VAL(BLE_HOST) +#if MYNEWT_VAL(BLE_HOST) || MYNEWT_VAL(BLE_HCI_BRIDGE) case HCI_PKT_EVT: /* header */ if (rxd->len < 2) { @@ -433,6 +440,7 @@ nrf5340_ble_hci_trans_rx(int channel, void *user_data) } } +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg) { @@ -441,6 +449,7 @@ ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg) return 0; } +#endif void nrf5340_ble_hci_init(void) @@ -460,6 +469,7 @@ nrf5340_ble_hci_init(void) MYNEWT_VAL(BLE_ACL_BUF_COUNT)); SYSINIT_PANIC_ASSERT(rc == 0); +#if !MYNEWT_VAL(BLE_HCI_BRIDGE) rc = os_mempool_init(&nrf5340_ble_hci_pool_evt_hi, MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE), @@ -479,6 +489,7 @@ nrf5340_ble_hci_init(void) nrf5340_ble_hci_pool_cmd_mempool_buf, "nrf5340_ble_hci_pool_cmd_mempool"); SYSINIT_PANIC_ASSERT(rc == 0); +#endif ipc_nrf5340_recv(IPC_RX_CHANNEL, nrf5340_ble_hci_trans_rx, NULL); } diff --git a/nimble/transport/nrf5340/syscfg.yml b/nimble/transport/nrf5340/syscfg.yml index 1417bbc03d..a12e0c3736 100644 --- a/nimble/transport/nrf5340/syscfg.yml +++ b/nimble/transport/nrf5340/syscfg.yml @@ -17,34 +17,21 @@ # syscfg.defs: - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'Number of high-priority event buffers.' - value: 2 - - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'Number of low-priority event buffers.' - value: 8 - - BLE_HCI_EVT_BUF_SIZE: - description: 'Size of each event buffer, in bytes.' - value: 70 - - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 4 - - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 255 - BLE_TRANS_NRF5340_SYSINIT_STAGE: description: > Sysinit stage for the RAM BLE transport. value: 100 -syscfg.vals.BLE_EXT_ADV: +syscfg.vals.'!BLE_HCI_BRIDGE: + BLE_HCI_EVT_HI_BUF_COUNT: 2 + BLE_HCI_EVT_LO_BUF_COUNT: 8 + BLE_ACL_BUF_COUNT: 4 + BLE_ACL_BUF_SIZE: 255 + +syscfg.vals.'!BLE_HCI_BRIDGE && !BLE_EXT_ADV': + BLE_HCI_EVT_BUF_SIZE: 70 + +syscfg.vals.'!BLE_HCI_BRIDGE && BLE_EXT_ADV': BLE_HCI_EVT_BUF_SIZE: 257 syscfg.restrictions: diff --git a/nimble/transport/pkg.yml b/nimble/transport/pkg.yml index 8174286d06..5484002ebc 100644 --- a/nimble/transport/pkg.yml +++ b/nimble/transport/pkg.yml @@ -52,3 +52,9 @@ pkg.deps.'BLE_HCI_TRANSPORT == "usb"': pkg.deps.'BLE_HCI_TRANSPORT == "nrf5340"': - nimble/transport/nrf5340 + +pkg.deps.'BLE_HCI_BRIDGE_TRANSPORT == "nrf5340"': + - nimble/transport/nrf5340 + +pkg.deps.'BLE_HCI_BRIDGE_TRANSPORT == "dialog_cmac"': + - nimble/transport/dialog_cmac diff --git a/nimble/transport/ram/syscfg.yml b/nimble/transport/ram/syscfg.yml index cbb57163ad..6286dfe722 100644 --- a/nimble/transport/ram/syscfg.yml +++ b/nimble/transport/ram/syscfg.yml @@ -17,32 +17,17 @@ # syscfg.defs: - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'Number of high-priority event buffers.' - value: 2 - - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'Number of low-priority event buffers.' - value: 8 - - BLE_HCI_EVT_BUF_SIZE: - description: 'Size of each event buffer, in bytes.' - value: 70 - - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 4 - - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 65535 - BLE_TRANS_RAM_SYSINIT_STAGE: description: > Sysinit stage for the RAM BLE transport. value: 100 +syscfg.vals: + BLE_HCI_EVT_HI_BUF_COUNT: 2 + BLE_HCI_EVT_LO_BUF_COUNT: 8 + BLE_HCI_EVT_BUF_SIZE: 70 + BLE_ACL_BUF_COUNT: 4 + BLE_ACL_BUF_SIZE: 65535 + syscfg.vals.BLE_EXT_ADV: BLE_HCI_EVT_BUF_SIZE: 257 diff --git a/nimble/transport/socket/syscfg.yml b/nimble/transport/socket/syscfg.yml index 2050f64692..9c8fa583d6 100644 --- a/nimble/transport/socket/syscfg.yml +++ b/nimble/transport/socket/syscfg.yml @@ -17,24 +17,6 @@ # syscfg.defs: - BLE_HCI_EVT_BUF_SIZE: - description: 'The size of the allocated event buffers' - value: 70 - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'The number of high priority event buffers' - value: 8 - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'The number of low priority event buffers' - value: 8 - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 24 - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 255 - BLE_HCI_ACL_OUT_COUNT: description: > This count is used in creating a pool of elements used by the @@ -75,5 +57,12 @@ syscfg.defs: Sysinit stage for the socket BLE transport. value: 500 -syscfg.vals.BLE_EXT_ADV: +syscfg.vals.'!BLE_HCI_BRIDGE && BLE_EXT_ADV': BLE_HCI_EVT_BUF_SIZE: 257 + +syscfg.vals.'!BLE_HCI_BRIDGE && !BLE_EXT_ADV': + BLE_HCI_EVT_BUF_SIZE: 70 + BLE_HCI_EVT_HI_BUF_COUNT: 8 + BLE_HCI_EVT_LO_BUF_COUNT: 8 + BLE_ACL_BUF_COUNT: 24 + BLE_ACL_BUF_SIZE: 255 diff --git a/nimble/transport/syscfg.yml b/nimble/transport/syscfg.yml index 5bec6adf4d..7eed69ba4e 100644 --- a/nimble/transport/syscfg.yml +++ b/nimble/transport/syscfg.yml @@ -37,6 +37,47 @@ syscfg.defs: - usb # USB - nrf5340 # nRF5340 + BLE_HCI_BRIDGE_TRANSPORT: + description: > + Selects HCI transport to be included in bridge configuration build. + This applies to multi core configurations where controller runs + on separate core and main core forwards HCI traffic to external host. + This has virtually the same effect as including package dependency + manually, but it allows to easily override HCI transport package in + application or target settings. + This is the transport + value: + choices: + - dialog_cmac # Dialog CMAC via shared memory + - nrf5340 # nRF5340 + + BLE_HCI_BRIDGE: + description: > + External interface (UART/USB/Socket) bridged to second core controller. + value: 0 + + BLE_HCI_EVT_HI_BUF_COUNT: + description: 'Number of high-priority event buffers.' + value: + + BLE_HCI_EVT_LO_BUF_COUNT: + description: 'Number of low-priority event buffers.' + value: + + BLE_HCI_EVT_BUF_SIZE: + description: 'Size of each event buffer, in bytes.' + value: + + BLE_ACL_BUF_COUNT: + description: 'The number of ACL data buffers' + value: + + BLE_ACL_BUF_SIZE: + description: > + This is the maximum size of the data portion of HCI ACL data + packets. + value: + # Deprecated settings BLE_HCI_TRANSPORT_NIMBLE_BUILTIN: description: Use BLE_HCI_TRANSPORT instead. @@ -69,3 +110,10 @@ syscfg.vals.BLE_HCI_TRANSPORT_SOCKET: BLE_HCI_TRANSPORT: socket syscfg.vals.BLE_HCI_TRANSPORT_EMSPI: BLE_HCI_TRANSPORT: emspi + +syscfg.vals.'(MCU_TARGET == "DA14691" || MCU_TARGET == "DA14695" || MCU_TARGET == "DA14697" || MCU_TARGET == "DA14699")': + BLE_HCI_BRIDGE_TRANSPORT: dialog_cmac + +syscfg.vals.'(MCU_TARGET == "nRF5340_APP")': + BLE_HCI_BRIDGE_TRANSPORT: nrf5340 + diff --git a/nimble/transport/uart/src/ble_hci_uart.c b/nimble/transport/uart/src/ble_hci_uart.c index ac49b30b07..cc796c0005 100644 --- a/nimble/transport/uart/src/ble_hci_uart.c +++ b/nimble/transport/uart/src/ble_hci_uart.c @@ -53,7 +53,7 @@ */ /* XXX: for now, define this here */ -#if MYNEWT_VAL(BLE_CONTROLLER) +#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE) extern void ble_ll_data_buffer_overflow(void); extern void ble_ll_hw_error(void); @@ -385,7 +385,7 @@ ble_hci_uart_tx_char(void *arg) return rc; } -#if MYNEWT_VAL(BLE_CONTROLLER) +#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE) /** * HCI uart sync lost. * @@ -418,7 +418,7 @@ ble_hci_uart_rx_pkt_type(uint8_t data) switch (ble_hci_uart_state.rx_type) { /* Host should never receive a command! */ -#if MYNEWT_VAL(BLE_CONTROLLER) +#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE) case BLE_HCI_UART_H4_CMD: ble_hci_uart_state.rx_cmd.len = 0; ble_hci_uart_state.rx_cmd.cur = 0; @@ -458,7 +458,7 @@ ble_hci_uart_rx_pkt_type(uint8_t data) break; default: -#if MYNEWT_VAL(BLE_CONTROLLER) +#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE) /* * If we receive an unknown HCI packet type this is considered a loss * of sync. @@ -477,7 +477,7 @@ ble_hci_uart_rx_pkt_type(uint8_t data) return 0; } -#if MYNEWT_VAL(BLE_CONTROLLER) +#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE) /** * HCI uart sync loss. * @@ -708,7 +708,7 @@ ble_hci_uart_rx_acl(uint8_t data) */ if (pktlen > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) { os_mbuf_free_chain(ble_hci_uart_state.rx_acl.buf); -#if MYNEWT_VAL(BLE_CONTROLLER) +#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE) ble_hci_uart_sync_lost(); #else /* @@ -769,7 +769,7 @@ ble_hci_uart_rx_char(void *arg, uint8_t data) switch (ble_hci_uart_state.rx_type) { case BLE_HCI_UART_H4_NONE: return ble_hci_uart_rx_pkt_type(data); -#if MYNEWT_VAL(BLE_CONTROLLER) +#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE) case BLE_HCI_UART_H4_CMD: ble_hci_uart_rx_cmd(data); return 0; @@ -898,6 +898,7 @@ ble_hci_trans_ll_acl_tx(struct os_mbuf *om) return rc; } +#if MYNEWT_VAL(BLE_HOST) /** * Sends an HCI command from the host to the controller. * @@ -955,6 +956,7 @@ ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, { ble_hci_uart_set_rx_cbs(cmd_cb, cmd_arg, acl_cb, acl_arg); } +#endif /** * Configures the HCI transport to operate with a host. The transport will diff --git a/nimble/transport/uart/syscfg.yml b/nimble/transport/uart/syscfg.yml index 43486a8bfe..7eff9517c1 100644 --- a/nimble/transport/uart/syscfg.yml +++ b/nimble/transport/uart/syscfg.yml @@ -17,24 +17,6 @@ # syscfg.defs: - BLE_HCI_EVT_BUF_SIZE: - description: 'The size of the allocated event buffers' - value: 70 - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'The number of high priority event buffers' - value: 8 - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'The number of low priority event buffers' - value: 8 - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 12 - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 255 - BLE_HCI_ACL_OUT_COUNT: description: > This count is used in creating a pool of elements used by the @@ -70,3 +52,10 @@ syscfg.defs: syscfg.vals.BLE_EXT_ADV: BLE_HCI_EVT_BUF_SIZE: 257 + +syscfg.vals: + BLE_HCI_EVT_BUF_SIZE: 70 + BLE_HCI_EVT_HI_BUF_COUNT: 8 + BLE_HCI_EVT_LO_BUF_COUNT: 8 + BLE_ACL_BUF_COUNT: 12 + BLE_ACL_BUF_SIZE: 255 diff --git a/nimble/transport/usb/syscfg.yml b/nimble/transport/usb/syscfg.yml index ebc261a23d..38effde60c 100644 --- a/nimble/transport/usb/syscfg.yml +++ b/nimble/transport/usb/syscfg.yml @@ -17,24 +17,6 @@ # syscfg.defs: - BLE_HCI_EVT_BUF_SIZE: - description: 'The size of the allocated event buffers' - value: 70 - BLE_HCI_EVT_HI_BUF_COUNT: - description: 'The number of high priority event buffers' - value: 8 - BLE_HCI_EVT_LO_BUF_COUNT: - description: 'The number of low priority event buffers' - value: 8 - BLE_ACL_BUF_COUNT: - description: 'The number of ACL data buffers' - value: 12 - BLE_ACL_BUF_SIZE: - description: > - This is the maximum size of the data portion of HCI ACL data - packets. It does not include the HCI data header (of 4 bytes). - value: 255 - BLE_HCI_ACL_OUT_COUNT: description: > This count is used in creating a pool of elements used by the @@ -53,5 +35,12 @@ syscfg.defs: syscfg.vals.BLE_EXT_ADV: BLE_HCI_EVT_BUF_SIZE: 257 +syscfg.vals: + BLE_HCI_EVT_BUF_SIZE: 70 + BLE_HCI_EVT_HI_BUF_COUNT: 8 + BLE_HCI_EVT_LO_BUF_COUNT: 8 + BLE_ACL_BUF_COUNT: 12 + BLE_ACL_BUF_SIZE: 255 + syscfg.restrictions: - '!BLE_HOST' From 11b8107a371351a3adbad5dfe32571b07f9d4aab Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 22 Nov 2021 10:25:18 +0100 Subject: [PATCH 303/306] apps: Add blehcibridge application This application is equivalent of blehci for dual-core MCUs. It allows to forward traffic from external transport (USB/UART) to BLE core via internal transport. --- apps/blehcibridge/pkg.yml | 40 +++++++++++++++++++++ apps/blehcibridge/src/main.c | 69 ++++++++++++++++++++++++++++++++++++ apps/blehcibridge/syscfg.yml | 36 +++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 apps/blehcibridge/pkg.yml create mode 100644 apps/blehcibridge/src/main.c create mode 100644 apps/blehcibridge/syscfg.yml diff --git a/apps/blehcibridge/pkg.yml b/apps/blehcibridge/pkg.yml new file mode 100644 index 0000000000..9d170a89f3 --- /dev/null +++ b/apps/blehcibridge/pkg.yml @@ -0,0 +1,40 @@ +# 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. +# +pkg.name: apps/blehcibridge +pkg.type: app +pkg.description: BLE controller application exposing HCI over external interface +pkg.author: "Jerzy Kasenberg " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + +pkg.deps: + - "@apache-mynewt-core/sys/log/stub" + - "@apache-mynewt-core/sys/stats/full" + - "@apache-mynewt-core/kernel/os" + - "@apache-mynewt-core/sys/shell" + - nimble/transport + +pkg.req_apis: + - ble_transport + +pkg.deps.'CONSOLE_MODE=="full"': + - "@apache-mynewt-core/sys/console/full" +pkg.deps.'CONSOLE_MODE=="minimal": + - "@apache-mynewt-core/sys/console/minimal" +pkg.deps.'CONSOLE_MODE=="stub": + - "@apache-mynewt-core/sys/console/stub" diff --git a/apps/blehcibridge/src/main.c b/apps/blehcibridge/src/main.c new file mode 100644 index 0000000000..620cc37121 --- /dev/null +++ b/apps/blehcibridge/src/main.c @@ -0,0 +1,69 @@ +/* + * 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 +#include + +static int +forward_cmd_to_controller(uint8_t *cmdbuf, void *arg) +{ + (void)arg; + + return ble_hci_trans_hs_cmd_tx(cmdbuf); +} + +int +forward_acl_to_controller(struct os_mbuf *om, void *arg) +{ + (void)arg; + + return ble_hci_trans_hs_acl_tx(om); +} + +static int +forward_evt_to_host(uint8_t *hci_ev, void *arg) +{ + (void)arg; + + return ble_hci_trans_ll_evt_tx(hci_ev); +} + +int +forward_acl_to_host(struct os_mbuf *om, void *arg) +{ + (void)arg; + + return ble_hci_trans_ll_acl_tx(om); +} + +int +main(void) +{ + /* Initialize OS */ + sysinit(); + + ble_hci_trans_cfg_hs(forward_evt_to_host, NULL, forward_acl_to_host, NULL); + ble_hci_trans_cfg_ll(forward_cmd_to_controller, NULL, forward_acl_to_controller, NULL); + + while (1) { + os_eventq_run(os_eventq_dflt_get()); + } + return 0; +} diff --git a/apps/blehcibridge/syscfg.yml b/apps/blehcibridge/syscfg.yml new file mode 100644 index 0000000000..146ab52642 --- /dev/null +++ b/apps/blehcibridge/syscfg.yml @@ -0,0 +1,36 @@ +# 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. +# + +syscfg.defs: + CONSOLE_MODE: + description: Which console to use + value: stub + choices: + - full + - minimal + - stub + +syscfg.vals: + # Default task settings + OS_MAIN_STACK_SIZE: 64 + # Use USB transport by default + BLE_HCI_TRANSPORT: usb + + SHELL_TASK: 1 + + BLE_HCI_BRIDGE: 1 From 4386bb4c2cde5f4977cab0d4975f9ff818c18391 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 22 Nov 2021 14:12:34 +0100 Subject: [PATCH 304/306] apps: Update transport selection method Transport package should not be included directly. Instead, nimble/transport should be included and BLE_HCI_TRANSPORT syscfv value should specify transport, and this will include correct package. This commit changes nimble/transport/ram to nimble/transport in all applications that still have deprecated way of transport selection. --- nimble/controller/test/pkg.yml | 2 +- nimble/controller/test/syscfg.yml | 1 + nimble/host/test/pkg.yml | 2 +- nimble/host/test/syscfg.yml | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/nimble/controller/test/pkg.yml b/nimble/controller/test/pkg.yml index ea72881149..1b06a5b576 100644 --- a/nimble/controller/test/pkg.yml +++ b/nimble/controller/test/pkg.yml @@ -31,4 +31,4 @@ pkg.deps.SELFTEST: - "@apache-mynewt-core/sys/log/full" - "@apache-mynewt-core/sys/stats/stub" - nimble/drivers/native - - nimble/transport/ram + - nimble/transport diff --git a/nimble/controller/test/syscfg.yml b/nimble/controller/test/syscfg.yml index 6edad438bb..4448a0e66f 100644 --- a/nimble/controller/test/syscfg.yml +++ b/nimble/controller/test/syscfg.yml @@ -23,3 +23,4 @@ syscfg.vals: MCU_TIMER_POLLER_PRIO: 1 MCU_UART_POLLER_PRIO: 2 NATIVE_SOCKETS_PRIO: 3 + BLE_HCI_TRANSPORT: ram diff --git a/nimble/host/test/pkg.yml b/nimble/host/test/pkg.yml index dd1ad18bf3..cb5d97cfb3 100644 --- a/nimble/host/test/pkg.yml +++ b/nimble/host/test/pkg.yml @@ -31,4 +31,4 @@ pkg.deps.SELFTEST: - "@apache-mynewt-core/sys/console/stub" - "@apache-mynewt-core/sys/log/full" - "@apache-mynewt-core/sys/stats/stub" - - nimble/transport/ram + - nimble/transport diff --git a/nimble/host/test/syscfg.yml b/nimble/host/test/syscfg.yml index 6307398e4c..45bc638b62 100644 --- a/nimble/host/test/syscfg.yml +++ b/nimble/host/test/syscfg.yml @@ -29,3 +29,4 @@ syscfg.vals: CONFIG_FCB: 1 BLE_VERSION: 52 BLE_L2CAP_ENHANCED_COC: 1 + BLE_HCI_TRANSPORT: ram From 390744d836658c2eecd32e8883fa9d072f4d1c65 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 22 Nov 2021 15:05:21 +0100 Subject: [PATCH 305/306] transport: Bridge build workaround Function ble_ll_data_buffer_overflow() and ble_ll_hw_error() are executed from host code, but those are controller functions. They would only work when host and controller runs on same CPU. In bridge build when controller code can't be executed this way two transports (nrf5340/dialog_cmac) provide those functions so UART can be used in bridge configuration. This is just workaround till functions are implemented or other way of signaling those errors is established. --- .../dialog_cmac/src/ble_hci_cmac_hs.c | 21 +++++++++++++++++++ .../transport/nrf5340/src/nrf5340_ble_hci.c | 21 +++++++++++++++++++ nimble/transport/usb/pkg.yml | 1 + 3 files changed, 43 insertions(+) diff --git a/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c b/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c index 172fc87952..266637f78e 100644 --- a/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c +++ b/nimble/transport/dialog_cmac/src/ble_hci_cmac_hs.c @@ -41,6 +41,27 @@ static struct ble_hci_cmac_hs_api g_ble_hci_cmac_hs_api; static struct ble_hci_trans_h4_rx_state g_ble_hci_cmac_hs_rx_state; static bool g_ble_hci_cmac_hs_read_err; +#if MYNEWT_VAL(BLE_HCI_BRIDGE) +/* + * TODO: Remove/fix functions ble_ll_data_buffer_overflow() ble_ll_hw_error() + * Following two functions are added to allowed build of HCI bridge configurations. + * Those functions are only used by UART transport, in RAM transport configuration + * they can be called directly in bridge mode controller code is on other core + * and those can't be called. + */ +void +ble_ll_data_buffer_overflow(void) +{ + +} + +void +ble_ll_hw_error(uint8_t err) +{ + (void)err; +} +#endif + static int ble_hci_cmac_hs_frame_cb(uint8_t pkt_type, void *data) { diff --git a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c index fe93c0fd6e..41f164edb2 100644 --- a/nimble/transport/nrf5340/src/nrf5340_ble_hci.c +++ b/nimble/transport/nrf5340/src/nrf5340_ble_hci.c @@ -123,6 +123,27 @@ ble_hci_trans_reset(void) } #endif +#if MYNEWT_VAL(BLE_HCI_BRIDGE) +/* + * TODO: Remove/fix functions ble_ll_data_buffer_overflow() ble_ll_hw_error() + * Following two functions are added to allowed build of HCI bridge configurations. + * Those functions are only used by UART transport, in RAM transport configuration + * they can be called directly in bridge mode controller code is on other core + * and those can't be called. + */ +void +ble_ll_data_buffer_overflow(void) +{ + +} + +void +ble_ll_hw_error(uint8_t err) +{ + (void)err; +} +#endif + static int ble_hci_trans_acl_tx(struct os_mbuf *om) { diff --git a/nimble/transport/usb/pkg.yml b/nimble/transport/usb/pkg.yml index 49317c97d5..c4c314c867 100644 --- a/nimble/transport/usb/pkg.yml +++ b/nimble/transport/usb/pkg.yml @@ -31,6 +31,7 @@ pkg.deps: - "@apache-mynewt-core/kernel/os" - "@apache-mynewt-core/util/mem" - nimble + - "@apache-mynewt-core/hw/usb/tinyusb" pkg.apis: - ble_transport From c1d153d60e944fed0e76458fcea19fad84d9c639 Mon Sep 17 00:00:00 2001 From: Marceau Fillon Date: Mon, 20 Sep 2021 11:31:48 +1000 Subject: [PATCH 306/306] nimble/host: Support database hash Supports database hash characteristic. Computes database hash and stores it on first pairing with device. Computes current hash and compares it with stored hash on reconnection. See BLE Core spec 5.2 section 7.2 --- nimble/host/include/host/ble_att.h | 1 + nimble/host/include/host/ble_gatt.h | 2 + nimble/host/include/host/ble_store.h | 35 +++++ .../gatt/include/services/gatt/ble_svc_gatt.h | 2 + nimble/host/services/gatt/src/ble_svc_gatt.c | 56 +++++++- nimble/host/src/ble_gatts.c | 124 ++++++++++++++++++ nimble/host/src/ble_sm.c | 10 ++ nimble/host/src/ble_store.c | 77 +++++++++++ nimble/host/src/ble_store_util.c | 8 +- 9 files changed, 311 insertions(+), 4 deletions(-) diff --git a/nimble/host/include/host/ble_att.h b/nimble/host/include/host/ble_att.h index 391a992aeb..1427b3b33d 100644 --- a/nimble/host/include/host/ble_att.h +++ b/nimble/host/include/host/ble_att.h @@ -38,6 +38,7 @@ struct os_mbuf; #define BLE_ATT_UUID_SECONDARY_SERVICE 0x2801 #define BLE_ATT_UUID_INCLUDE 0x2802 #define BLE_ATT_UUID_CHARACTERISTIC 0x2803 +#define BLE_ATT_UUID_DESCRIPTOR 0x2902 #define BLE_ATT_ERR_INVALID_HANDLE 0x01 #define BLE_ATT_ERR_READ_NOT_PERMITTED 0x02 diff --git a/nimble/host/include/host/ble_gatt.h b/nimble/host/include/host/ble_gatt.h index b06344fc2e..77028ce46d 100644 --- a/nimble/host/include/host/ble_gatt.h +++ b/nimble/host/include/host/ble_gatt.h @@ -894,3 +894,5 @@ int ble_gatts_start(void); */ #endif + +int ble_compute_db_hash(uint8_t db_hash[16]); \ No newline at end of file diff --git a/nimble/host/include/host/ble_store.h b/nimble/host/include/host/ble_store.h index 30a5666cfe..1f8a35cf9c 100644 --- a/nimble/host/include/host/ble_store.h +++ b/nimble/host/include/host/ble_store.h @@ -30,6 +30,7 @@ extern "C" { #define BLE_STORE_OBJ_TYPE_OUR_SEC 1 #define BLE_STORE_OBJ_TYPE_PEER_SEC 2 #define BLE_STORE_OBJ_TYPE_CCCD 3 +#define BLE_STORE_OBJ_TYPE_HASH 4 /** Failed to persist record; insufficient storage capacity. */ #define BLE_STORE_EVENT_OVERFLOW 1 @@ -120,6 +121,30 @@ struct ble_store_value_cccd { unsigned value_changed:1; }; +/** + * Used as a key for lookups of stored database hashes. + * This struct corresponds to the BLE_STORE_OBJ_TYPE_HASH store object type. + */ +struct ble_store_key_hash { + /** + * Key by peer identity address; + * peer_addr=BLE_ADDR_NONE means don't key off peer. + */ + ble_addr_t peer_addr; + + /** Number of results to skip; 0 means retrieve the first match. */ + uint8_t idx; +}; + +/** + * Represents the last stored server database hash for a paired client device. + * This struct corresponds to the BLE_STORE_OBJ_TYPE_HASH store object type. + */ +struct ble_store_value_hash{ + ble_addr_t peer_addr; + uint8_t db_hash[16]; +}; + /** * Used as a key for store lookups. This union must be accompanied by an * object type code to indicate which field is valid. @@ -127,6 +152,7 @@ struct ble_store_value_cccd { union ble_store_key { struct ble_store_key_sec sec; struct ble_store_key_cccd cccd; + struct ble_store_key_hash hash; }; /** @@ -136,6 +162,7 @@ union ble_store_key { union ble_store_value { struct ble_store_value_sec sec; struct ble_store_value_cccd cccd; + struct ble_store_value_hash hash; }; struct ble_store_status_event { @@ -266,10 +293,18 @@ int ble_store_read_cccd(const struct ble_store_key_cccd *key, int ble_store_write_cccd(const struct ble_store_value_cccd *value); int ble_store_delete_cccd(const struct ble_store_key_cccd *key); +int ble_store_read_hash(uint16_t conn_handle, + const struct ble_store_key_hash *key, + struct ble_store_value_hash *out_value); +int ble_store_write_hash(const struct ble_store_value_hash *value); +int ble_store_delete_hash(const struct ble_store_key_hash *key); + void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, const struct ble_store_value_sec *value); void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, const struct ble_store_value_cccd *value); +void ble_store_key_from_value_hash(struct ble_store_key_hash *out_key, + const struct ble_store_value_hash *value); void ble_store_key_from_value(int obj_type, union ble_store_key *out_key, diff --git a/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h b/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h index 06c44784af..344bc8520b 100644 --- a/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h +++ b/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h @@ -29,8 +29,10 @@ extern "C" { struct ble_hs_cfg; #define BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16 0x2a05 +#define BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16 0x2B2A void ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle); +void ble_svc_conn_gatt_changed(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle); void ble_svc_gatt_init(void); #ifdef __cplusplus diff --git a/nimble/host/services/gatt/src/ble_svc_gatt.c b/nimble/host/services/gatt/src/ble_svc_gatt.c index 78b4a0683c..c8cae8a620 100644 --- a/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/nimble/host/services/gatt/src/ble_svc_gatt.c @@ -22,8 +22,10 @@ #include "sysinit/sysinit.h" #include "host/ble_hs.h" #include "services/gatt/ble_svc_gatt.h" +#include "host/ble_gatt.h" static uint16_t ble_svc_gatt_changed_val_handle; +static uint16_t ble_svc_gatt_hash_val_handle; static uint16_t ble_svc_gatt_start_handle; static uint16_t ble_svc_gatt_end_handle; @@ -31,6 +33,10 @@ static int ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +static int +ble_svc_gatt_db_hash_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + static const struct ble_gatt_svc_def ble_svc_gatt_defs[] = { { /*** Service: GATT */ @@ -41,7 +47,14 @@ static const struct ble_gatt_svc_def ble_svc_gatt_defs[] = { .access_cb = ble_svc_gatt_access, .val_handle = &ble_svc_gatt_changed_val_handle, .flags = BLE_GATT_CHR_F_INDICATE, - }, { + }, + { + .uuid = BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16), + .access_cb = ble_svc_gatt_db_hash_access, + .val_handle = &ble_svc_gatt_hash_val_handle, + .flags = BLE_GATT_CHR_F_READ, + }, + { 0, /* No more characteristics in this service. */ } }, }, @@ -51,6 +64,28 @@ static const struct ble_gatt_svc_def ble_svc_gatt_defs[] = { }, }; +static int +ble_svc_gatt_db_hash_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + int rc; + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + assert(ctxt->chr == &ble_svc_gatt_defs[0].characteristics[1]); + uint8_t db_hash[16]; + uint16_t len_data = sizeof(db_hash); + int res = ble_compute_db_hash(db_hash); + if(res != 0){ + return BLE_ATT_ERR_UNLIKELY; + } + + rc = os_mbuf_append(ctxt->om, db_hash, len_data); + if(rc !=0){ + return BLE_ATT_ERR_UNLIKELY; + } + + return 0; +} + static int ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) @@ -73,7 +108,7 @@ ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle, put_le16(u8p + 0, ble_svc_gatt_start_handle); put_le16(u8p + 2, ble_svc_gatt_end_handle); - + return 0; } @@ -89,7 +124,22 @@ ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle) { ble_svc_gatt_start_handle = start_handle; ble_svc_gatt_end_handle = end_handle; - ble_gatts_chr_updated(ble_svc_gatt_changed_val_handle); + ble_gatts_chr_updated(ble_svc_gatt_changed_val_handle); +} + +/** + * Indicates a change in attribute assignment to specified peer. + * + * @param conn_handle The connection to indicate. + * @param start_handle The start of the affected handle range. + * @param end_handle The end of the affected handle range. + */ +void +ble_svc_conn_gatt_changed(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) +{ + ble_svc_gatt_start_handle = start_handle; + ble_svc_gatt_end_handle = end_handle; + ble_gattc_indicate(conn_handle, ble_svc_gatt_changed_val_handle); } void diff --git a/nimble/host/src/ble_gatts.c b/nimble/host/src/ble_gatts.c index 83402e7242..61a7189f8a 100644 --- a/nimble/host/src/ble_gatts.c +++ b/nimble/host/src/ble_gatts.c @@ -28,6 +28,17 @@ #define BLE_GATTS_INCLUDE_SZ 6 #define BLE_GATTS_CHR_MAX_SZ 19 +#if NIMBLE_BLE_SM +#include "tinycrypt/aes.h" +#include "tinycrypt/constants.h" +#include "tinycrypt/utils.h" + +#if MYNEWT_VAL(BLE_SM_SC) +#include "tinycrypt/cmac_mode.h" +#include "tinycrypt/ecc_dh.h" +#endif +#endif + static const ble_uuid_t *uuid_pri = BLE_UUID16_DECLARE(BLE_ATT_UUID_PRIMARY_SERVICE); static const ble_uuid_t *uuid_sec = @@ -1719,6 +1730,8 @@ ble_gatts_bonding_restored(uint16_t conn_handle) { struct ble_store_value_cccd cccd_value; struct ble_store_key_cccd cccd_key; + struct ble_store_value_hash hash_value; + struct ble_store_key_hash hash_key; struct ble_gatts_clt_cfg *clt_cfg; struct ble_hs_conn *conn; uint8_t att_op; @@ -1799,6 +1812,13 @@ ble_gatts_bonding_restored(uint16_t conn_handle) cccd_key.idx++; } + + hash_key.peer_addr = conn->bhc_peer_addr; + hash_key.peer_addr.type = + ble_hs_misc_peer_addr_type_to_id(conn->bhc_peer_addr.type); + hash_key.idx = 0; + + rc = ble_store_read_hash(conn_handle, &hash_key, &hash_value); // read peer hash, read the database hash characteristic and compare, if rc != 0 => ble_svc_conn_gatt_changed(0, 0xffff) } static struct ble_gatts_svc_entry * @@ -2182,3 +2202,107 @@ ble_gatts_init(void) return 0; } + +static void ble_db_hash_message_append_u16(uint16_t val, uint8_t *buf, uint8_t *len) { + val = htole16(val); + memcpy(buf + *len, &val, sizeof(uint16_t)); + *len += sizeof(uint16_t); +} + +static void ble_db_hash_message_append_u32(uint32_t val, uint8_t *buf, uint8_t *len) { + val = htole32(val); + memcpy(buf + *len, &val, sizeof(uint32_t)); + *len += sizeof(uint32_t); +} + +static void ble_db_hash_message_append_uuid(const ble_uuid_t *uuid, uint8_t *buf, uint8_t *len) { + switch (uuid->type) { + case BLE_UUID_TYPE_16: { + ble_db_hash_message_append_u16( BLE_UUID16(uuid)->value, buf, len); + break; + } + case BLE_UUID_TYPE_32: { + ble_db_hash_message_append_u32(BLE_UUID32(uuid)->value, buf, len); + break; + } + case BLE_UUID_TYPE_128: { + memcpy(buf + *len, BLE_UUID128(uuid)->value, 16); + *len += 16; + break; + } + default: + break; + } +} + +/** + * Called when the database cmac hash needs to be computed using the information + * from registered services, characteristics and descriptors. This + * function: + * o Sets up the cmac generator with a key of 0s + * o Parse services, characteristics and descriptors and adds information + * to the message to code. + * o Computes the cmac coded message. + */ +int ble_compute_db_hash(uint8_t db_hash[16]) +{ + uint8_t buf[24]; + uint8_t buf_len; + + struct tc_aes_key_sched_struct sched; + struct tc_cmac_struct state; + const uint8_t key[16] = {0}; + + if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) { + return BLE_HS_EUNKNOWN; + } + + for (int i = 0; i < ble_gatts_num_svc_entries; i++) { + struct ble_gatts_svc_entry *entry = &ble_gatts_svc_entries[i]; + buf_len = 0; + ble_db_hash_message_append_u16(entry->handle, buf, &buf_len); + ble_db_hash_message_append_u16(BLE_ATT_UUID_PRIMARY_SERVICE, buf, &buf_len); + ble_db_hash_message_append_uuid(entry->svc->uuid, buf, &buf_len); + + if (tc_cmac_update(&state, buf, buf_len) == TC_CRYPTO_FAIL) { + return BLE_HS_EUNKNOWN; + } + buf_len = 0; + + if (entry->svc->characteristics != NULL) { + for (const struct ble_gatt_chr_def *chr = entry->svc->characteristics; chr && chr->uuid; chr++) { + if (chr->val_handle == NULL) { + continue; + } + ble_db_hash_message_append_u16(*chr->val_handle - 1, buf, &buf_len); + ble_db_hash_message_append_u16(BLE_ATT_UUID_CHARACTERISTIC, buf, &buf_len); + ble_db_hash_message_append_u16(chr->flags, buf, &buf_len); + ble_db_hash_message_append_u16(*chr->val_handle, buf, &buf_len); + ble_db_hash_message_append_uuid(chr->uuid, buf, &buf_len); + + if (tc_cmac_update(&state, buf, buf_len) == TC_CRYPTO_FAIL) { + return BLE_HS_EUNKNOWN; + } + buf_len = 0; + + if (chr->descriptors != NULL) { + for (struct ble_gatt_dsc_def *dsc = chr->descriptors; dsc && dsc->uuid; dsc++) { + ble_db_hash_message_append_u16(*chr->val_handle + 1, buf, &buf_len); + ble_db_hash_message_append_u16(BLE_ATT_UUID_DESCRIPTOR, buf, &buf_len); + + if (tc_cmac_update(&state, buf, buf_len) == TC_CRYPTO_FAIL) { + return BLE_HS_EUNKNOWN; + } + buf_len = 0; + } + } + } + } + } + + if (tc_cmac_final(db_hash, &state) == TC_CRYPTO_FAIL) { + return BLE_HS_EUNKNOWN; + } + + return 0; +} diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index c63af4087c..8f2bc5f517 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -516,11 +516,13 @@ static void ble_sm_persist_keys(struct ble_sm_proc *proc) { struct ble_store_value_sec value_sec; + struct ble_store_value_hash value_hash; struct ble_hs_conn *conn; ble_addr_t peer_addr; int authenticated; int identity_ev = 0; int sc; + int rc; ble_hs_lock(); @@ -577,6 +579,14 @@ ble_sm_persist_keys(struct ble_sm_proc *proc) ble_sm_fill_store_value(&peer_addr, authenticated, sc, &proc->peer_keys, &value_sec); ble_store_write_peer_sec(&value_sec); + + + // Compute current database hash and store it + value_hash.peer_addr = peer_addr; + rc = ble_compute_db_hash(value_hash.db_hash); + if (rc == 0) { + rc = ble_store_write_hash(&value_hash); + } } static int diff --git a/nimble/host/src/ble_store.c b/nimble/host/src/ble_store.c index 22e6089471..574973904a 100644 --- a/nimble/host/src/ble_store.c +++ b/nimble/host/src/ble_store.c @@ -21,6 +21,8 @@ #include "host/ble_store.h" #include "ble_hs_priv.h" +#include "host/ble_gatt.h" +#include "services/gatt/ble_svc_gatt.h" int ble_store_read(int obj_type, const union ble_store_key *key, @@ -249,6 +251,64 @@ ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec) return 0; } +int +ble_store_read_hash(uint16_t conn_handle, const struct ble_store_key_hash *key_hash, + struct ble_store_value_hash *value_hash) +{ + union ble_store_value *store_value; + union ble_store_key *store_key; + int rc; + int rc_calc; + + store_key = (void *)key_hash; + store_value = (void *)value_hash; + rc = ble_store_read(BLE_STORE_OBJ_TYPE_HASH, store_key, store_value); + + struct ble_store_value_hash new_value_hash; + new_value_hash.peer_addr = key_hash->peer_addr; + rc_calc = ble_compute_db_hash(new_value_hash.db_hash); + if (rc_calc != 0) { + return rc_calc; + } + if (rc == 0) { + for(int i=0; i<16; i++){ + if(memcmp(new_value_hash.db_hash, value_hash->db_hash, 16) != 0){ + rc = 1; + break; + } + } + } + + if (rc != 0) { + ble_store_write_hash(&new_value_hash); + ble_svc_conn_gatt_changed(conn_handle, 0x0001, 0xffff); + } + + return rc; +} + +int +ble_store_write_hash(const struct ble_store_value_hash *value_hash) +{ + int rc; + union ble_store_value *store_value; + + store_value = (void *)value_hash; + rc = ble_store_write(BLE_STORE_OBJ_TYPE_HASH, store_value); + return rc; +} + +int +ble_store_delete_hash(const struct ble_store_key_hash *key) +{ + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + rc = ble_store_delete(BLE_STORE_OBJ_TYPE_HASH, store_key); + return rc; +} + int ble_store_read_cccd(const struct ble_store_key_cccd *key, struct ble_store_value_cccd *out_value) @@ -306,6 +366,14 @@ ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, out_key->idx = 0; } +void +ble_store_key_from_value_hash(struct ble_store_key_hash *out_key, + const struct ble_store_value_hash *value) +{ + out_key->peer_addr = value->peer_addr; + out_key->idx = 0; +} + void ble_store_key_from_value(int obj_type, union ble_store_key *out_key, @@ -321,6 +389,10 @@ ble_store_key_from_value(int obj_type, ble_store_key_from_value_cccd(&out_key->cccd, &value->cccd); break; + case BLE_STORE_OBJ_TYPE_HASH: + ble_store_key_from_value_hash(&out_key->hash, &value->hash); + break; + default: BLE_HS_DBG_ASSERT(0); break; @@ -350,6 +422,10 @@ ble_store_iterate(int obj_type, key.cccd.peer_addr = *BLE_ADDR_ANY; pidx = &key.cccd.idx; break; + case BLE_STORE_OBJ_TYPE_HASH: + key.hash.peer_addr = *BLE_ADDR_ANY; + pidx = &key.hash.idx; + break; default: BLE_HS_DBG_ASSERT(0); return BLE_HS_EINVAL; @@ -394,6 +470,7 @@ ble_store_clear(void) BLE_STORE_OBJ_TYPE_OUR_SEC, BLE_STORE_OBJ_TYPE_PEER_SEC, BLE_STORE_OBJ_TYPE_CCCD, + BLE_STORE_OBJ_TYPE_HASH }; union ble_store_key key; int obj_type; diff --git a/nimble/host/src/ble_store_util.c b/nimble/host/src/ble_store_util.c index 7de482721b..39247f945a 100644 --- a/nimble/host/src/ble_store_util.c +++ b/nimble/host/src/ble_store_util.c @@ -101,7 +101,8 @@ ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers, /** * Deletes all entries from the store that are attached to the specified peer - * address. This function deletes security entries and CCCD records. + * address. This function deletes security entries, CCCD records and stored + * database hashes. * * @param peer_id_addr Entries with this peer address get deleted. * @@ -127,6 +128,11 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr) return rc; } + rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_HASH, &key); + if (rc != 0) { + return rc; + } + memset(&key, 0, sizeof key); key.cccd.peer_addr = *peer_id_addr;