From 98ea693d4172936686fab0034f8021552aa1f252 Mon Sep 17 00:00:00 2001
From: Jason2866 <24528715+Jason2866@users.noreply.github.com>
Date: Wed, 17 Aug 2022 12:20:12 +0200
Subject: [PATCH 1/3] NimBLE 1.4.0
---
lib/libesp32_div/NimBLE-Arduino/.gitignore | 1 +
lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md | 141 +-
lib/libesp32_div/NimBLE-Arduino/README.md | 79 +-
.../docs/Bluetooth 5 features.md | 28 +
.../docs/Command_line_config.md | 40 +-
lib/libesp32_div/NimBLE-Arduino/docs/Doxyfile | 2673 +++++++++++++++++
.../docs/Improvements_and_updates.md | 110 +-
.../NimBLE-Arduino/docs/Migration_guide.md | 316 +-
.../NimBLE-Arduino/docs/New_user_guide.md | 8 +-
.../NimBLE-Arduino/docs/Usage_tips.md | 6 +-
lib/libesp32_div/NimBLE-Arduino/docs/index.md | 70 +
.../NimBLE_extended_client.ino | 171 ++
.../NimBLE_extended_server.ino | 150 +
.../NimBLE_multi_advertiser.ino | 181 ++
.../examples/NimBLE_Client/NimBLE_Client.ino | 4 +
.../NimBLE_Secure_Client.ino | 16 +-
.../NimBLE_Secure_Server.ino | 8 +-
.../examples/NimBLE_Server/NimBLE_Server.ino | 58 +-
lib/libesp32_div/NimBLE-Arduino/library.json | 2 +-
.../NimBLE-Arduino/library.properties | 4 +-
.../NimBLE-Arduino/src/NimBLE2904.cpp | 4 +-
.../NimBLE-Arduino/src/NimBLEAddress.cpp | 6 +-
.../src/NimBLEAdvertisedDevice.cpp | 169 +-
.../src/NimBLEAdvertisedDevice.h | 33 +-
.../NimBLE-Arduino/src/NimBLEAdvertising.cpp | 31 +-
.../NimBLE-Arduino/src/NimBLEAdvertising.h | 9 +-
.../NimBLE-Arduino/src/NimBLEAttValue.h | 2 +-
.../NimBLE-Arduino/src/NimBLEBeacon.cpp | 2 +-
.../src/NimBLECharacteristic.cpp | 18 +-
.../NimBLE-Arduino/src/NimBLEClient.cpp | 107 +-
.../NimBLE-Arduino/src/NimBLEClient.h | 16 +-
.../NimBLE-Arduino/src/NimBLEDescriptor.cpp | 13 +-
.../NimBLE-Arduino/src/NimBLEDevice.cpp | 61 +-
.../NimBLE-Arduino/src/NimBLEDevice.h | 29 +-
.../NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp | 18 +-
.../NimBLE-Arduino/src/NimBLEEddystoneURL.cpp | 2 +-
.../src/NimBLEExtAdvertising.cpp | 870 ++++++
.../NimBLE-Arduino/src/NimBLEExtAdvertising.h | 152 +
.../NimBLE-Arduino/src/NimBLEHIDDevice.cpp | 2 +-
.../src/NimBLERemoteCharacteristic.cpp | 17 +-
.../src/NimBLERemoteCharacteristic.h | 4 +-
.../src/NimBLERemoteService.cpp | 18 +-
.../NimBLE-Arduino/src/NimBLEScan.cpp | 92 +-
.../NimBLE-Arduino/src/NimBLESecurity.cpp | 4 +-
.../NimBLE-Arduino/src/NimBLEServer.cpp | 97 +-
.../NimBLE-Arduino/src/NimBLEServer.h | 30 +-
.../NimBLE-Arduino/src/NimBLEUUID.cpp | 6 +-
.../NimBLE-Arduino/src/NimBLEUtils.cpp | 6 +-
.../NimBLE-Arduino/src/nimble/README.md | 1 +
.../src/nimble/RELEASE_NOTES.md | 25 +-
.../src/nimble/console/console.h | 2 +-
.../esp_port/port/include/esp_nimble_cfg.h | 89 +
.../nimble/esp_port/port/src/esp_nimble_mem.c | 44 +
.../esp_port/port/src/esp_nimble_mem.cpp | 53 -
.../controller/include/controller/ble_ll.h | 38 +
.../include/controller/ble_ll_conn.h | 7 +
.../include/controller/ble_ll_ctrl.h | 87 +-
.../include/controller/ble_ll_hci.h | 2 +-
.../include/controller/ble_ll_iso.h | 53 +
.../controller/include/controller/ble_phy.h | 2 +
.../src/nimble/nimble/controller/src/ble_ll.c | 66 +-
.../nimble/nimble/controller/src/ble_ll_adv.c | 30 +-
.../nimble/controller/src/ble_ll_conn.c | 480 ++-
.../nimble/controller/src/ble_ll_conn_hci.c | 35 +-
.../nimble/controller/src/ble_ll_conn_priv.h | 13 +-
.../nimble/controller/src/ble_ll_ctrl.c | 135 +-
.../nimble/nimble/controller/src/ble_ll_hci.c | 266 +-
.../nimble/controller/src/ble_ll_hci_ev.c | 31 +
.../nimble/nimble/controller/src/ble_ll_iso.c | 147 +
.../nimble/controller/src/ble_ll_rand.c | 18 +
.../nimble/controller/src/ble_ll_scan.c | 64 +-
.../nimble/controller/src/ble_ll_sched.c | 32 +-
.../nimble/controller/src/ble_ll_supp_cmd.c | 91 +-
.../nimble/controller/src/ble_ll_sync.c | 142 +-
.../nimble/controller/src/ble_ll_utils.c | 7 +-
.../nimble/nimble/drivers/nrf51/src/ble_phy.c | 4 +-
.../nimble/nimble/drivers/nrf52/src/ble_phy.c | 6 +-
.../nimble/nimble/host/include/host/ble_gap.h | 97 +-
.../nimble/host/include/host/ble_hs_log.h | 1 +
.../nimble/host/include/host/ble_monitor.h | 1 +
.../nimble/host/mesh/include/mesh/access.h | 109 +-
.../nimble/host/mesh/include/mesh/atomic.h | 409 +++
.../nimble/host/mesh/include/mesh/cdb.h | 267 ++
.../nimble/host/mesh/include/mesh/cfg.h | 485 +++
.../nimble/host/mesh/include/mesh/cfg_cli.h | 244 +-
.../nimble/host/mesh/include/mesh/cfg_srv.h | 42 +-
.../nimble/host/mesh/include/mesh/glue.h | 202 +-
.../host/mesh/include/mesh/health_cli.h | 42 +-
.../host/mesh/include/mesh/health_srv.h | 20 +-
.../nimble/host/mesh/include/mesh/heartbeat.h | 123 +
.../nimble/host/mesh/include/mesh/main.h | 198 +-
.../nimble/host/mesh/include/mesh/mesh.h | 5 +
.../nimble/host/mesh/include/mesh/model_cli.h | 18 +-
.../nimble/host/mesh/include/mesh/model_srv.h | 24 +-
.../nimble/host/mesh/include/mesh/testing.h | 22 +-
.../src/nimble/nimble/host/mesh/src/access.c | 188 +-
.../src/nimble/nimble/host/mesh/src/access.h | 23 +-
.../src/nimble/nimble/host/mesh/src/adv.c | 44 +-
.../src/nimble/nimble/host/mesh/src/adv.h | 19 +-
.../src/nimble/nimble/host/mesh/src/aes-ccm.c | 229 ++
.../nimble/nimble/host/mesh/src/app_keys.c | 512 ++++
.../nimble/nimble/host/mesh/src/app_keys.h | 86 +
.../src/nimble/nimble/host/mesh/src/beacon.c | 287 +-
.../src/nimble/nimble/host/mesh/src/beacon.h | 1 +
.../src/nimble/nimble/host/mesh/src/cdb.c | 393 +++
.../src/nimble/nimble/host/mesh/src/cfg.c | 272 ++
.../src/nimble/nimble/host/mesh/src/cfg.h | 9 +
.../src/nimble/nimble/host/mesh/src/cfg_cli.c | 901 +++++-
.../src/nimble/nimble/host/mesh/src/cfg_srv.c | 1803 +++--------
.../src/nimble/nimble/host/mesh/src/crypto.c | 550 +---
.../src/nimble/nimble/host/mesh/src/crypto.h | 143 +-
.../nimble/nimble/host/mesh/src/foundation.h | 42 +-
.../src/nimble/nimble/host/mesh/src/friend.c | 443 +--
.../src/nimble/nimble/host/mesh/src/friend.h | 20 +-
.../src/nimble/nimble/host/mesh/src/glue.c | 96 +-
.../nimble/nimble/host/mesh/src/health_cli.c | 68 +-
.../nimble/nimble/host/mesh/src/health_srv.c | 38 +-
.../nimble/nimble/host/mesh/src/heartbeat.c | 356 +++
.../nimble/nimble/host/mesh/src/heartbeat.h | 40 +
.../nimble/nimble/host/mesh/src/light_model.c | 22 +-
.../nimble/nimble/host/mesh/src/light_model.h | 12 +-
.../src/nimble/nimble/host/mesh/src/lpn.c | 195 +-
.../src/nimble/nimble/host/mesh/src/lpn.h | 6 +-
.../src/nimble/nimble/host/mesh/src/mesh.c | 233 +-
.../nimble/nimble/host/mesh/src/mesh_priv.h | 22 +-
.../nimble/nimble/host/mesh/src/model_cli.c | 30 +-
.../nimble/nimble/host/mesh/src/model_srv.c | 16 +-
.../src/nimble/nimble/host/mesh/src/net.c | 1188 ++------
.../src/nimble/nimble/host/mesh/src/net.h | 245 +-
.../src/nimble/nimble/host/mesh/src/nodes.c | 2 +-
.../src/nimble/nimble/host/mesh/src/pb_adv.c | 891 ++++++
.../src/nimble/nimble/host/mesh/src/pb_gatt.c | 163 +
.../src/nimble/nimble/host/mesh/src/prov.c | 1982 ++----------
.../src/nimble/nimble/host/mesh/src/prov.h | 133 +-
.../nimble/nimble/host/mesh/src/prov_bearer.h | 116 +
.../nimble/nimble/host/mesh/src/prov_device.c | 573 ++++
.../nimble/nimble/host/mesh/src/provisioner.c | 750 +++++
.../nimble/nimble/host/mesh/src/provisioner.h | 10 +
.../src/nimble/nimble/host/mesh/src/proxy.c | 275 +-
.../src/nimble/nimble/host/mesh/src/proxy.h | 15 +-
.../src/nimble/nimble/host/mesh/src/rpl.c | 167 +
.../src/nimble/nimble/host/mesh/src/rpl.h | 30 +
.../nimble/nimble/host/mesh/src/settings.c | 1305 +++++---
.../nimble/nimble/host/mesh/src/settings.h | 17 +-
.../src/nimble/nimble/host/mesh/src/shell.c | 1227 ++++++--
.../src/nimble/nimble/host/mesh/src/subnet.c | 670 +++++
.../src/nimble/nimble/host/mesh/src/subnet.h | 197 ++
.../nimble/nimble/host/mesh/src/transport.c | 1242 ++++----
.../nimble/nimble/host/mesh/src/transport.h | 80 +-
.../bas/include/services/bas/ble_svc_bas.h | 2 +
.../gap/include/services/gap/ble_svc_gap.h | 1 +
.../host/services/gap/src/ble_svc_gap.c | 6 +
.../src/nimble/nimble/host/src/ble_att.c | 3 +
.../src/nimble/nimble/host/src/ble_att_clt.c | 3 +
.../src/nimble/nimble/host/src/ble_att_cmd.c | 3 +
.../src/nimble/nimble/host/src/ble_att_svr.c | 5 +-
.../src/nimble/nimble/host/src/ble_gap.c | 176 +-
.../src/nimble/nimble/host/src/ble_gap_priv.h | 1 +
.../src/nimble/nimble/host/src/ble_gattc.c | 13 +-
.../nimble/nimble/host/src/ble_gatts_lcl.c | 2 +
.../src/nimble/nimble/host/src/ble_hs.c | 62 +-
.../src/nimble/nimble/host/src/ble_hs_conn.c | 9 +
.../src/nimble/nimble/host/src/ble_hs_flow.c | 29 +-
.../src/nimble/nimble/host/src/ble_hs_hci.c | 29 +-
.../nimble/nimble/host/src/ble_hs_hci_cmd.c | 12 +
.../nimble/nimble/host/src/ble_hs_hci_evt.c | 78 +-
.../nimble/nimble/host/src/ble_hs_hci_priv.h | 2 +
.../nimble/nimble/host/src/ble_hs_hci_util.c | 54 +
.../nimble/nimble/host/src/ble_hs_mqueue.c | 6 +
.../nimble/host/src/ble_hs_periodic_sync.c | 3 +
.../src/nimble/nimble/host/src/ble_hs_priv.h | 2 +
.../nimble/nimble/host/src/ble_hs_resolv.c | 1 +
.../src/nimble/nimble/host/src/ble_l2cap.c | 3 +
.../nimble/nimble/host/src/ble_l2cap_coc.c | 67 +-
.../nimble/nimble/host/src/ble_l2cap_priv.h | 1 +
.../nimble/nimble/host/src/ble_l2cap_sig.c | 26 +-
.../nimble/host/src/ble_l2cap_sig_cmd.c | 3 +
.../src/nimble/nimble/host/src/ble_monitor.c | 9 +
.../src/nimble/nimble/host/src/ble_sm.c | 6 +
.../src/nimble/nimble/host/src/ble_sm_alg.c | 44 +-
.../src/nimble/nimble/host/src/ble_sm_cmd.c | 3 +
.../src/nimble/nimble/host/src/ble_sm_lgcy.c | 2 +
.../src/nimble/nimble/host/src/ble_sm_sc.c | 2 +
.../src/nimble/nimble/host/src/ble_uuid.c | 6 +-
.../src/nimble/nimble/host/util/src/addr.c | 26 +-
.../src/nimble/nimble/include/nimble/ble.h | 9 +-
.../nimble/include/nimble/ble_hci_trans.h | 215 ++
.../nimble/nimble/include/nimble/hci_common.h | 348 ++-
.../nimble/transport/ram/src/ble_hci_ram.c | 6 +-
.../nimble/include/log_common/log_common.h | 104 +-
.../porting/nimble/include/logcfg/logcfg.h | 34 +-
.../nimble/porting/nimble/include/mem/mem.h | 39 +
.../porting/nimble/include/modlog/modlog.h | 48 +-
.../nimble/include/nimble/nimble_port.h | 25 +-
.../nimble/porting/nimble/include/os/endian.h | 63 +-
.../src/nimble/porting/nimble/include/os/os.h | 4 +
.../porting/nimble/include/os/os_cputime.h | 20 +-
.../porting/nimble/include/os/os_error.h | 19 +
.../porting/nimble/include/os/os_mbuf.h | 500 ++-
.../porting/nimble/include/os/os_mempool.h | 154 +-
.../porting/nimble/include/os/os_trace_api.h | 198 +-
.../nimble/porting/nimble/include/os/queue.h | 3 +-
.../porting/nimble/include/syscfg/syscfg.h | 23 +-
.../nimble/include/sysflash/sysflash.h | 2 +-
.../src/nimble/porting/nimble/src/endian.c | 12 +-
.../src/nimble/porting/nimble/src/hal_timer.c | 217 +-
.../src/nimble/porting/nimble/src/hal_uart.c | 388 +++
.../src/nimble/porting/nimble/src/mem.c | 25 +-
.../nimble/porting/nimble/src/nimble_port.c | 256 +-
.../porting/nimble/src/os_cputime_pwr2.c | 20 +-
.../src/nimble/porting/nimble/src/os_mbuf.c | 160 +-
.../nimble/porting/nimble/src/os_mempool.c | 259 +-
.../nimble/porting/nimble/src/os_msys_init.c | 129 +-
.../freertos/include/nimble/nimble_npl_os.h | 402 +++
.../include/nimble/nimble_port_freertos.h | 32 +-
.../freertos/include/nimble/npl_freertos.h | 36 +
.../npl/freertos/src/nimble_port_freertos.c | 71 +-
.../npl/freertos/src/npl_os_freertos.c | 1335 +++++++-
.../NimBLE-Arduino/src/nimconfig.h | 87 +-
.../NimBLE-Arduino/tasmota_lib_changes.md | 12 -
220 files changed, 25563 insertions(+), 8932 deletions(-)
create mode 100644 lib/libesp32_div/NimBLE-Arduino/.gitignore
create mode 100644 lib/libesp32_div/NimBLE-Arduino/docs/Bluetooth 5 features.md
create mode 100644 lib/libesp32_div/NimBLE-Arduino/docs/Doxyfile
create mode 100644 lib/libesp32_div/NimBLE-Arduino/docs/index.md
create mode 100644 lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_extended_client/NimBLE_extended_client.ino
create mode 100644 lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_extended_server/NimBLE_extended_server.ino
create mode 100644 lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_multi_advertiser/NimBLE_multi_advertiser.ino
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.cpp
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c
delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.cpp
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_iso.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_iso.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/atomic.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cdb.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/heartbeat.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/aes-ccm.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/app_keys.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/app_keys.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cdb.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/heartbeat.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/heartbeat.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/pb_adv.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/pb_gatt.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov_bearer.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov_device.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/provisioner.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/provisioner.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/rpl.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/rpl.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/subnet.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/subnet.h
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_uart.c
diff --git a/lib/libesp32_div/NimBLE-Arduino/.gitignore b/lib/libesp32_div/NimBLE-Arduino/.gitignore
new file mode 100644
index 000000000..111405a1c
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/.gitignore
@@ -0,0 +1 @@
+docs/doxydocs
diff --git a/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md b/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md
index 08d274106..5d1d2d409 100644
--- a/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md
+++ b/lib/libesp32_div/NimBLE-Arduino/CHANGELOG.md
@@ -2,6 +2,41 @@
All notable changes to this project will be documented in this file.
+## [1.4.0] - 2022-07-10
+
+### Fixed
+- Fixed missing data from long notification values.
+- Fixed NimbleCharacteristicCallbacks::onRead not being called when a non-long read command is received.
+
+### Changed
+- Updated NimBLE core to use the v1.4.0 branch of esp-nimble.
+- AD flags are no longer set in the advertisements of non-connectable beacons, freeing up 3 bytes of advertisement room.
+
+### Added
+- Preliminary support for non-esp devices, NRF51 and NRF52 devices supported with [n-able arduino core](https://github.com/h2zero/n-able-Arduino)
+- Alias added for `NimBLEServerCallbacks::onMTUChange` to `onMtuChanged` in order to support porting code from original library.
+- `NimBLEAttValue` Class added to reduce and control RAM footprint of characteristic/descriptor values and support conversions from Arduino Strings and many other data types.
+- Bluetooth 5 extended advertising support for capable devices. CODED Phy, 2M Phy, extended advertising data, and multi-advertising are supported, periodic advertising will be implemented in the future.
+
+## [1.3.8] - 2022-04-27
+
+### Fixed
+- Fix compile error with ESP32S3.
+- Prevent a potential crash when retrieving characteristics from a service if the result was successful but no characteristics found.
+
+### Changed
+- Save resources when retrieving descriptors if the characteristic handle is the same as the end handle (no descriptors).
+- Subscribing to characteristic notifications/indications will now always use write with response, as per BLE specifications.
+- `NimBLEClient::discoverAttributes` now returns a bool value to indicate success/failure
+
+## [1.3.7] - 2022-02-15
+
+### Fixed
+
+- Crash when retrieving an attribute that does not exist on the peer.
+- Memory leak when deleting client instances.
+- Compilation errors for esp32s3
+
## [1.3.6] - 2022-01-18
### Changed
@@ -11,7 +46,7 @@ All notable changes to this project will be documented in this file.
- Memory leak when services are changed on server devices.
- Rare crashing that occurs when BLE commands are sent from ISR context using IPC.
- Crashing caused by uninitialized disconnect timer in client.
-- Potential crash due to unintialized advertising callback pointer.
+- Potential crash due to uninitialized advertising callback pointer.
## [1.3.5] - 2022-01-14
@@ -48,7 +83,7 @@ All notable changes to this project will be documented in this file.
## [1.3.0] - 2021-08-02
### Added
-- `NimBLECharacteristic::removeDescriptor`: Dynamically remove a descriptor from a characterisic. Takes effect after all connections are closed and sends a service changed indication.
+- `NimBLECharacteristic::removeDescriptor`: Dynamically remove a descriptor from a characteristic. Takes effect after all connections are closed and sends a service changed indication.
- `NimBLEService::removeCharacteristic`: Dynamically remove a characteristic from a service. Takes effect after all connections are closed and sends a service changed indication
- `NimBLEServerCallbacks::onMTUChange`: This is callback is called when the MTU is updated after connection with a client.
- ESP32C3 support
@@ -79,12 +114,12 @@ All notable changes to this project will be documented in this file.
### Fixed
- `NimBLECharacteristicCallbacks::onSubscribe` Is now called after the connection is added to the vector.
- Corrected bonding failure when reinitializing the BLE stack.
-- Writing to a characterisic with a std::string value now correctly writes values with null characters.
-- Retrieving remote descriptors now uses the characterisic end handle correctly.
+- Writing to a characteristic with a std::string value now correctly writes values with null characters.
+- Retrieving remote descriptors now uses the characteristic end handle correctly.
- Missing data in long writes to remote descriptors.
- Hanging on task notification when sending an indication from the characteristic callback.
- BLE controller memory could be released when using Arduino as a component.
-- Complile errors with NimBLE release 1.3.0.
+- Compile errors with NimBLE release 1.3.0.
## [1.2.0] - 2021-02-08
@@ -97,7 +132,7 @@ All notable changes to this project will be documented in this file.
- `NimBLEService::getCharacteristicByHandle`: Get a pointer to the characteristic object with the specified handle.
-- `NimBLEService::getCharacteristics`: Get the vector containing pointers to each characteristic associated with this service.
+- `NimBLEService::getCharacteristics`: Get the vector containing pointers to each characteristic associated with this service.
Overloads to get a vector containing pointers to all the characteristics in a service with the UUID. (supports multiple same UUID's in a service)
- `NimBLEService::getCharacteristics(const char *uuid)`
- `NimBLEService::getCharacteristics(const NimBLEUUID &uuid)`
@@ -139,12 +174,12 @@ Overloads to get a vector containing pointers to all the characteristics in a se
- `NimBLEAdvertising` Transmission power is no longer advertised by default and can be added to the advertisement by calling `NimBLEAdvertising::addTxPower`
-- `NimBLEAdvertising` Custom scan response data can now be used without custom advertisment.
+- `NimBLEAdvertising` Custom scan response data can now be used without custom advertisement.
-- `NimBLEScan` Now uses the controller duplicate filter.
+- `NimBLEScan` Now uses the controller duplicate filter.
-- `NimBLEAdvertisedDevice` Has been refactored to store the complete advertisement payload and no longer parses the data from each advertisement.
-Instead the data will be parsed on-demand when the user application asks for specific data.
+- `NimBLEAdvertisedDevice` Has been refactored to store the complete advertisement payload and no longer parses the data from each advertisement.
+Instead the data will be parsed on-demand when the user application asks for specific data.
### Fixed
- `NimBLEHIDDevice` Characteristics now use encryption, this resolves an issue with communicating with devices requiring encryption for HID devices.
@@ -153,84 +188,84 @@ Instead the data will be parsed on-demand when the user application asks for spe
## [1.1.0] - 2021-01-20
### Added
-- `NimBLEDevice::setOwnAddrType` added to enable the use of random and random-resolvable addresses, by asukiaaa
+- `NimBLEDevice::setOwnAddrType` added to enable the use of random and random-resolvable addresses, by asukiaaa
-- New examples for securing and authenticating client/server connections, by mblasee.
+- New examples for securing and authenticating client/server connections, by mblasee.
-- `NimBLEAdvertising::SetMinPreferred` and `NimBLEAdvertising::SetMinPreferred` re-added.
+- `NimBLEAdvertising::SetMinPreferred` and `NimBLEAdvertising::SetMinPreferred` re-added.
-- Conditional checks added for command line config options in `nimconfig.h` to support custom configuration in platformio.
+- Conditional checks added for command line config options in `nimconfig.h` to support custom configuration in platformio.
-- `NimBLEClient::setValue` Now takes an extra bool parameter `response` to enable the use of write with response (default = false).
+- `NimBLEClient::setValue` Now takes an extra bool parameter `response` to enable the use of write with response (default = false).
-- `NimBLEClient::getCharacteristic(uint16_t handle)` Enabling the use of the characteristic handle to be used to find
-the NimBLERemoteCharacteristic object.
+- `NimBLEClient::getCharacteristic(uint16_t handle)` Enabling the use of the characteristic handle to be used to find
+the NimBLERemoteCharacteristic object.
-- `NimBLEHIDDevice` class added by wakwak-koba.
+- `NimBLEHIDDevice` class added by wakwak-koba.
-- `NimBLEServerCallbacks::onDisconnect` overloaded callback added to provide a ble_gap_conn_desc parameter for the application
-to obtain information about the disconnected client.
+- `NimBLEServerCallbacks::onDisconnect` overloaded callback added to provide a ble_gap_conn_desc parameter for the application
+to obtain information about the disconnected client.
-- Conditional checks in `nimconfig.h` for command line defined macros to support platformio config settings.
+- Conditional checks in `nimconfig.h` for command line defined macros to support platformio config settings.
### Changed
-- `NimBLEAdvertising::start` now returns a bool value to indicate success/failure.
+- `NimBLEAdvertising::start` now returns a bool value to indicate success/failure.
-- Some asserts were removed in `NimBLEAdvertising::start` and replaced with better return code handling and logging.
+- Some asserts were removed in `NimBLEAdvertising::start` and replaced with better return code handling and logging.
-- If a host reset event occurs, scanning and advertising will now only be restarted if their previous duration was indefinite.
+- If a host reset event occurs, scanning and advertising will now only be restarted if their previous duration was indefinite.
- `NimBLERemoteCharacteristic::subscribe` and `NimBLERemoteCharacteristic::registerForNotify` will now set the callback
-regardless of the existance of the CCCD and return true unless the descriptor write operation failed.
+regardless of the existence of the CCCD and return true unless the descriptor write operation failed.
-- Advertising tx power level is now sent in the advertisement packet instead of scan response.
+- Advertising tx power level is now sent in the advertisement packet instead of scan response.
-- `NimBLEScan` When the scan ends the scan stopped flag is now set before calling the scan complete callback (if used)
-this allows the starting of a new scan from the callback function.
+- `NimBLEScan` When the scan ends the scan stopped flag is now set before calling the scan complete callback (if used)
+this allows the starting of a new scan from the callback function.
### Fixed
-- Sometimes `NimBLEClient::connect` would hang on the task block if no event arrived to unblock.
-A time limit has been added to timeout appropriately.
+- Sometimes `NimBLEClient::connect` would hang on the task block if no event arrived to unblock.
+A time limit has been added to timeout appropriately.
-- When getting descriptors for a characterisic the end handle of the service was used as a proxy for the characteristic end
-handle. This would be rejected by some devices and has been changed to use the next characteristic handle as the end when possible.
+- When getting descriptors for a characteristic the end handle of the service was used as a proxy for the characteristic end
+handle. This would be rejected by some devices and has been changed to use the next characteristic handle as the end when possible.
-- An exception could occur when deleting a client instance if a notification arrived while the attribute vectors were being
-deleted. A flag has been added to prevent this.
-
-- An exception could occur after a host reset event when the host re-synced if the tasks that were stopped during the event did
-not finish processing. A yield has been added after re-syncing to allow tasks to finish before proceeding.
-
-- Occasionally the controller would fail to send a disconnected event causing the client to indicate it is connected
-and would be unable to reconnect. A timer has been added to reset the host/controller if it expires.
-
-- Occasionally the call to start scanning would get stuck in a loop on BLE_HS_EBUSY, this loop has been removed.
+- An exception could occur when deleting a client instance if a notification arrived while the attribute vectors were being
+deleted. A flag has been added to prevent this.
-- 16bit and 32bit UUID's in some cases were not discovered or compared correctly if the device
-advertised them as 16/32bit but resolved them to 128bits. Both are now checked.
-
-- `FreeRTOS` compile errors resolved in latest Ardruino core and IDF v3.3.
+- An exception could occur after a host reset event when the host re-synced if the tasks that were stopped during the event did
+not finish processing. A yield has been added after re-syncing to allow tasks to finish before proceeding.
-- Multiple instances of `time()` called inside critical sections caused sporadic crashes, these have been moved out of critical regions.
+- Occasionally the controller would fail to send a disconnected event causing the client to indicate it is connected
+and would be unable to reconnect. A timer has been added to reset the host/controller if it expires.
-- Advertisement type now correctly set when using non-connectable (advertiser only) mode.
+- Occasionally the call to start scanning would get stuck in a loop on BLE_HS_EBUSY, this loop has been removed.
-- Advertising payload length correction, now accounts for appearance.
+- 16bit and 32bit UUID's in some cases were not discovered or compared correctly if the device
+advertised them as 16/32bit but resolved them to 128bits. Both are now checked.
-- (Arduino) Ensure controller mode is set to BLE Only.
+- `FreeRTOS` compile errors resolved in latest Arduino core and IDF v3.3.
+
+- Multiple instances of `time()` called inside critical sections caused sporadic crashes, these have been moved out of critical regions.
+
+- Advertisement type now correctly set when using non-connectable (advertiser only) mode.
+
+- Advertising payload length correction, now accounts for appearance.
+
+- (Arduino) Ensure controller mode is set to BLE Only.
## [1.0.2] - 2020-09-13
### Changed
-- `NimBLEAdvertising::start` Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a
-callback that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
+- `NimBLEAdvertising::start` Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a
+callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
- (Arduino) Maximum BLE connections can now be altered by only changing the value of `CONFIG_BT_NIMBLE_MAX_CONNECTIONS` in `nimconfig.h`.
Any changes to the controller max connection settings in `sdkconfig.h` will now have no effect when using this library.
-- (Arduino) Revert the previous change to fix the advertising start delay. Instead a replacement fix that routes all BLE controller commands from
+- (Arduino) Revert the previous change to fix the advertising start delay. Instead a replacement fix that routes all BLE controller commands from
a task running on core 0 (same as the controller) has been implemented. This improves response times and reliability for all BLE functions.
diff --git a/lib/libesp32_div/NimBLE-Arduino/README.md b/lib/libesp32_div/NimBLE-Arduino/README.md
index fd480fd83..86b28e3f9 100644
--- a/lib/libesp32_div/NimBLE-Arduino/README.md
+++ b/lib/libesp32_div/NimBLE-Arduino/README.md
@@ -1,63 +1,50 @@
[Latest release 
-](https://github.com/h2zero/NimBLE-Arduino/releases/latest/)
+](https://github.com/h2zero/NimBLE-Arduino/releases/latest/)
-Need help? Have questions or suggestions? Join the [](https://gitter.im/NimBLE-Arduino/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+Need help? Have questions or suggestions? Join the [](https://gitter.im/NimBLE-Arduino/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
# NimBLE-Arduino
-A fork of the NimBLE stack restructured for compilation in the Ardruino IDE with a CPP library for use with ESP32.
+A fork of the NimBLE stack refactored for compilation in the Ardruino IDE.
-**Note for IDF users: This repo will not compile correctly in ESP-IDF. An ESP-IDF component version of this library can be [found here.](https://github.com/h2zero/esp-nimble-cpp)**
+**As of release 1.4.0 Nordic Semiconductor nRF51 and nRF52 series devices are now supported**
-This library **significantly** reduces resource usage and improves performance for ESP32 BLE applications as compared
-with the bluedroid based library. The goal is to maintain, as much as reasonable, compatibility with the original
-library but refactored to use the NimBLE stack. In addition, this library will be more actively developed and maintained
-to provide improved capabilites and stability over the original.
+## Supported MCU's
+ - Espressif: ESP32, ESP32C3, ESP32S3
+ - Nordic: nRF51, nRF52 series (**Requires** using [n-able arduino core](https://github.com/h2zero/n-able-Arduino))
+
+**Note for ESP-IDF users: This repo will not compile correctly in ESP-IDF. An ESP-IDF component version of this library can be [found here.](https://github.com/h2zero/esp-nimble-cpp)**
+
+This library **significantly** reduces resource usage and improves performance for ESP32 BLE applications as compared with the bluedroid based library. The goal is to maintain, as much as reasonable, compatibility with the original library but refactored to use the NimBLE stack. In addition, this library will be more actively developed and maintained to provide improved capabilities and stability over the original.
-## Resource use improvement
+For Nordic devices, this library provides access to a completely open source and configurable BLE stack. No softdevice to work around, allowing for full debugging and resource management, continuous updates, with a cross platform API.
-### (Original) BLE_client example comparison (Debug):
-#### Arduino BLE Library
-Sketch uses **1216377** bytes (58%) of program storage space.
-Memory after connection: Free Heap: **171548**
-
-#### NimBLE-Arduino library
-Sketch uses **617256** bytes (29%) of program storage space.
-Memory after connection: Free Heap: **270336**
-***
-### (Original) BLE_notify example comparison (Debug):
-#### Arduino BLE Library
-Sketch uses **1208409** bytes (57%) of program storage space.
-Memory after connection: Free Heap: **173300**
-
-#### NimBLE-Arduino library
-Sketch uses **603432** bytes (28%) of program storage space.
-Memory after connection: Free Heap: **269792**
-
-**As shown: there is nearly a 50% reduction in flash use and approx. 100kB less ram consumed!**
-
-
-# Installation
-**Arduino Library manager:** Go to `sketch` -> `Include Library` -> `Manage Libraries` and search for NimBLE and install.
+# Arduino installation
+**Arduino Library manager:** Go to `sketch` -> `Include Library` -> `Manage Libraries`, search for NimBLE and install.
**Alternatively:** Download as .zip and extract to Arduino/libraries folder, or in Arduino IDE from Sketch menu -> Include library -> Add .Zip library.
`#include "NimBLEDevice.h"` at the beginning of your sketch.
-Tested and working with esp32-arduino in Arduino IDE and platform IO.
-
+# Platformio installation
+* Open platformio.ini, a project configuration file located in the root of PlatformIO project.
+* Add the following line to the lib_deps option of [env:] section:
+```
+h2zero/NimBLE-Arduino@^1.4.0
+```
+* Build a project, PlatformIO will automatically install dependencies.
# Using
-This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
+This library is intended to be compatible with the original ESP32 BLE functions and types with minor changes.
-If you have not used the original Bluedroid library please refer to the [New user guide](docs/New_user_guide.md).
+If you have not used the original Bluedroid library please refer to the [New user guide](docs/New_user_guide.md).
-If you are familiar with the original library, see: [The migration guide](docs/Migration_guide.md) for details about breaking changes and migration.
+If you are familiar with the original library, see: [The migration guide](docs/Migration_guide.md) for details about breaking changes and migration.
Also see [Improvements_and_updates](docs/Improvements_and_updates.md) for information about non-breaking changes.
-[Full API documentation and class list can be found here.](https://h2zero.github.io/esp-nimble-cpp/)
+[Full API documentation and class list can be found here.](https://h2zero.github.io/NimBLE-Arduino/)
For added performance and optimizations see [Usage tips](docs/Usage_tips.md).
@@ -65,21 +52,21 @@ Check the Refactored_original_examples in the examples folder for highlights of
More advanced examples highlighting many available features are in examples/ NimBLE_Server, NimBLE_Client.
-Beacon examples provided by @beegee-tokyo are in examples/ BLE_Beacon_Scanner, BLE_EddystoneTLM_Beacon, BLE_EddystoneURL_Beacon.
+Beacon examples provided by @beegee-tokyo are in examples/ BLE_Beacon_Scanner, BLE_EddystoneTLM_Beacon, BLE_EddystoneURL_Beacon.
-Change the settings in the `src/nimconfig.h` file to customize NimBLE to your project,
-such as increasing max connections, default is 3, absolute maximum connections is 9.
+Change the settings in the `src/nimconfig.h` file to customize NimBLE to your project,
+such as increasing max connections, default is 3, absolute maximum connections is 9.
# Development Status
-This Library is tracking the esp-nimble repo, nimble-1.3.0-idf master branch, currently [@5bb7b40.](https://github.com/espressif/esp-nimble)
+This Library is tracking the esp-nimble repo, nimble-1.4.0-idf branch, currently [@3df0d20.](https://github.com/espressif/esp-nimble)
-Also tracking the NimBLE related changes in ESP-IDF, master branch, currently [@639e7ad.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
+Also tracking the NimBLE related changes in ESP-IDF, master branch, currently [@95db4bb.](https://github.com/espressif/esp-idf/tree/master/components/bt/host/nimble)
# Acknowledgments
* [nkolban](https://github.com/nkolban) and [chegewara](https://github.com/chegewara) for the [original esp32 BLE library](https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils) this project was derived from.
* [beegee-tokyo](https://github.com/beegee-tokyo) for contributing your time to test/debug and contributing the beacon examples.
-* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code.
-
-
+* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code.
+
+
diff --git a/lib/libesp32_div/NimBLE-Arduino/docs/Bluetooth 5 features.md b/lib/libesp32_div/NimBLE-Arduino/docs/Bluetooth 5 features.md
new file mode 100644
index 000000000..3737b0d7e
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/docs/Bluetooth 5 features.md
@@ -0,0 +1,28 @@
+# Bluetooth 5.x features
+
+## About extended advertising
+Extended advertising allows for much more capability and flexibility.
+
+* Allows for 251 bytes of advertisement data and up to 1650 bytes when chained (configuration dependant) vs 31.
+
+* New PHY's (physical layers) that allow for faster data rate (2M PHY) or long range/slower data rates (CODED PHY) as well as the original 1M PHY.
+
+* New periodic advertising, allowing the scanning device to sync with the advertisements of a beacon. This allows for the scanning device to sleep or perform other tasks before the next expected advertisement is sent, preserving cpu cycles and power (To be implemented).
+
+
+## Enabling extended advertising
+Extended advertising is supported when enabled with the config option `CONFIG_BT_NIMBLE_EXT_ADV` set to a value of 1. This is done in menuconfig under `Component config > Bluetooth > NimBLE options > Enable extended advertising`, or set in `nimconfig.h` for Arduino, or in `build_flags` in PlatformIO.
+
+When enabled the following will occur:
+* `NimBLEScan::start` method will scan on both the 1M PHY and the coded PHY standards automatically.
+
+* `NimBLEClient::connect` will use the primary PHY the device is listening on, unless specified (see below).
+
+* `NimBLEClient::setConnectPhy` becomes available to specify the PHY's to connect with (default is all).
+
+* `NimBLEAdvertising` is no longer available for use and is replaced by `NimBLEExtAdvertising`. `NimBLEDevice::getAdvertising` will now return an instance of `NimBLEExtAdvertising`.
+
+* `NimBLEAdvertisementData` is no longer available for use and is replaced by `NimBLEExtAdvertisement`. This new class is where everything about the advertisement is configured, including the advertisement intervals and advertisement ended callback.
+
+
+
diff --git a/lib/libesp32_div/NimBLE-Arduino/docs/Command_line_config.md b/lib/libesp32_div/NimBLE-Arduino/docs/Command_line_config.md
index 3fe4acb3e..f6f6b5ac5 100644
--- a/lib/libesp32_div/NimBLE-Arduino/docs/Command_line_config.md
+++ b/lib/libesp32_div/NimBLE-Arduino/docs/Command_line_config.md
@@ -23,7 +23,7 @@ characteristic or descriptor is constructed before a value is read/notifed.
Increasing this will reduce reallocations but increase memory footprint.
Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
-
+
`CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU`
Sets the default MTU size.
@@ -140,3 +140,41 @@ Set the task stack size for the NimBLE core.
- Default is 4096
+`CONFIG_NIMBLE_STACK_USE_MEM_POOLS`
+
+ Enable the use of memory pools for stack operations. This will use slightly more RAM but may provide more stability.
+
+- Options: 0 or 1, default is disabled (0)
+
+
+### Extended advertising settings, For use with ESP32C3, ESP32S3, ESP32H2 ONLY!
+
+`CONFIG_BT_NIMBLE_EXT_ADV`
+
+Set to 1 to enable extended advertising features.
+
+
+`CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES`
+
+Sets the max number of extended advertising instances
+- Range: 0 - 4
+- Default is 1
+
+
+`CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN`
+
+Set the max extended advertising data size,
+- Range: 31 - 1650
+- Default is 255
+
+
+`CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV`
+
+Set to 1 to enable periodic advertising.
+
+
+`CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS`
+
+Set the maximum number of periodically synced devices.
+- Range: 1 - 8
+- Default is 1
diff --git a/lib/libesp32_div/NimBLE-Arduino/docs/Doxyfile b/lib/libesp32_div/NimBLE-Arduino/docs/Doxyfile
new file mode 100644
index 000000000..54129a191
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/docs/Doxyfile
@@ -0,0 +1,2673 @@
+# Doxyfile 1.9.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = NimBLE-Arduino
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = 1.4.0
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = docs
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION = None
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which efficively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = YES
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if ... \endif and \cond
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
+# The default value is: NO.
+
+WARN_AS_ERROR = FAIL_ON_WARNINGS
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = . \
+ ../src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
+# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl,
+# *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.doc \
+ *.txt \
+ *.py \
+ *.pyw \
+ *.f90 \
+ *.f95 \
+ *.f03 \
+ *.f08 \
+ *.f18 \
+ *.f \
+ *.for \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf \
+ *.ice
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = ./README.md \
+ ./examples \
+ ./CMakelists.txt \
+ ../src/nimconfig_rename.h \
+ ../src/nimble
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+#
+#
+# where is the value of the INPUT_FILTER tag, and is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = index.md
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see:
+# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
+# performance. This can be particularly helpful with template rich C++ code for
+# which doxygen's built-in parser lacks the necessary type information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to
+# YES then doxygen will add the directory of each input to the include path.
+# The default value is: YES.
+
+CLANG_ADD_INC_PATHS = YES
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the directory containing a file called compile_commands.json. This
+# file is the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
+# options used when the source files were built. This is equivalent to
+# specifying the -p option to a clang tool, such as clang-check. These options
+# will then be passed to the parser. Any options specified with CLANG_OPTIONS
+# will be added as well.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see:
+# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use + S
+# (what the is depends on the OS and browser, but it is typically
+# , /, or both). Inside the search box use the to jump into the search results window, the results can be navigated
+# using the . Press to select an item or to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing +. Also here use the
+# to select a filter and or to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = NO
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to Sqlite3 output
+#---------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = _DOXYGEN_ \
+ CONFIG_BT_ENABLED \
+ CONFIG_BT_NIMBLE_ROLE_CENTRAL \
+ CONFIG_BT_NIMBLE_ROLE_OBSERVER \
+ CONFIG_BT_NIMBLE_ROLE_PERIPHERAL \
+ CONFIG_BT_NIMBLE_ROLE_BROADCASTER \
+ CONFIG_BT_NIMBLE_EXT_ADV
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = NO
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc and
+# plantuml temporary files.
+# The default value is: YES.
+
+DOT_CLEANUP = YES
diff --git a/lib/libesp32_div/NimBLE-Arduino/docs/Improvements_and_updates.md b/lib/libesp32_div/NimBLE-Arduino/docs/Improvements_and_updates.md
index c3c11265e..e353f6d17 100644
--- a/lib/libesp32_div/NimBLE-Arduino/docs/Improvements_and_updates.md
+++ b/lib/libesp32_div/NimBLE-Arduino/docs/Improvements_and_updates.md
@@ -1,7 +1,6 @@
# Improvements and updates
-Many improvements have been made to this library vs the original, this is a brief overview of the most significant changes.
-Refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annotated.html) for futher information on class specifics.
+Many improvements have been made to this library vs the original, this is a brief overview of the most significant changes. Refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annotated.html) for further information on class specifics.
* [Server](#server)
* [Advertising](#advertising)
@@ -10,23 +9,26 @@ Refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annot
-# Server
+# Server
-`NimBLECharacteristic::setValue(const T &s)`
-`NimBLEDescriptor::setValue(const T &s)`
+`NimBLEService::NimBLEService::createCharacteristic` takes a 3rd parameter to specify the maximum data size that can be stored by the characteristic. This allows for limiting the RAM use of the characteristic in cases where small amounts of data are expected.
+
-Now use a template to accomodate standard and custom types/values.
+`NimBLECharacteristic::setValue(const T &s)`
+`NimBLEDescriptor::setValue(const T &s)`
+
+Now use the `NimbleAttValue` class and templates to accommodate standard and custom types/values.
**Example**
```
-struct my_struct{
+struct my_struct {
uint8_t one;
uint16_t two;
uint32_t four;
uint64_t eight;
float flt;
-}myStruct;
-
+} myStruct;
+
myStruct.one = 1;
myStruct.two = 2;
myStruct.four = 4;
@@ -34,12 +36,14 @@ struct my_struct{
myStruct.flt = 1234.56;
pCharacteristic->setValue(myStruct);
- ```
-This will send the struct to the recieving client when read or a notification sent.
-`NimBLECharacteristic::getValue` now takes an optional timestamp parameter which will update it's value with
-the time the last value was recieved. In addition an overloaded template has been added to retrieve the value
-as a type specified by the user.
+ // Arduino String support
+ String myString = "Hello";
+ pCharacteristic->setValue(myString);
+ ```
+This will send the struct to the receiving client when read or a notification sent.
+
+`NimBLECharacteristic::getValue` now takes an optional timestamp parameter which will update it's value with the time the last value was received. In addition an overloaded template has been added to retrieve the value as a type specified by the user.
**Example**
```
@@ -48,38 +52,34 @@ as a type specified by the user.
```
-**Advertising will automatically start when a client disconnects.**
+**Advertising will automatically start when a client disconnects.**
A new method `NimBLEServer::advertiseOnDisconnect(bool)` has been implemented to control this, true(default) = enabled.
-`NimBLEServer::removeService` takes an additional parameter `bool deleteSvc` that if true will delete the service
-and all characteristics / descriptors belonging to it and invalidating any pointers to them.
+`NimBLEServer::removeService` takes an additional parameter `bool deleteSvc` that if true will delete the service and all characteristics / descriptors belonging to it and invalidating any pointers to them.
-If false the service is only removed from visibility by clients. The pointers to the service and
-it's characteristics / descriptors will remain valid and the service can be re-added in the future
-using `NimBLEServer::addService`.
+If false the service is only removed from visibility by clients. The pointers to the service and it's characteristics / descriptors will remain valid and the service can be re-added in the future using `NimBLEServer::addService`.
# Advertising
`NimBLEAdvertising::start`
-Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback
-that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
+Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
-This provides an opportunity to update the advertisment data if desired.
+This provides an opportunity to update the advertisement data if desired.
-Also now returns a bool value to indicate if advertising successfully started or not.
-
+Also now returns a bool value to indicate if advertising successfully started or not.
+
-# Client
+# Client
-`NimBLERemoteCharacteristic::readValue(time_t\*, bool)`
-`NimBLERemoteDescriptor::readValue(bool)`
+`NimBLERemoteCharacteristic::readValue(time_t\*, bool)`
+`NimBLERemoteDescriptor::readValue(bool)`
-Have been added as templates to allow reading the values as any specified type.
+Have been added as templates to allow reading the values as any specified type.
**Example**
```
@@ -93,56 +93,56 @@ struct my_struct{
time_t timestamp;
myStruct = pRemoteCharacteristic->readValue(×tamp); // timestamp optional
-```
+```
-`NimBLERemoteCharacteristic::registerForNotify`
-Has been **deprecated** as now the internally stored characteristic value is updated when notification/indication is recieved.
+`NimBLERemoteCharacteristic::registerForNotify`
+Has been **deprecated** as now the internally stored characteristic value is updated when notification/indication is received.
-`NimBLERemoteCharacteristic::subscribe` and `NimBLERemoteCharacteristic::unsubscribe` have been implemented to replace it.
-A callback is no longer requred to get the most recent value unless timing is important. Instead, the application can call `NimBLERemoteCharacteristic::getValue` to
-get the last updated value any time.
-
+`NimBLERemoteCharacteristic::subscribe` and `NimBLERemoteCharacteristic::unsubscribe` have been implemented to replace it.
+A callback is no longer required to get the most recent value unless timing is important. Instead, the application can call `NimBLERemoteCharacteristic::getValue` to get the last updated value any time.
+
-The `notifiy_callback` function is now defined as a `std::function` to take advantage of using `std::bind` to specifiy a class member function for the callback.
+The `notify_callback` function is now defined as a `std::function` to take advantage of using `std::bind` to specify a class member function for the callback.
-Example:
+Example:
```
using namespace std::placeholders;
notify_callback callback = std::bind(&::, this, _1, _2, _3, _4);
+
->subscribe(true, callback);
```
-`NimBLERemoteCharacteristic::readValue` and `NimBLERemoteCharacteristic::getValue` take an optional timestamp parameter which will update it's value with
-the time the last value was recieved.
+`NimBLERemoteCharacteristic::readValue` and `NimBLERemoteCharacteristic::getValue` take an optional timestamp parameter which will update it's value with
+the time the last value was received.
> NimBLEClient::getService
> NimBLERemoteService::getCharacteristic
-> NimBLERemoteCharacteristic::getDescriptor
+> NimBLERemoteCharacteristic::getDescriptor
-These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only)
-the specified attribute from the peripheral.
+These methods will now check the respective vectors for the attribute object and, if not found, will retrieve (only)
+the specified attribute from the peripheral.
-These changes allow more control for the user to manage the resources used for the attributes.
+These changes allow more control for the user to manage the resources used for the attributes.
-`NimBLEClient::connect()` can now be called without an address or advertised device parameter. This will connect to the
-device with the address previously set when last connected or set with `NimBLEDevice::setPeerAddress()`.
+`NimBLEClient::connect()` can now be called without an address or advertised device parameter. This will connect to the device with the address previously set when last connected or set with `NimBLEDevice::setPeerAddress()`.
-# General
-To reduce resource use all instances of `std::map` have been replaced with `std::vector`.
+# General
+To reduce resource use all instances of `std::map` have been replaced with `std::vector`.
-Use of `FreeRTOS::Semaphore` has been removed as it was consuming too much ram, the related files have been left in place to accomodate application use.
+Use of `FreeRTOS::Semaphore` has been removed as it was consuming too much ram, the related files have been left in place to accomodate application use.
-Operators `==`, `!=` and `std::string` have been added to `NimBLEAddress` and `NimBLEUUID` for easier comparison and logging.
+Operators `==`, `!=` and `std::string` have been added to `NimBLEAddress` and `NimBLEUUID` for easier comparison and logging.
-New constructor for `NimBLEUUID(uint32_t, uint16_t, uint16_t, uint64_t)` added to lower memory use vs string construction. See: [#21](https://github.com/h2zero/NimBLE-Arduino/pull/21).
+New constructor for `NimBLEUUID(uint32_t, uint16_t, uint16_t, uint64_t)` added to lower memory use vs string construction. See: [#21](https://github.com/h2zero/NimBLE-Arduino/pull/21).
-Security/pairing operations are now handled in the respective `NimBLEClientCallbacks` and `NimBLEServerCallbacks` classes, `NimBLESecurity`(deprecated) remains for backward compatibility.
+Security/pairing operations are now handled in the respective `NimBLEClientCallbacks` and `NimBLEServerCallbacks` classes, `NimBLESecurity`(deprecated) remains for backward compatibility.
-Configuration options have been added to add or remove debugging information, when disabled (default) significatly reduces binary size.
+Configuration options have been added to add or remove debugging information, when disabled (default) significantly reduces binary size.
In ESP-IDF the options are in menuconfig: `Main menu -> ESP-NimBLE-cpp configuration`.
-For Arduino the options must be commented / uncommented in nimconfig.h.
-
+For Arduino the options must be commented / uncommented in nimconfig.h.
+
+Characteristics and descriptors now use the `NimBLEAttValue` class to store their data. This is a polymorphic container class capable of converting to/from many different types efficiently. See: [#286](https://github.com/h2zero/NimBLE-Arduino/pull/286)
diff --git a/lib/libesp32_div/NimBLE-Arduino/docs/Migration_guide.md b/lib/libesp32_div/NimBLE-Arduino/docs/Migration_guide.md
index 62406c622..2ddc1b3c6 100644
--- a/lib/libesp32_div/NimBLE-Arduino/docs/Migration_guide.md
+++ b/lib/libesp32_div/NimBLE-Arduino/docs/Migration_guide.md
@@ -1,10 +1,10 @@
# Migrating from Bluedroid to NimBLE
-This guide describes the required changes to existing projects migrating from the original bluedroid API to NimBLE.
+This guide describes the required changes to existing projects migrating from the original bluedroid API to NimBLE.
-**The changes listed here are only the required changes that must be made**, and a short overview of options for migrating existing applications.
+**The changes listed here are only the required changes that must be made**, and a short overview of options for migrating existing applications.
-For more information on the improvements and additions please refer to the [class documentation](https://h2zero.github.io/esp-nimble-cpp/annotated.html) and [Improvements and updates](Improvements_and_updates.md)
+For more information on the improvements and additions please refer to the [class documentation](https://h2zero.github.io/NimBLE-Arduino/annotated.html) and [Improvements and updates](Improvements_and_updates.md)
* [General Changes](#general-information)
* [Server](#server-api)
@@ -19,82 +19,78 @@ For more information on the improvements and additions please refer to the [clas
* [Security](#client-security)
* [General Security](#security-api)
* [Configuration](#arduino-configuration)
-
+
## General Information
### Header Files
-All classes are accessible by including `NimBLEDevice.h` in your application, no further headers need to be included.
+All classes are accessible by including `NimBLEDevice.h` in your application, no further headers need to be included.
-(Mainly for Arduino) You may choose to include `NimBLELog.h` in your appplication if you want to use the `NIMBLE_LOGx` macros for debugging.
-These macros are used the same way as the `ESP_LOGx` macros.
+(Mainly for Arduino) You may choose to include `NimBLELog.h` in your application if you want to use the `NIMBLE_LOGx` macros for debugging. These macros are used the same way as the `ESP_LOGx` macros.
### Class Names
-Class names remain the same as the original with the addition of a "Nim" prefix.
-For example `BLEDevice` is now `NimBLEDevice` and `BLEServer` is now `NimBLEServer` etc.
+Class names remain the same as the original with the addition of a "Nim" prefix.
+For example `BLEDevice` is now `NimBLEDevice` and `BLEServer` is now `NimBLEServer` etc.
-For convienience definitions have been added to allow applications to use either name for all classes
-this means **no class names need to be changed in existing code** and makes migrating easier.
+For convenience definitions have been added to allow applications to use either name for all classes this means **no class names need to be changed in existing code** and makes migrating easier.
### BLE Addresses
-`BLEAddress` (`NimBLEAddress`) When constructing an address the constructor now takes an *(optional)* `uint8_t type` paramameter
-to specify the address type. Default is (0) Public static address.
+`BLEAddress` (`NimBLEAddress`) When constructing an address the constructor now takes an *(optional)* `uint8_t type` parameter to specify the address type. Default is (0) Public static address.
-For example `BLEAddress addr(11:22:33:44:55:66, 1)` will create the address object with an address type of: 1 (Random).
+For example `BLEAddress addr(11:22:33:44:55:66, 1)` will create the address object with an address type of: 1 (Random).
-As this paramameter is optional no changes to existing code are needed, it is mentioned here for information.
-
-`BLEAddress::getNative` (`NimBLEAddress::getNative`) returns a uint8_t pointer to the native address byte array.
-In this library the address bytes are stored in reverse order from the original library. This is due to the way
-the NimBLE stack expects addresses to be presented to it. All other functions such as `toString` are
-not affected as the endian change is made within them.
+As this parameter is optional no changes to existing code are needed, it is mentioned here for information.
+
+`BLEAddress::getNative` (`NimBLEAddress::getNative`) returns a uint8_t pointer to the native address byte array. In this library the address bytes are stored in reverse order from the original library. This is due to the way the NimBLE stack expects addresses to be presented to it. All other functions such as `toString` are
+not affected as the endian change is made within them.
## Server API
Creating a `BLEServer` instance is the same as original, no changes required.
-For example `BLEDevice::createServer()` will work just as it did before.
+For example `BLEDevice::createServer()` will work just as it did before.
-`BLEServerCallbacks` (`NimBLEServerCallbacks`) has new methods for handling security operations.
-**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
+`BLEServerCallbacks` (`NimBLEServerCallbacks`) has new methods for handling security operations.
+**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
### Services
-Creating a `BLEService` (`NimBLEService`) instance is the same as original, no changes required.
-For example `BLEServer::createService(SERVICE_UUID)` will work just as it did before.
+Creating a `BLEService` (`NimBLEService`) instance is the same as original, no changes required.
+For example `BLEServer::createService(SERVICE_UUID)` will work just as it did before.
### Characteristics
-`BLEService::createCharacteristic` (`NimBLEService::createCharacteristic`) is used the same way as originally except the properties parameter has changed.
+`BLEService::createCharacteristic` (`NimBLEService::createCharacteristic`) is used the same way as originally except the properties parameter has changed.
When creating a characteristic the properties are now set with `NIMBLE_PROPERTY::XXXX` instead of `BLECharacteristic::XXXX`.
#### Originally
-> BLECharacteristic::PROPERTY_READ |
-> BLECharacteristic::PROPERTY_WRITE
+> BLECharacteristic::PROPERTY_READ |
+> BLECharacteristic::PROPERTY_WRITE
#### Is Now
-> NIMBLE_PROPERTY::READ |
-> NIMBLE_PROPERTY::WRITE
+> NIMBLE_PROPERTY::READ |
+> NIMBLE_PROPERTY::WRITE
#### The full list of properties
-> NIMBLE_PROPERTY::READ
-> NIMBLE_PROPERTY::READ_ENC
-> NIMBLE_PROPERTY::READ_AUTHEN
-> NIMBLE_PROPERTY::READ_AUTHOR
-> NIMBLE_PROPERTY::WRITE
-> NIMBLE_PROPERTY::WRITE_NR
-> NIMBLE_PROPERTY::WRITE_ENC
-> NIMBLE_PROPERTY::WRITE_AUTHEN
-> NIMBLE_PROPERTY::WRITE_AUTHOR
-> NIMBLE_PROPERTY::BROADCAST
-> NIMBLE_PROPERTY::NOTIFY
-> NIMBLE_PROPERTY::INDICATE
+> NIMBLE_PROPERTY::READ
+> NIMBLE_PROPERTY::READ_ENC
+> NIMBLE_PROPERTY::READ_AUTHEN
+> NIMBLE_PROPERTY::READ_AUTHOR
+> NIMBLE_PROPERTY::WRITE
+> NIMBLE_PROPERTY::WRITE_NR
+> NIMBLE_PROPERTY::WRITE_ENC
+> NIMBLE_PROPERTY::WRITE_AUTHEN
+> NIMBLE_PROPERTY::WRITE_AUTHOR
+> NIMBLE_PROPERTY::BROADCAST
+> NIMBLE_PROPERTY::NOTIFY
+> NIMBLE_PROPERTY::INDICATE
+
**Example:**
@@ -102,7 +98,7 @@ When creating a characteristic the properties are now set with `NIMBLE_PROPERTY:
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
- BLECharacteristic::PROPERTY_WRITE
+ BLECharacteristic::PROPERTY_WRITE
);
```
@@ -111,23 +107,22 @@ Needs to be changed to:
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
NIMBLE_PROPERTY::READ |
- NIMBLE_PROPERTY::WRITE
+ NIMBLE_PROPERTY::WRITE
);
```
-`BLECharacteristicCallbacks` (`NimBLECharacteristicCallbacks`) has a new method `NimBLECharacteristicCallbacks::onSubscribe`
-which is called when a client subscribes to notifications/indications.
+`BLECharacteristicCallbacks` (`NimBLECharacteristicCallbacks`) has a new method `NimBLECharacteristicCallbacks::onSubscribe` which is called when a client subscribes to notifications/indications.
-**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
+**Note:** All callback methods have default implementations which allows the application to implement only the methods applicable.
-> BLECharacteristic::getData
+> BLECharacteristic::getData
-**Has been removed from the API.**
-Originally this returned a `uint8_t*` to the internal data, which is volatile.
-To prevent possibly throwing exceptions this has been removed and `NimBLECharacteristic::getValue` should be used
-to get a copy of the data first which can then safely be accessed via pointer.
+**Has been removed from the API.**
+Originally this returned a `uint8_t*` to the internal data, which is volatile.
+To prevent possibly throwing exceptions this has been removed and `NimBLECharacteristic::getValue` should be used
+to get a copy of the data first which can then safely be accessed via pointer.
**Example:**
```
@@ -142,48 +137,47 @@ my_struct_t myStruct = pChr->getValue();
### Descriptors
-The previous method `BLECharacteristic::addDescriptor()` has been removed.
Descriptors are now created using the `NimBLECharacteristic::createDescriptor` method.
-
-BLE2902 or NimBLE2902 class has been removed.
-NimBLE automatically creates the 0x2902 descriptor if a characteristic has a notification or indication property assigned to it.
-It was no longer useful to have a class for the 0x2902 descriptor as a new callback `NimBLECharacteristicCallbacks::onSubscribe` was added
-to handle callback functionality and the client subscription status is handled internally.
+BLE2902 or NimBLE2902 class has been removed.
+NimBLE automatically creates the 0x2902 descriptor if a characteristic has a notification or indication property assigned to it.
-**Note:** Attempting to create a 0x2902 descriptor will trigger an assert to notify the error,
+It was no longer useful to have a class for the 0x2902 descriptor as a new callback `NimBLECharacteristicCallbacks::onSubscribe` was added
+to handle callback functionality and the client subscription status is handled internally.
+
+**Note:** Attempting to create a 0x2902 descriptor will trigger an assert to notify the error,
allowing the creation of it would cause a fault in the NimBLE stack.
-All other descriptors are now created just as characteristics are by using the `NimBLECharacteristic::createDescriptor` method (except 0x2904, see below).
+All other descriptors are now created just as characteristics are by using the `NimBLECharacteristic::createDescriptor` method (except 0x2904, see below).
Which are defined as:
```
NimBLEDescriptor* createDescriptor(const char* uuid,
- uint32_t properties =
+ uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = 100);
-
+
NimBLEDescriptor* createDescriptor(NimBLEUUID uuid,
- uint32_t properties =
+ uint32_t properties =
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE,
uint16_t max_len = 100);
```
##### Example
```
-pDescriptor = pCharacteristic->createDescriptor("ABCD",
- NIMBLE_PROPERTY::READ |
+pDescriptor = pCharacteristic->createDescriptor("ABCD",
+ NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE |
NIMBLE_PROPERTY::WRITE_ENC,
25);
```
-Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes.
+Would create a descriptor with the UUID 0xABCD, publicly readable but only writable if paired/bonded (encrypted) and has a max value length of 25 bytes.
For the 0x2904, there is a special class that is created when you call `createDescriptor("2904").
-The pointer returned is of the base class `NimBLEDescriptor` but the call will create the derived class of `NimBLE2904` so you must cast the returned pointer to
+The pointer returned is of the base class `NimBLEDescriptor` but the call will create the derived class of `NimBLE2904` so you must cast the returned pointer to
`NimBLE2904` to access the specific class methods.
##### Example
@@ -195,127 +189,115 @@ p2904 = (NimBLE2904*)pCharacteristic->createDescriptor("2904");
### Server Security
Security is set on the characteristic or descriptor properties by applying one of the following:
-> NIMBLE_PROPERTY::READ_ENC
-> NIMBLE_PROPERTY::READ_AUTHEN
-> NIMBLE_PROPERTY::READ_AUTHOR
-> NIMBLE_PROPERTY::WRITE_ENC
-> NIMBLE_PROPERTY::WRITE_AUTHEN
-> NIMBLE_PROPERTY::WRITE_AUTHOR
+> NIMBLE_PROPERTY::READ_ENC
+> NIMBLE_PROPERTY::READ_AUTHEN
+> NIMBLE_PROPERTY::READ_AUTHOR
+> NIMBLE_PROPERTY::WRITE_ENC
+> NIMBLE_PROPERTY::WRITE_AUTHEN
+> NIMBLE_PROPERTY::WRITE_AUTHOR
-When a peer wants to read or write a characteristic or descriptor with any of these properties applied
-it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
-This can be changed to use passkey authentication or numeric comparison. See [Security API](#security-api) for details.
+
+
+When a peer wants to read or write a characteristic or descriptor with any of these properties applied it will trigger the pairing process. By default the "just-works" pairing will be performed automatically.
+
+This can be changed to use passkey authentication or numeric comparison. See [Security API](#security-api) for details.
## Advertising API
-Advertising works the same as the original API except:
-> BLEAdvertising::setMinPreferred
-> BLEAdvertising::setMaxPreferred
+Advertising works the same as the original API except:
-These methods were found to not provide useful functionality and consumed valuable advertising space (6 bytes of 31) if used unknowingly.
-If you wish to advertise these parameters you can still do so manually via `BLEAdvertisementData::addData` (`NimBLEAdvertisementData::addData`).
-
-
-Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
-`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
-
-~~Calling `NimBLEAdvertising::setScanResponseData` without also calling `NimBLEAdvertising::setAdvertisementData` will have no effect.
-When using custom scan response data you must also use custom advertisement data.~~
-No longer true as of release 1.2.0 and above, custom scan response is now supported without custom advertisement data.
+Calling `NimBLEAdvertising::setAdvertisementData` will entirely replace any data set with `NimBLEAdvertising::addServiceUUID`, or
+`NimBLEAdvertising::setAppearance` or similar methods. You should set all the data you wish to advertise within the `NimBLEAdvertisementData` instead.
> BLEAdvertising::start (NimBLEAdvertising::start)
-Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback
-that is invoked when advertsing ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
-
-This provides an opportunity to update the advertisment data if desired.
+Now takes 2 optional parameters, the first is the duration to advertise for (in seconds), the second is a callback that is invoked when advertising ends and takes a pointer to a `NimBLEAdvertising` object (similar to the `NimBLEScan::start` API).
+This provides an opportunity to update the advertisement data if desired.
## Client API
-Client instances are created just as before with `BLEDevice::createClient` (`NimBLEDevice::createClient`).
+Client instances are created just as before with `BLEDevice::createClient` (`NimBLEDevice::createClient`).
-Multiple client instances can be created, up to the maximum number of connections set in the config file (default: 3).
-To delete a client instance you must use `NimBLEDevice::deleteClient`.
+Multiple client instances can be created, up to the maximum number of connections set in the config file (default: 3). To delete a client instance you must use `NimBLEDevice::deleteClient`.
-`BLEClient::connect`(`NimBLEClient::connect`) Has had it's parameters altered.
+`BLEClient::connect`(`NimBLEClient::connect`) Has had it's parameters altered.
Defined as:
-> NimBLEClient::connect(bool deleteServices = true);
-> NimBLEClient::connect(NimBLEAdvertisedDevice\* device, bool deleteServices = true);
-> NimBLEClient::connect(NimBLEAddress address, bool deleteServices = true);
+> NimBLEClient::connect(bool deleteServices = true);
+> NimBLEClient::connect(NimBLEAdvertisedDevice\* device, bool deleteServices = true);
+> NimBLEClient::connect(NimBLEAddress address, bool deleteServices = true);
-The type parameter has been removed and a new bool parameter has been added to indicate if the client should
-delete the attribute database previously retrieved (if applicable) for the peripheral, default value is true.
-If set to false the client will use the attribute database it retrieved from the peripheral when previously connected.
-This allows for faster connections and power saving if the devices dropped connection and are reconnecting.
+The type parameter has been removed and a new bool parameter has been added to indicate if the client should delete the attribute database previously retrieved (if applicable) for the peripheral, default value is true.
+
+If set to false the client will use the attribute database it retrieved from the peripheral when previously connected.
+
+This allows for faster connections and power saving if the devices dropped connection and are reconnecting.
-> `BLEClient::getServices` (`NimBLEClient::getServices`)
+> `BLEClient::getServices` (`NimBLEClient::getServices`)
-This method now takes an optional (bool) parameter to indicate if the services should be retrieved from the server (true) or
-the currently known database returned (false : default).
-Also now returns a pointer to `std::vector` instead of `std::map`.
+This method now takes an optional (bool) parameter to indicate if the services should be retrieved from the server (true) or the currently known database returned (false : default).
+Also now returns a pointer to `std::vector` instead of `std::map`.
-**Removed:** the automatic discovery of all peripheral attributes as they consumed time and resources for data
-the user may not be interested in.
-
-**Added:** `NimBLEClient::discoverAttributes` for the user to discover all the peripheral attributes
-to replace the the removed automatic functionality.
+**Removed:** the automatic discovery of all peripheral attributes as they consumed time and resources for data the user may not be interested in.
+
+**Added:** `NimBLEClient::discoverAttributes` for the user to discover all the peripheral attributes to replace the the removed automatic functionality.
### Remote Services
-`BLERemoteService` (`NimBLERemoteService`) Methods remain mostly unchanged with the exceptions of:
+`BLERemoteService` (`NimBLERemoteService`) Methods remain mostly unchanged with the exceptions of:
> BLERemoteService::getCharacteristicsByHandle
-This method has been removed.
+This method has been removed.
-> `BLERemoteService::getCharacteristics` (`NimBLERemoteService::getCharacteristics`)
+> `BLERemoteService::getCharacteristics` (`NimBLERemoteService::getCharacteristics`)
-This method now takes an optional (bool) parameter to indicate if the characteristics should be retrieved from the server (true) or
-the currently known database returned (false : default).
-Also now returns a pointer to `std::vector` instead of `std::map`.
+This method now takes an optional (bool) parameter to indicate if the characteristics should be retrieved from the server (true) or
+the currently known database returned (false : default).
+Also now returns a pointer to `std::vector` instead of `std::map`.
### Remote Characteristics
-`BLERemoteCharacteristic` (`NimBLERemoteCharacteristic`) There have been a few changes to the methods in this class:
+`BLERemoteCharacteristic` (`NimBLERemoteCharacteristic`)
+ There have been a few changes to the methods in this class:
-> `BLERemoteCharacteristic::writeValue` (`NimBLERemoteCharacteristic::writeValue`)
-> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
+> `BLERemoteCharacteristic::writeValue` (`NimBLERemoteCharacteristic::writeValue`)
+> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
-Now return true or false to indicate success or failure so you can choose to disconnect or try again.
+Now return true or false to indicate success or failure so you can choose to disconnect or try again.
-> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
+> `BLERemoteCharacteristic::registerForNotify` (`NimBLERemoteCharacteristic::registerForNotify`)
-Is now **deprecated**.
-> `NimBLERemoteCharacteristic::subscribe`
-> `NimBLERemoteCharacteristic::unsubscribe`
+Is now **deprecated**.
+> `NimBLERemoteCharacteristic::subscribe`
+> `NimBLERemoteCharacteristic::unsubscribe`
-Are the new methods added to replace it.
+Are the new methods added to replace it.
-> `BLERemoteCharacteristic::readUInt8` (`NimBLERemoteCharacteristic::readUInt8`)
-> `BLERemoteCharacteristic::readUInt16` (`NimBLERemoteCharacteristic::readUInt16`)
-> `BLERemoteCharacteristic::readUInt32` (`NimBLERemoteCharacteristic::readUInt32`)
-> `BLERemoteCharacteristic::readFloat` (`NimBLERemoteCharacteristic::readFloat`)
+> `BLERemoteCharacteristic::readUInt8` (`NimBLERemoteCharacteristic::readUInt8`)
+> `BLERemoteCharacteristic::readUInt16` (`NimBLERemoteCharacteristic::readUInt16`)
+> `BLERemoteCharacteristic::readUInt32` (`NimBLERemoteCharacteristic::readUInt32`)
+> `BLERemoteCharacteristic::readFloat` (`NimBLERemoteCharacteristic::readFloat`)
-Are **deprecated** a template: NimBLERemoteCharacteristic::readValue(time_t\*, bool) has been added to replace them.
+Are **deprecated** a template: `NimBLERemoteCharacteristic::readValue(time_t\*, bool)` has been added to replace them.
-> `BLERemoteCharacteristic::readRawData`
+> `BLERemoteCharacteristic::readRawData`
-**Has been removed from the API**
-Originally it stored an unnecessary copy of the data and was returning a `uint8_t` pointer to volatile internal data.
-The user application should use `NimBLERemoteCharacteristic::readValue` or `NimBLERemoteCharacteristic::getValue`.
-To obatain a copy of the data, then cast the returned std::string to the type required such as:
+**Has been removed from the API**
+Originally it stored an unnecessary copy of the data and was returning a `uint8_t` pointer to volatile internal data.
+The user application should use `NimBLERemoteCharacteristic::readValue` or `NimBLERemoteCharacteristic::getValue`.
+To obtain a copy of the data, then cast the returned std::string to the type required such as:
```
std::string value = pChr->readValue();
uint8_t *data = (uint8_t*)value.data();
@@ -325,75 +307,73 @@ Alternatively use the `readValue` template:
my_struct_t myStruct = pChr->readValue();
```
-
-> `BLERemoteCharacteristic::getDescriptors` (`NimBLERemoteCharacteristic::getDescriptors`)
-This method now takes an optional (bool) parameter to indicate if the descriptors should be retrieved from the server (true) or
-the currently known database returned (false : default).
-Also now returns a pointer to `std::vector` instead of `std::map`.
+> `BLERemoteCharacteristic::getDescriptors` (`NimBLERemoteCharacteristic::getDescriptors`)
+
+This method now takes an optional (bool) parameter to indicate if the descriptors should be retrieved from the server (true) or
+the currently known database returned (false : default).
+Also now returns a pointer to `std::vector` instead of `std::map`.
### Client Security
-The client will automatically initiate security when the peripheral responds that it's required.
-The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
+The client will automatically initiate security when the peripheral responds that it's required.
+The default configuration will use "just-works" pairing with no bonding, if you wish to enable bonding see below.
## Security API
Security operations have been moved to `BLEDevice` (`NimBLEDevice`).
-Also security callback methods are now incorporated in the `NimBLEServerCallbacks` / `NimBLEClientCallbacks` classes.
-However backward compatibility with the original `BLESecurity` (`NimBLESecurity`) class is retained to minimize application code changes.
+Also security callback methods are now incorporated in the `NimBLEServerCallbacks` / `NimBLEClientCallbacks` classes.
+However backward compatibility with the original `BLESecurity` (`NimBLESecurity`) class is retained to minimize application code changes.
The callback methods are:
-> `bool onConfirmPIN(uint32_t pin)`
+> `bool onConfirmPIN(uint32_t pin)`
-Receives the pin when using numeric comparison authentication, `return true;` to accept.
+Receives the pin when using numeric comparison authentication, `return true;` to accept.
-> `uint32_t onPassKeyRequest()`
+> `uint32_t onPassKeyRequest()`
-For server callback; return the passkey expected from the client.
-For client callback; return the passkey to send to the server.
+For server callback; return the passkey expected from the client.
+For client callback; return the passkey to send to the server.
-> `void onAuthenticationComplete(ble_gap_conn_desc\* desc)`
+> `void onAuthenticationComplete(ble_gap_conn_desc\* desc)`
-Authentication complete, success or failed information is in `desc`.
+Authentication complete, success or failed information is in `desc`.
Security settings and IO capabilities are now set by the following methods of NimBLEDevice.
-> `NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc)`
-> `NimBLEDevice::setSecurityAuth(uint8_t auth_req)`
+> `NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc)`
+> `NimBLEDevice::setSecurityAuth(uint8_t auth_req)`
-Sets the authorization mode for this device.
+Sets the authorization mode for this device.
-> `NimBLEDevice::setSecurityIOCap(uint8_t iocap)`
+> `NimBLEDevice::setSecurityIOCap(uint8_t iocap)`
-Sets the Input/Output capabilities of this device.
+Sets the Input/Output capabilities of this device.
-> `NimBLEDevice::setSecurityInitKey(uint8_t init_key)`
+> `NimBLEDevice::setSecurityInitKey(uint8_t init_key)`
-If we are the initiator of the security procedure this sets the keys we will distribute.
+If we are the initiator of the security procedure this sets the keys we will distribute.
-> `NimBLEDevice::setSecurityRespKey(uint8_t resp_key)`
+> `NimBLEDevice::setSecurityRespKey(uint8_t resp_key)`
-Sets the keys we are willing to accept from the peer during pairing.
+Sets the keys we are willing to accept from the peer during pairing.
## Arduino Configuration
-Unlike the original library pre-packaged in the esp32-arduino, this library has all the configuration
-options that are normally set in menuconfig available in the *src/nimconfig.h* file.
+Unlike the original library pre-packaged in the esp32-arduino, this library has all the configuration options that are normally set in menuconfig available in the *src/nimconfig.h* file.
-This allows Arduino users to fully customize the build, such as increasing max connections
-or loading the BLE stack into external PSRAM.
+This allows Arduino users to fully customize the build, such as increasing max connections or loading the BLE stack into external PSRAM.
-For details on the options, they are fully commented in *nimconfig.h*
+For details on the options, they are fully commented in *nimconfig.h*
diff --git a/lib/libesp32_div/NimBLE-Arduino/docs/New_user_guide.md b/lib/libesp32_div/NimBLE-Arduino/docs/New_user_guide.md
index 9f0eeee7d..ce02efe7e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/docs/New_user_guide.md
+++ b/lib/libesp32_div/NimBLE-Arduino/docs/New_user_guide.md
@@ -23,7 +23,7 @@ This can be called any time you wish to use BLE functions and does not need to b
## Creating a Server
-BLE servers perform 2 tasks, they advertise their existance for clients to find them and they provide services which contain information for the connecting client.
+BLE servers perform 2 tasks, they advertise their existence for clients to find them and they provide services which contain information for the connecting client.
After initializing the NimBLE stack we create a server by calling `NimBLEDevice::createServer()`, this will create a server instance and return a pointer to it.
@@ -91,7 +91,7 @@ void app_main(void)
}
```
-All that's left to do now is start the sevice, give the characteristic a value and start advertising for clients.
+All that's left to do now is start the service, give the characteristic a value and start advertising for clients.
Fist we start the service by calling `NimBLEService::start()`.
@@ -214,7 +214,7 @@ for(int i = 0; i < results.getCount(); i++) {
}
}
```
-As shown, the call to `NimBLEClient::connect` should have it's eturn value tested to make sure it succeeded before proceeding to get data.
+As shown, the call to `NimBLEClient::connect` should have it's return value tested to make sure it succeeded before proceeding to get data.
Next we need to access the servers data by asking it for the service and the characteristic we are interested in, then read the characteristic value.
@@ -222,7 +222,7 @@ Next we need to access the servers data by asking it for the service and the cha
To do this we call `NimBLEClient::getService`, which takes as a parameter the UUID of the service and returns
a pointer an instance to `NimBLERemoteService` or `nullptr` if the service was not found.
-Next we will call `NimBLERemoteService::getCharateristic` which takes as a parameter the UUID of the service and returns
+Next we will call `NimBLERemoteService::getCharacteristic` which takes as a parameter the UUID of the service and returns
a pointer to an instance of `NimBLERemoteCharacteristic` or `nullptr` if not found.
Finally we will read the characteristic value with `NimBLERemoteCharacteristic::readValue()`.
diff --git a/lib/libesp32_div/NimBLE-Arduino/docs/Usage_tips.md b/lib/libesp32_div/NimBLE-Arduino/docs/Usage_tips.md
index b8edde2de..8a60ef241 100644
--- a/lib/libesp32_div/NimBLE-Arduino/docs/Usage_tips.md
+++ b/lib/libesp32_div/NimBLE-Arduino/docs/Usage_tips.md
@@ -2,7 +2,7 @@
## Put BLE functions in a task running on the NimBLE stack core
-When commands are sent to the stack from a differnt core they can experience delays in execution.
+When commands are sent to the stack from a different core they can experience delays in execution.
This library detects this and invokes the esp32 IPC to reroute these commands through the correct core but this also increases overhead.
Therefore it is highly recommended to create tasks for BLE to run on the same core, the macro `CONFIG_BT_NIMBLE_PINNED_TO_CORE` can be used to set the core.
@@ -13,12 +13,12 @@ When a client instance has been created and has connected to a peer device and i
If you are periodically connecting to the same devices and you have deleted the client instance or the services when connecting again it will cause a retrieval of that information from the peer again.
This results in significant energy drain on the battery of the devices, fragments heap, and reduces connection performance.
-Client instances in this library use approximately 20% of the original bluedroid library, deleteing them will provide much less gain than it did before.
+Client instances in this library use approximately 20% of the original bluedroid library, deleting them will provide much less gain than it did before.
It is recommended to retain the client instance in cases where the time between connecting to the same device is less than 5 minutes.
-## Only retrieve the services and characteriscs needed
+## Only retrieve the services and characteristics needed
As a client the use of `NimBLEClient::getServices` or `NimBLERemoteService::getCharacteristics` and using `true` for the parameter should be limited to devices that are not known.
Instead `NimBLEClient::getService(NimBLEUUID)` or `NimBLERemoteService::getCharacteristic(NimBLEUUID)` should be used to access certain attributes that are useful to the application.
diff --git a/lib/libesp32_div/NimBLE-Arduino/docs/index.md b/lib/libesp32_div/NimBLE-Arduino/docs/index.md
new file mode 100644
index 000000000..2f1af75a2
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/docs/index.md
@@ -0,0 +1,70 @@
+# Overview
+
+This is a C++ BLE library for Espressif ESP32 and Nordic nRF51/nRF52 devices that uses the NimBLE BLE stack.
+The aim is to maintain, as much as reasonable, the original ESP32 Arduino BLE API by while adding new features and making improvements in performance, resource use, and stability.
+
+
+# What is NimBLE?
+NimBLE is a completely open source Bluetooth Low Energy stack produced by [Apache](https://github.com/apache/mynewt-nimble).
+
+
+# Arduino installation
+**NOTE:** Nordic devices require using [n-able arduino core](https://github.com/h2zero/n-able-Arduino)
+
+**Arduino Library manager:** Go to `sketch` -> `Include Library` -> `Manage Libraries` and search for NimBLE and install.
+
+**Alternatively:** Download as .zip and extract to Arduino/libraries folder, or in Arduino IDE from Sketch menu -> Include library -> Add .Zip library.
+
+`#include "NimBLEDevice.h"` at the beginning of your sketch.
+
+Call `NimBLEDevice::init` in `setup`.
+
+
+# Platformio installation
+* Open platformio.ini, a project configuration file located in the root of PlatformIO project.
+* Add the following line to the lib_deps option of [env:] section:
+```
+h2zero/NimBLE-Arduino@^1.4.0
+```
+* Build a project, PlatformIO will automatically install dependencies.
+
+
+# Using
+This library is intended to be compatible with the original ESP32 BLE library functions and types with minor changes.
+
+If you have not used the original BLE library please refer to the [New user guide](New_user_guide.md).
+
+If you are familiar with the original library, see: [The migration guide](Migration_guide.md) for details.
+
+Also see [Improvements and updates](Improvements_and_updates.md) for information about non-breaking changes.
+
+For more advanced usage see [Usage tips](Usage_tips.md) for more performance and optimization.
+
+
+## Examples
+See the Refactored_original_examples in the examples folder for highlights of the differences with the original library.
+
+More advanced examples highlighting many available features are in examples/NimBLE_Server, NimBLE_Client.
+
+Beacon examples provided by [beegee-tokyo](https://github.com/beegee-tokyo) are in examples/BLE_Beacon_Scanner, BLE_EddystoneTLM_Beacon, BLE_EddystoneURL_Beacon.
+
+Change the settings in the nimconfig.h file to customize NimBLE to your project, such as increasing max connections (default is 3).
+
+
+## Arduino command line and platformio
+As an alternative to changing the configuration in nimconfig.h, Arduino command line and platformio.ini options are available.
+
+See the command line configuration options available in [Command line config](Command_line_config.md).
+
+
+# Need help? Have a question or suggestion?
+Come chat on [gitter](https://gitter.im/NimBLE-Arduino/community?utm_source=share-link&utm_medium=link&utm_campaign=share-link) or open an issue at [NimBLE-Arduino](https://github.com/h2zero/NimBLE-Arduino/issues) or [esp-nimble-cpp](https://github.com/h2zero/esp-nimble-cpp/issues)
+
+
+# Acknowledgments
+
+* [nkolban](https://github.com/nkolban) and [chegewara](https://github.com/chegewara) for the [original esp32 BLE library](https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils) this project was derived from.
+* [beegee-tokyo](https://github.com/beegee-tokyo) for contributing your time to test/debug and contributing the beacon examples.
+* [Jeroen88](https://github.com/Jeroen88) for the amazing help debugging and improving the client code.
+
+
diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_extended_client/NimBLE_extended_client.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_extended_client/NimBLE_extended_client.ino
new file mode 100644
index 000000000..91a1e626b
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_extended_client/NimBLE_extended_client.ino
@@ -0,0 +1,171 @@
+
+/** NimBLE Extended Client Demo:
+ *
+ * Demonstrates the Bluetooth 5.x client capabilities.
+ *
+ * Created: on April 2 2022
+ * Author: H2zero
+ *
+*/
+
+/****************************************************
+ * For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
+ /**************************************************/
+
+#include
+#if !CONFIG_BT_NIMBLE_EXT_ADV
+# error Must enable extended advertising, see nimconfig.h file.
+#endif
+
+void scanEndedCB(NimBLEScanResults results);
+
+#define SERVICE_UUID "ABCD"
+#define CHARACTERISTIC_UUID "1234"
+
+static NimBLEAdvertisedDevice* advDevice;
+static bool doConnect = false;
+static uint32_t scanTime = 10; /* 0 = scan forever */
+
+/* Define the PHY's to use when connecting to peer devices, can be 1, 2, or all 3 (default).*/
+static uint8_t connectPhys = BLE_GAP_LE_PHY_CODED_MASK | BLE_GAP_LE_PHY_1M_MASK /*| BLE_GAP_LE_PHY_2M_MASK */ ;
+
+/* Define a class to handle the callbacks for client connection events */
+class ClientCallbacks : public NimBLEClientCallbacks {
+ void onConnect(NimBLEClient* pClient) {
+ Serial.printf("Connected\n");
+ };
+
+ void onDisconnect(NimBLEClient* pClient) {
+ Serial.printf("%s Disconnected - Starting scan\n", pClient->getPeerAddress().toString().c_str());
+ NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
+ };
+};
+
+
+/* Define a class to handle the callbacks when advertisements are received */
+class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {
+
+ void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
+ Serial.printf("Advertised Device found: %s\n", advertisedDevice->toString().c_str());
+ if(advertisedDevice->isAdvertisingService(NimBLEUUID("ABCD")))
+ {
+ Serial.printf("Found Our Service\n");
+ /* Ready to connect now */
+ doConnect = true;
+ /* Save the device reference in a global for the client to use*/
+ advDevice = advertisedDevice;
+ /* stop scan before connecting */
+ NimBLEDevice::getScan()->stop();
+ }
+ };
+};
+
+
+/* Callback to process the results of the last scan or restart it */
+void scanEndedCB(NimBLEScanResults results){
+ Serial.printf("Scan Ended\n");
+ if (!doConnect) { /* Don't start the scan while connecting */
+ NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
+ }
+}
+
+
+/* Handles the provisioning of clients and connects / interfaces with the server */
+bool connectToServer() {
+ NimBLEClient* pClient = nullptr;
+
+ pClient = NimBLEDevice::createClient();
+ pClient->setClientCallbacks(new ClientCallbacks, false);
+
+ /* Set the PHY's to use for this connection. This is a bitmask that represents the PHY's:
+ * * 0x01 BLE_GAP_LE_PHY_1M_MASK
+ * * 0x02 BLE_GAP_LE_PHY_2M_MASK
+ * * 0x04 BLE_GAP_LE_PHY_CODED_MASK
+ * Combine these with OR ("|"), eg BLE_GAP_LE_PHY_1M_MASK | BLE_GAP_LE_PHY_2M_MASK | BLE_GAP_LE_PHY_CODED_MASK;
+ */
+ pClient->setConnectPhy(connectPhys);
+
+ /** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
+ pClient->setConnectTimeout(10);
+
+ if (!pClient->connect(advDevice)) {
+ /* Created a client but failed to connect, don't need to keep it as it has no data */
+ NimBLEDevice::deleteClient(pClient);
+ Serial.printf("Failed to connect, deleted client\n");
+ return false;
+ }
+
+ Serial.printf("Connected to: %s RSSI: %d\n",
+ pClient->getPeerAddress().toString().c_str(),
+ pClient->getRssi());
+
+ /* Now we can read/write/subscribe the charateristics of the services we are interested in */
+ NimBLERemoteService* pSvc = nullptr;
+ NimBLERemoteCharacteristic* pChr = nullptr;
+
+ pSvc = pClient->getService(SERVICE_UUID);
+
+ if (pSvc) {
+ pChr = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
+
+ if (pChr) {
+ // Read the value of the characteristic.
+ if (pChr->canRead()) {
+ std::string value = pChr->readValue();
+ Serial.printf("Characteristic value: %s\n", value.c_str());
+ }
+ }
+
+ } else {
+ Serial.printf("ABCD service not found.\n");
+ }
+
+ NimBLEDevice::deleteClient(pClient);
+ Serial.printf("Done with this device!\n");
+ return true;
+}
+
+void setup () {
+ Serial.begin(115200);
+ Serial.printf("Starting NimBLE Client\n");
+
+ /* Initialize NimBLE, no device name specified as we are not advertising */
+ NimBLEDevice::init("");
+ NimBLEScan* pScan = NimBLEDevice::getScan();
+
+ /* create a callback that gets called when advertisers are found */
+ pScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
+
+ /* Set scan interval (how often) and window (how long) in milliseconds */
+ pScan->setInterval(97);
+ pScan->setWindow(67);
+
+ /* Active scan will gather scan response data from advertisers
+ * but will use more energy from both devices
+ */
+ pScan->setActiveScan(true);
+
+ /* Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
+ * Optional callback for when scanning stops.
+ */
+ pScan->start(scanTime, scanEndedCB);
+
+ Serial.printf("Scanning for peripherals\n");
+}
+
+void loop () {
+ /* Loop here until we find a device we want to connect to */
+ if (doConnect) {
+ /* Found a device we want to connect to, do it now */
+ if (connectToServer()) {
+ Serial.printf("Success!, scanning for more!\n");
+ } else {
+ Serial.printf("Failed to connect, starting scan\n");
+ }
+
+ doConnect = false;
+ NimBLEDevice::getScan()->start(scanTime, scanEndedCB);
+ }
+
+ delay(10);
+}
diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_extended_server/NimBLE_extended_server.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_extended_server/NimBLE_extended_server.ino
new file mode 100644
index 000000000..4bcd1b100
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_extended_server/NimBLE_extended_server.ino
@@ -0,0 +1,150 @@
+/** NimBLE Extended Advertiser Demo:
+ *
+ * Demonstrates the Bluetooth 5.x extended advertising capabilities.
+ *
+ * This demo will advertise a long data string on the CODED and 1M Phy's and
+ * starts a server allowing connection over either PHY's. It will advertise for
+ * 5 seconds then sleep for 20 seconds, if a client connects it will sleep once
+ * it has disconnected then repeats.
+ *
+ * Created: on April 2 2022
+ * Author: H2zero
+ *
+*/
+
+/****************************************************
+ * For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
+ /**************************************************/
+
+#include "NimBLEDevice.h"
+#if !CONFIG_BT_NIMBLE_EXT_ADV
+# error Must enable extended advertising, see nimconfig.h file.
+#endif
+
+#include "esp_sleep.h"
+
+#define SERVICE_UUID "ABCD"
+#define CHARACTERISTIC_UUID "1234"
+
+/* Time in milliseconds to advertise */
+static uint32_t advTime = 5000;
+
+/* Time to sleep between advertisements */
+static uint32_t sleepSeconds = 20;
+
+/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
+static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
+
+/* Secondary PHY used for advertising and connecting,
+ * can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
+ */
+static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
+
+
+/* Handler class for server events */
+class ServerCallbacks: public NimBLEServerCallbacks {
+ void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
+ Serial.printf("Client connected:: %s\n", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
+ };
+
+ void onDisconnect(NimBLEServer* pServer) {
+ Serial.printf("Client disconnected - sleeping for %u seconds\n", sleepSeconds);
+ esp_deep_sleep_start();
+ };
+};
+
+/* Callback class to handle advertising events */
+class advertisingCallbacks: public NimBLEExtAdvertisingCallbacks {
+ void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t inst_id) {
+ /* Check the reason advertising stopped, don't sleep if client is connecting */
+ printf("Advertising instance %u stopped\n", inst_id);
+ switch (reason) {
+ case 0:
+ printf("Client connecting\n");
+ return;
+ case BLE_HS_ETIMEOUT:
+ printf("Time expired - sleeping for %u seconds\n", sleepSeconds);
+ break;
+ default:
+ break;
+ }
+
+ esp_deep_sleep_start();
+ }
+};
+
+void setup () {
+ Serial.begin(115200);
+
+ NimBLEDevice::init("Extended advertiser");
+
+ /* Create the server and add the services/characteristics/descriptors */
+ NimBLEServer *pServer = NimBLEDevice::createServer();
+ pServer->setCallbacks(new ServerCallbacks);
+
+ NimBLEService *pService = pServer->createService(SERVICE_UUID);
+ NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,
+ NIMBLE_PROPERTY::READ |
+ NIMBLE_PROPERTY::WRITE |
+ NIMBLE_PROPERTY::NOTIFY);
+
+ pCharacteristic->setValue("Hello World");
+
+ /* Start the services */
+ pService->start();
+
+ /*
+ * Create an extended advertisement with the instance ID 0 and set the PHY's.
+ * Multiple instances can be added as long as the instance ID is incremented.
+ */
+ NimBLEExtAdvertisement extAdv(primaryPhy, secondaryPhy);
+
+ /* Set the advertisement as connectable */
+ extAdv.setConnectable(true);
+
+ /* As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
+ extAdv.setScannable(false); // The default is false, set here for demonstration.
+
+ /* Extended advertising allows for 251 bytes (minus header bytes ~20) in a single advertisement or up to 1650 if chained */
+ extAdv.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Extended Advertising Demo.\r\n"
+ "Extended advertising allows for "
+ "251 bytes of data in a single advertisement,\r\n"
+ "or up to 1650 bytes with chaining.\r\n"
+ "This example message is 226 bytes long "
+ "and is using CODED_PHY for long range."));
+
+ extAdv.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
+
+ /* When extended advertising is enabled `NimBLEDevice::getAdvertising` returns a pointer to `NimBLEExtAdvertising */
+ NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
+
+ /* Set the callbacks for advertising events */
+ pAdvertising->setCallbacks(new advertisingCallbacks);
+
+ /*
+ * NimBLEExtAdvertising::setInstanceData takes the instance ID and
+ * a reference to a `NimBLEExtAdvertisement` object. This sets the data
+ * that will be advertised for this instance ID, returns true if successful.
+ *
+ * Note: It is safe to create the advertisement as a local variable if setInstanceData
+ * is called before exiting the code block as the data will be copied.
+ */
+ if (pAdvertising->setInstanceData(0, extAdv)) {
+ /*
+ * `NimBLEExtAdvertising::start` takes the advertisement instance ID to start
+ * and a duration in milliseconds or a max number of advertisements to send (or both).
+ */
+ if (pAdvertising->start(0, advTime)) {
+ Serial.printf("Started advertising\n");
+ } else {
+ Serial.printf("Failed to start advertising\n");
+ }
+ } else {
+ Serial.printf("Failed to register advertisment data\n");
+ }
+
+ esp_sleep_enable_timer_wakeup(sleepSeconds * 1000000);
+}
+
+void loop () {
+}
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_multi_advertiser/NimBLE_multi_advertiser.ino b/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_multi_advertiser/NimBLE_multi_advertiser.ino
new file mode 100644
index 000000000..73b7c89a2
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/examples/Bluetooth_5/NimBLE_multi_advertiser/NimBLE_multi_advertiser.ino
@@ -0,0 +1,181 @@
+/** NimBLE Multi Advertiser Demo:
+ *
+ * Demonstrates the Bluetooth 5.x extended advertising capabilities.
+ *
+ * This demo will advertise 2 advertisements, and extended scannable instance
+ * and a connectable legacy instance. They will advertise for 5 seconds then
+ * sleep for 20 seconds. The extended scannable instance will use the scan
+ * request callback to update it's data when a scan response is requested.
+ *
+ * Created: on April 9 2022
+ * Author: H2zero
+ *
+*/
+
+/****************************************************
+ * For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
+ /**************************************************/
+
+#include
+#if !CONFIG_BT_NIMBLE_EXT_ADV
+# error Must enable extended advertising, see nimconfig.h file.
+#endif
+
+#include "esp_sleep.h"
+
+#define SERVICE_UUID "ABCD"
+#define CHARACTERISTIC_UUID "1234"
+
+/* Time in milliseconds to advertise */
+static uint32_t advTime = 5000;
+
+/* Time to sleep between advertisements */
+static uint32_t sleepTime = 20;
+
+/* Primary PHY used for advertising, can be one of BLE_HCI_LE_PHY_1M or BLE_HCI_LE_PHY_CODED */
+static uint8_t primaryPhy = BLE_HCI_LE_PHY_CODED;
+
+/* Secondary PHY used for advertising and connecting,
+ * can be one of BLE_HCI_LE_PHY_1M, BLE_HCI_LE_PHY_2M or BLE_HCI_LE_PHY_CODED
+ */
+static uint8_t secondaryPhy = BLE_HCI_LE_PHY_1M;
+
+
+/* Handler class for server events */
+class ServerCallbacks: public NimBLEServerCallbacks {
+ void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
+ Serial.printf("Client connected: %s\n", NimBLEAddress(desc->peer_ota_addr).toString().c_str());
+ };
+
+ void onDisconnect(NimBLEServer* pServer) {
+ Serial.printf("Client disconnected\n");
+ // if still advertising we won't sleep yet.
+ if (!pServer->getAdvertising()->isAdvertising()) {
+ Serial.printf("Sleeping for %u seconds\n", sleepTime);
+ esp_deep_sleep_start();
+ }
+ };
+};
+
+/* Callback class to handle advertising events */
+class advCallbacks: public NimBLEExtAdvertisingCallbacks {
+ void onStopped(NimBLEExtAdvertising* pAdv, int reason, uint8_t inst_id) {
+ /* Check the reason advertising stopped, don't sleep if client is connecting */
+ Serial.printf("Advertising instance %u stopped\n", inst_id);
+ switch (reason) {
+ case 0:
+ Serial.printf(" client connecting\n");
+ return;
+ case BLE_HS_ETIMEOUT:
+ Serial.printf("Time expired - sleeping for %u seconds\n", sleepTime);
+ break;
+ default:
+ break;
+ }
+
+ esp_deep_sleep_start();
+ }
+
+ bool m_updatedSR = false;
+
+ void onScanRequest(NimBLEExtAdvertising* pAdv, uint8_t inst_id, NimBLEAddress addr) {
+ Serial.printf("Scan request for instance %u\n", inst_id);
+ // if the data has already been updated we don't need to change it again.
+ if (!m_updatedSR) {
+ Serial.printf("Updating scan data\n");
+ NimBLEExtAdvertisement sr;
+ sr.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Hello from scan response!"));
+ pAdv->setScanResponseData(inst_id, sr);
+ m_updatedSR = true;
+ }
+ }
+};
+
+void setup () {
+ Serial.begin(115200);
+
+ NimBLEDevice::init("Multi advertiser");
+
+ /* Create a server for our legacy advertiser */
+ NimBLEServer *pServer = NimBLEDevice::createServer();
+ pServer->setCallbacks(new ServerCallbacks);
+
+ NimBLEService *pService = pServer->createService(SERVICE_UUID);
+ NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID,
+ NIMBLE_PROPERTY::READ |
+ NIMBLE_PROPERTY::WRITE |
+ NIMBLE_PROPERTY::NOTIFY);
+
+ pCharacteristic->setValue("Hello World");
+
+ /* Start the service */
+ pService->start();
+
+ /* Create our multi advertising instances */
+
+ // extended scannable instance advertising on coded and 1m PHY's.
+ NimBLEExtAdvertisement extScannable(primaryPhy, secondaryPhy);
+
+ // Legacy advertising as a connectable device.
+ NimBLEExtAdvertisement legacyConnectable;
+
+ // Optional scan response data.
+ NimBLEExtAdvertisement legacyScanResponse;
+
+ /* As per Bluetooth specification, extended advertising cannot be both scannable and connectable */
+ extScannable.setScannable(true);
+ extScannable.setConnectable(false);
+
+ /* Set the initial data */
+ extScannable.setServiceData(NimBLEUUID(SERVICE_UUID), std::string("Scan me!"));
+
+ /* enable the scan response callback, we will use this to update the data. */
+ extScannable.enableScanRequestCallback(true);
+
+ /* Optional custom address for this advertisment. */
+ legacyConnectable.setAddress(NimBLEAddress("DE:AD:BE:EF:BA:AD"));
+
+ /* Set the advertising data. */
+ legacyConnectable.setName("Legacy");
+ legacyConnectable.setCompleteServices16({NimBLEUUID(SERVICE_UUID)});
+
+ /* Set the legacy and connectable flags. */
+ legacyConnectable.setLegacyAdvertising(true);
+ legacyConnectable.setConnectable(true);
+
+ /* Put some data in the scan response if desired. */
+ legacyScanResponse.setServiceData(NimBLEUUID(SERVICE_UUID), "Legacy SR");
+
+ /* Get the advertising ready */
+ NimBLEExtAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
+
+ /* Set the callbacks to handle advertising events */
+ pAdvertising->setCallbacks(new advCallbacks);
+
+ /* Set instance data.
+ * Up to 5 instances can be used if configured in menuconfig, instance 0 is always available.
+ *
+ * We will set the extended scannable data on instance 0 and the legacy data on instance 1.
+ * Note that the legacy scan response data needs to be set to the same instance (1).
+ */
+ if (pAdvertising->setInstanceData( 0, extScannable ) &&
+ pAdvertising->setInstanceData( 1, legacyConnectable ) &&
+ pAdvertising->setScanResponseData( 1, legacyScanResponse )) {
+ /*
+ * `NimBLEExtAdvertising::start` takes the advertisement instance ID to start
+ * and a duration in milliseconds or a max number of advertisements to send (or both).
+ */
+ if (pAdvertising->start(0, advTime) && pAdvertising->start(1, advTime)) {
+ Serial.printf("Started advertising\n");
+ } else {
+ Serial.printf("Failed to start advertising\n");
+ }
+ } else {
+ Serial.printf("Failed to register advertisment data\n");
+ }
+
+ esp_sleep_enable_timer_wakeup(sleepTime * 1000000);
+}
+
+void loop(){
+}
diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino
index a3899cddc..577f67ff8 100644
--- a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino
+++ b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Client/NimBLE_Client.ino
@@ -347,7 +347,11 @@ void setup (){
NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
/** Optional: set the transmit power, default is 3db */
+#ifdef ESP_PLATFORM
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
+#else
+ NimBLEDevice::setPower(9); /** +9db */
+#endif
/** Optional: set any devices you don't want to get advertisments from */
// NimBLEDevice::addIgnored(NimBLEAddress ("aa:bb:cc:dd:ee:ff"));
diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino
index 3a35ebeb2..0936b5a26 100644
--- a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino
+++ b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Client/NimBLE_Secure_Client.ino
@@ -1,5 +1,5 @@
/** NimBLE_Secure_Client Demo:
- *
+ *
* This example demonstrates the secure passkey protected conenction and communication between an esp32 server and an esp32 client.
* Please note that esp32 stores auth info in nvs memory. After a successful connection it is possible that a passkey change will be ineffective.
* To avoid this clear the memory of the esp32's between security testings. esptool.py is capable of this, example: esptool.py --port /dev/ttyUSB0 erase_flash.
@@ -7,7 +7,7 @@
* Created: on Jan 08 2021
* Author: mblasee
*/
-
+
#include
class ClientCallbacks : public NimBLEClientCallbacks
@@ -28,7 +28,11 @@ void setup()
Serial.println("Starting NimBLE Client");
NimBLEDevice::init("");
- NimBLEDevice::setPower(ESP_PWR_LVL_P9);
+#ifdef ESP_PLATFORM
+ NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
+#else
+ NimBLEDevice::setPower(9); /** +9db */
+#endif
NimBLEDevice::setSecurityAuth(true, true, true);
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY);
NimBLEScan *pScan = NimBLEDevice::getScan();
@@ -53,7 +57,7 @@ void setup()
if (pService != nullptr)
{
NimBLERemoteCharacteristic *pNonSecureCharacteristic = pService->getCharacteristic("1234");
-
+
if (pNonSecureCharacteristic != nullptr)
{
// Testing to read a non secured characteristic, you should be able to read this even if you have mismatching passkeys.
@@ -68,11 +72,11 @@ void setup()
{
// Testing to read a secured characteristic, you should be able to read this only if you have matching passkeys, otherwise you should
// get an error like this. E NimBLERemoteCharacteristic: "<< readValue rc=261"
- // This means you are trying to do something without the proper permissions.
+ // This means you are trying to do something without the proper permissions.
std::string value = pSecureCharacteristic->readValue();
// print or do whatever you need with the value
Serial.println(value.c_str());
- }
+ }
}
}
else
diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino
index 4de731e9f..9cd866ccb 100644
--- a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino
+++ b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Secure_Server/NimBLE_Secure_Server.ino
@@ -1,5 +1,5 @@
/** NimBLE_Secure_Server Demo:
- *
+ *
* This example demonstrates the secure passkey protected conenction and communication between an esp32 server and an esp32 client.
* Please note that esp32 stores auth info in nvs memory. After a successful connection it is possible that a passkey change will be ineffective.
* To avoid this clear the memory of the esp32's between security testings. esptool.py is capable of this, example: esptool.py --port /dev/ttyUSB0 erase_flash.
@@ -14,7 +14,11 @@ void setup() {
Serial.begin(115200);
Serial.println("Starting NimBLE Server");
NimBLEDevice::init("NimBLE");
- NimBLEDevice::setPower(ESP_PWR_LVL_P9);
+#ifdef ESP_PLATFORM
+ NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
+#else
+ NimBLEDevice::setPower(9); /** +9db */
+#endif
NimBLEDevice::setSecurityAuth(true, true, true);
NimBLEDevice::setSecurityPasskey(123456);
diff --git a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino
index 7b8c42949..034fe24d4 100644
--- a/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino
+++ b/lib/libesp32_div/NimBLE-Arduino/examples/NimBLE_Server/NimBLE_Server.ino
@@ -2,10 +2,10 @@
/** NimBLE_Server Demo:
*
* Demonstrates many of the available features of the NimBLE server library.
- *
+ *
* Created: on March 22 2020
* Author: H2zero
- *
+ *
*/
#include
@@ -13,16 +13,16 @@
static NimBLEServer* pServer;
/** None of these are required as they will be handled by the library with defaults. **
- ** Remove as you see fit for your needs */
+ ** Remove as you see fit for your needs */
class ServerCallbacks: public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer) {
Serial.println("Client connected");
Serial.println("Multi-connect support: start advertising");
NimBLEDevice::startAdvertising();
};
- /** Alternative onConnect() method to extract details of the connection.
+ /** Alternative onConnect() method to extract details of the connection.
* See: src/ble_gap.h for the details of the ble_gap_conn_desc struct.
- */
+ */
void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
Serial.print("Client address: ");
Serial.println(NimBLEAddress(desc->peer_ota_addr).toString().c_str());
@@ -31,7 +31,7 @@ class ServerCallbacks: public NimBLEServerCallbacks {
* latency, supervision timeout.
* Units; Min/Max Intervals: 1.25 millisecond increments.
* Latency: number of intervals allowed to skip.
- * Timeout: 10 millisecond increments, try for 5x interval time for best results.
+ * Timeout: 10 millisecond increments, try for 5x interval time for best results.
*/
pServer->updateConnParams(desc->conn_handle, 24, 48, 0, 60);
};
@@ -42,25 +42,25 @@ class ServerCallbacks: public NimBLEServerCallbacks {
void onMTUChange(uint16_t MTU, ble_gap_conn_desc* desc) {
Serial.printf("MTU updated: %u for connection ID: %u\n", MTU, desc->conn_handle);
};
-
+
/********************* Security handled here **********************
****** Note: these are the same return values as defaults ********/
uint32_t onPassKeyRequest(){
Serial.println("Server Passkey Request");
- /** This should return a random 6 digit number for security
+ /** This should return a random 6 digit number for security
* or make your own static passkey as done here.
*/
- return 123456;
+ return 123456;
};
bool onConfirmPIN(uint32_t pass_key){
Serial.print("The passkey YES/NO number: ");Serial.println(pass_key);
/** Return false if passkeys don't match. */
- return true;
+ return true;
};
void onAuthenticationComplete(ble_gap_conn_desc* desc){
- /** Check that encryption was successful, if not we disconnect the client */
+ /** Check that encryption was successful, if not we disconnect the client */
if(!desc->sec_state.encrypted) {
NimBLEDevice::getServer()->disconnect(desc->conn_handle);
Serial.println("Encrypt connection failed - disconnecting client");
@@ -83,7 +83,7 @@ class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
Serial.print(": onWrite(), value: ");
Serial.println(pCharacteristic->getValue().c_str());
};
- /** Called before notification or indication is sent,
+ /** Called before notification or indication is sent,
* the value can be changed here before sending if desired.
*/
void onNotify(NimBLECharacteristic* pCharacteristic) {
@@ -99,7 +99,7 @@ class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
str += status;
str += ", return code: ";
str += code;
- str += ", ";
+ str += ", ";
str += NimBLEUtils::returnCodeToString(code);
Serial.println(str);
};
@@ -123,8 +123,8 @@ class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
Serial.println(str);
};
};
-
-/** Handler class for descriptor actions */
+
+/** Handler class for descriptor actions */
class DescriptorCallbacks : public NimBLEDescriptorCallbacks {
void onWrite(NimBLEDescriptor* pDescriptor) {
std::string dscVal = pDescriptor->getValue();
@@ -139,7 +139,7 @@ class DescriptorCallbacks : public NimBLEDescriptorCallbacks {
};
-/** Define callback instances globally to use for multiple Charateristics \ Descriptors */
+/** Define callback instances globally to use for multiple Charateristics \ Descriptors */
static DescriptorCallbacks dscCallbacks;
static CharacteristicCallbacks chrCallbacks;
@@ -152,8 +152,12 @@ void setup() {
NimBLEDevice::init("NimBLE-Arduino");
/** Optional: set the transmit power, default is 3db */
+#ifdef ESP_PLATFORM
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
-
+#else
+ NimBLEDevice::setPower(9); /** +9db */
+#endif
+
/** Set the IO capabilities of the device, each option will trigger a different pairing method.
* BLE_HS_IO_DISPLAY_ONLY - Passkey pairing
* BLE_HS_IO_DISPLAY_YESNO - Numeric comparison pairing
@@ -164,10 +168,10 @@ void setup() {
/** 2 different ways to set security - both calls achieve the same result.
* no bonding, no man in the middle protection, secure connections.
- *
- * These are the default values, only shown here for demonstration.
- */
- //NimBLEDevice::setSecurityAuth(false, false, true);
+ *
+ * These are the default values, only shown here for demonstration.
+ */
+ //NimBLEDevice::setSecurityAuth(false, false, true);
NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
pServer = NimBLEDevice::createServer();
@@ -182,7 +186,7 @@ void setup() {
NIMBLE_PROPERTY::READ_ENC | // only allow reading if paired / encrypted
NIMBLE_PROPERTY::WRITE_ENC // only allow writing if paired / encrypted
);
-
+
pBeefCharacteristic->setValue("Burger");
pBeefCharacteristic->setCallbacks(&chrCallbacks);
@@ -191,10 +195,10 @@ void setup() {
* However we must cast the returned reference to the correct type as the method
* only returns a pointer to the base NimBLEDescriptor class.
*/
- NimBLE2904* pBeef2904 = (NimBLE2904*)pBeefCharacteristic->createDescriptor("2904");
+ NimBLE2904* pBeef2904 = (NimBLE2904*)pBeefCharacteristic->createDescriptor("2904");
pBeef2904->setFormat(NimBLE2904::FORMAT_UTF8);
pBeef2904->setCallbacks(&dscCallbacks);
-
+
NimBLEService* pBaadService = pServer->createService("BAAD");
NimBLECharacteristic* pFoodCharacteristic = pBaadService->createCharacteristic(
@@ -214,7 +218,7 @@ void setup() {
/** Custom descriptor: Arguments are UUID, Properties, max length in bytes of the value */
NimBLEDescriptor* pC01Ddsc = pFoodCharacteristic->createDescriptor(
"C01D",
- NIMBLE_PROPERTY::READ |
+ NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::WRITE|
NIMBLE_PROPERTY::WRITE_ENC, // only allow writing if paired / encrypted
20
@@ -222,7 +226,7 @@ void setup() {
pC01Ddsc->setValue("Send it back!");
pC01Ddsc->setCallbacks(&dscCallbacks);
- /** Start the services when finished creating all Characteristics and Descriptors */
+ /** Start the services when finished creating all Characteristics and Descriptors */
pDeadService->start();
pBaadService->start();
@@ -251,6 +255,6 @@ void loop() {
}
}
}
-
+
delay(2000);
}
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/library.json b/lib/libesp32_div/NimBLE-Arduino/library.json
index 69468f68d..348f77d3d 100644
--- a/lib/libesp32_div/NimBLE-Arduino/library.json
+++ b/lib/libesp32_div/NimBLE-Arduino/library.json
@@ -2,7 +2,7 @@
"name": "NimBLE-Arduino",
"keywords": "esp32, bluetooth",
"description": "Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE",
- "version": "1.3.6",
+ "version": "1.4.0",
"frameworks": "arduino",
"platforms": "espressif32"
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/library.properties b/lib/libesp32_div/NimBLE-Arduino/library.properties
index 38f044cde..16ddf82b5 100644
--- a/lib/libesp32_div/NimBLE-Arduino/library.properties
+++ b/lib/libesp32_div/NimBLE-Arduino/library.properties
@@ -1,10 +1,10 @@
name=NimBLE-Arduino
-version=1.3.6
+version=1.4.0
author=h2zero
maintainer=h2zero
sentence=Bluetooth low energy (BLE) library for arduino-esp32 based on NimBLE.
paragraph=This is a more updated and lower resource alternative to the original bluedroid BLE library for esp32. Uses 50% less flash space and approximately 100KB less ram with the same functionality. Nearly 100% compatible with existing application code, migration guide included.
url=https://github.com/h2zero/NimBLE-Arduino
category=Communication
-architectures=esp32
+architectures=esp32,arm-ble
includes=NimBLEDevice.h
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp
index 282eff55f..b518d9b00 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLE2904.cpp
@@ -22,11 +22,11 @@
#include "NimBLE2904.h"
-NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacterisitic)
+NimBLE2904::NimBLE2904(NimBLECharacteristic* pCharacteristic)
: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2904),
BLE_GATT_CHR_F_READ,
sizeof(BLE2904_Data),
- pCharacterisitic)
+ pCharacteristic)
{
m_data.m_format = 0;
m_data.m_exponent = 0;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp
index b8df5ac83..d8ce5e88c 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAddress.cpp
@@ -156,7 +156,7 @@ std::string NimBLEAddress::toString() const {
/**
- * @brief Convienience operator to check if this address is equal to another.
+ * @brief Convenience operator to check if this address is equal to another.
*/
bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const {
return memcmp(rhs.m_address, m_address, sizeof m_address) == 0;
@@ -164,7 +164,7 @@ bool NimBLEAddress::operator ==(const NimBLEAddress & rhs) const {
/**
- * @brief Convienience operator to check if this address is not equal to another.
+ * @brief Convenience operator to check if this address is not equal to another.
*/
bool NimBLEAddress::operator !=(const NimBLEAddress & rhs) const {
return !this->operator==(rhs);
@@ -186,7 +186,7 @@ NimBLEAddress::operator std::string() const {
/**
- * @brief Convienience operator to convert the native address representation to uint_64.
+ * @brief Convenience operator to convert the native address representation to uint_64.
*/
NimBLEAddress::operator uint64_t() const {
uint64_t address = 0;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp
index 01dd75d41..b4fb0f4de 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.cpp
@@ -20,6 +20,8 @@
#include "NimBLEUtils.h"
#include "NimBLELog.h"
+#include
+
static const char* LOG_TAG = "NimBLEAdvertisedDevice";
@@ -50,9 +52,9 @@ NimBLEAddress NimBLEAdvertisedDevice::getAddress() {
* @brief Get the advertisement type.
* @return The advertising type the device is reporting:
* * BLE_HCI_ADV_TYPE_ADV_IND (0) - indirect advertising
- * * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) - direct advertisng - high duty cycle
+ * * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD (1) - direct advertising - high duty cycle
* * BLE_HCI_ADV_TYPE_ADV_SCAN_IND (2) - indirect scan response
- * * BLE_HCI_ADV_TYPE_ADV_NONCONN_IND (3) - indirect advertisng - not connectable
+ * * BLE_HCI_ADV_TYPE_ADV_NONCONN_IND (3) - indirect advertising - not connectable
* * BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD (4) - direct advertising - low duty cycle
*/
uint8_t NimBLEAdvertisedDevice::getAdvType() {
@@ -64,12 +66,12 @@ uint8_t NimBLEAdvertisedDevice::getAdvType() {
* @brief Get the appearance.
*
* A %BLE device can declare its own appearance. The appearance is how it would like to be shown to an end user
- * typcially in the form of an icon.
+ * typically in the form of an icon.
*
* @return The appearance of the advertised device.
*/
uint16_t NimBLEAdvertisedDevice::getAppearance() {
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_APPEARANCE, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
@@ -87,7 +89,7 @@ uint16_t NimBLEAdvertisedDevice::getAppearance() {
* @return The advertisement interval in 0.625ms units.
*/
uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_ADV_ITVL, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
@@ -105,7 +107,7 @@ uint16_t NimBLEAdvertisedDevice::getAdvInterval() {
* @return The preferred min connection interval in 1.25ms units.
*/
uint16_t NimBLEAdvertisedDevice::getMinInterval() {
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
@@ -123,7 +125,7 @@ uint16_t NimBLEAdvertisedDevice::getMinInterval() {
* @return The preferred max connection interval in 1.25ms units.
*/
uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
@@ -141,7 +143,7 @@ uint16_t NimBLEAdvertisedDevice::getMaxInterval() {
* @return The manufacturer data of the advertised device.
*/
std::string NimBLEAdvertisedDevice::getManufacturerData() {
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_MFG_DATA, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
@@ -159,7 +161,7 @@ std::string NimBLEAdvertisedDevice::getManufacturerData() {
* @return The URI data.
*/
std::string NimBLEAdvertisedDevice::getURI() {
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_URI, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
@@ -177,7 +179,7 @@ std::string NimBLEAdvertisedDevice::getURI() {
* @return The name of the advertised device.
*/
std::string NimBLEAdvertisedDevice::getName() {
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_COMP_NAME, 0, &data_loc) > 0 ||
findAdvField(BLE_HS_ADV_TYPE_INCOMP_NAME, 0, &data_loc) > 0)
@@ -214,7 +216,7 @@ NimBLEScan* NimBLEAdvertisedDevice::getScan() {
* @brief Get the number of target addresses.
* @return The number of addresses.
*/
-size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
+uint8_t NimBLEAdvertisedDevice::getTargetAddressCount() {
uint8_t count = 0;
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR);
@@ -232,7 +234,7 @@ size_t NimBLEAdvertisedDevice::getTargetAddressCount() {
NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
ble_hs_adv_field *field = nullptr;
uint8_t count = 0;
- uint8_t data_loc = 0xFF;
+ size_t data_loc = ULONG_MAX;
index++;
count = findAdvField(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, index, &data_loc);
@@ -242,7 +244,7 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
count = findAdvField(BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR, index, &data_loc);
}
- if(count > 0 && data_loc != 0xFF) {
+ if(count > 0 && data_loc != ULONG_MAX) {
field = (ble_hs_adv_field *)&m_payload[data_loc];
if(field->length < index * BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN) {
index -= count - field->length / BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
@@ -264,9 +266,9 @@ NimBLEAddress NimBLEAdvertisedDevice::getTargetAddress(uint8_t index) {
std::string NimBLEAdvertisedDevice::getServiceData(uint8_t index) {
ble_hs_adv_field *field = nullptr;
uint8_t bytes;
- uint8_t data_loc = findServiceData(index, &bytes);
+ size_t data_loc = findServiceData(index, &bytes);
- if(data_loc != 0xFF) {
+ if(data_loc != ULONG_MAX) {
field = (ble_hs_adv_field *)&m_payload[data_loc];
if(field->length > bytes) {
return std::string((char*)(field->value + bytes), field->length - bytes - 1);
@@ -286,9 +288,9 @@ std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
ble_hs_adv_field *field = nullptr;
uint8_t bytes;
uint8_t index = 0;
- uint8_t data_loc = findServiceData(index, &bytes);
+ size_t data_loc = findServiceData(index, &bytes);
+ size_t plSize = m_payload.size() - 2;
uint8_t uuidBytes = uuid.bitSize() / 8;
- uint8_t plSize = m_payload.size() - 2;
while(data_loc < plSize) {
field = (ble_hs_adv_field *)&m_payload[data_loc];
@@ -306,16 +308,16 @@ std::string NimBLEAdvertisedDevice::getServiceData(const NimBLEUUID &uuid) {
/**
- * @brief Get the UUID of the serice data at the index.
+ * @brief Get the UUID of the service data at the index.
* @param [in] index The index of the service data UUID requested.
* @return The advertised service data UUID or an empty UUID if not found.
*/
NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
ble_hs_adv_field *field = nullptr;
uint8_t bytes;
- uint8_t data_loc = findServiceData(index, &bytes);
+ size_t data_loc = findServiceData(index, &bytes);
- if(data_loc != 0xFF) {
+ if(data_loc != ULONG_MAX) {
field = (ble_hs_adv_field *)&m_payload[data_loc];
if(field->length >= bytes) {
return NimBLEUUID(field->value, bytes, false);
@@ -330,10 +332,10 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceDataUUID(uint8_t index) {
* @brief Find the service data at the index.
* @param [in] index The index of the service data to find.
* @param [in] bytes A pointer to storage for the number of the bytes in the UUID.
- * @return The index in the vector where the data is located, 0xFF if not found.
+ * @return The index in the vector where the data is located, ULONG_MAX if not found.
*/
-uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
- uint8_t data_loc = 0;
+size_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
+ size_t data_loc = 0;
uint8_t found = 0;
*bytes = 0;
@@ -358,7 +360,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
return data_loc;
}
- return 0xFF;
+ return ULONG_MAX;
}
@@ -366,7 +368,7 @@ uint8_t NimBLEAdvertisedDevice::findServiceData(uint8_t index, uint8_t *bytes) {
* @brief Get the count of advertised service data UUIDS
* @return The number of service data UUIDS in the vector.
*/
-size_t NimBLEAdvertisedDevice::getServiceDataCount() {
+uint8_t NimBLEAdvertisedDevice::getServiceDataCount() {
uint8_t count = 0;
count += findAdvField(BLE_HS_ADV_TYPE_SVC_DATA_UUID16);
@@ -384,7 +386,7 @@ size_t NimBLEAdvertisedDevice::getServiceDataCount() {
*/
NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
uint8_t count = 0;
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
uint8_t uuidBytes = 0;
uint8_t type = BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
ble_hs_adv_field *field = nullptr;
@@ -431,7 +433,7 @@ NimBLEUUID NimBLEAdvertisedDevice::getServiceUUID(uint8_t index) {
* @brief Get the number of services advertised
* @return The count of services in the advertising packet.
*/
-size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
+uint8_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
uint8_t count = 0;
count += findAdvField(BLE_HS_ADV_TYPE_INCOMP_UUIDS16);
@@ -446,7 +448,7 @@ size_t NimBLEAdvertisedDevice::getServiceUUIDCount() {
/**
- * @brief Check advertised services for existance of the required UUID
+ * @brief Check advertised services for existence of the required UUID
* @param [in] uuid The service uuid to look for in the advertisement.
* @return Return true if service is advertised
*/
@@ -467,7 +469,7 @@ bool NimBLEAdvertisedDevice::isAdvertisingService(const NimBLEUUID &uuid) {
* @return The TX Power of the advertised device.
*/
int8_t NimBLEAdvertisedDevice::getTXPower() {
- uint8_t data_loc = 0;
+ size_t data_loc = 0;
if(findAdvField(BLE_HS_ADV_TYPE_TX_PWR_LVL, 0, &data_loc) > 0) {
ble_hs_adv_field *field = (ble_hs_adv_field *)&m_payload[data_loc];
@@ -581,17 +583,60 @@ bool NimBLEAdvertisedDevice::haveTXPower() {
} // haveTXPower
-uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_t *data_loc) {
- ble_hs_adv_field *field = nullptr;
- uint8_t data = 0;
- uint8_t length = m_payload.size();
- uint8_t count = 0;
+#if CONFIG_BT_NIMBLE_EXT_ADV
+/**
+ * @brief Get the set ID of the extended advertisement.
+ * @return The set ID.
+ */
+uint8_t NimBLEAdvertisedDevice::getSetId() {
+ return m_sid;
+} // getSetId
- if(length < 2) {
+
+/**
+ * @brief Get the primary PHY used by this advertisement.
+ * @return The PHY type, one of:
+ * * BLE_HCI_LE_PHY_1M
+ * * BLE_HCI_LE_PHY_CODED
+ */
+uint8_t NimBLEAdvertisedDevice::getPrimaryPhy() {
+ return m_primPhy;
+} // getPrimaryPhy
+
+
+/**
+ * @brief Get the primary PHY used by this advertisement.
+ * @return The PHY type, one of:
+ * * BLE_HCI_LE_PHY_1M
+ * * BLE_HCI_LE_PHY_2M
+ * * BLE_HCI_LE_PHY_CODED
+ */
+uint8_t NimBLEAdvertisedDevice::getSecondaryPhy() {
+ return m_secPhy;
+} // getSecondaryPhy
+
+
+/**
+ * @brief Get the periodic interval of the advertisement.
+ * @return The periodic advertising interval, 0 if not periodic advertising.
+ */
+uint16_t NimBLEAdvertisedDevice::getPeriodicInterval() {
+ return m_periodicItvl;
+} // getPeriodicInterval
+#endif
+
+
+uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, size_t * data_loc) {
+ ble_hs_adv_field *field = nullptr;
+ size_t length = m_payload.size();
+ size_t data = 0;
+ uint8_t count = 0;
+
+ if (length < 3) {
return count;
}
- while (length > 1) {
+ while (length > 2) {
field = (ble_hs_adv_field*)&m_payload[data];
if (field->length >= length) {
@@ -599,7 +644,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
}
if (field->type == type) {
- switch(type) {
+ switch (type) {
case BLE_HS_ADV_TYPE_INCOMP_UUIDS16:
case BLE_HS_ADV_TYPE_COMP_UUIDS16:
count += field->length / 2;
@@ -625,8 +670,8 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
break;
}
- if(data_loc != nullptr) {
- if(index == 0 || count >= index) {
+ if (data_loc != nullptr) {
+ if (index == 0 || count >= index) {
break;
}
}
@@ -636,7 +681,7 @@ uint8_t NimBLEAdvertisedDevice::findAdvField(uint8_t type, uint8_t index, uint8_
data += 1 + field->length;
}
- if(data_loc != nullptr && field != nullptr) {
+ if (data_loc != nullptr && field != nullptr) {
*data_loc = data;
}
@@ -657,8 +702,13 @@ void NimBLEAdvertisedDevice::setAddress(NimBLEAddress address) {
* @brief Set the adFlag for this device.
* @param [in] advType The advertisement flag data from the advertisement.
*/
-void NimBLEAdvertisedDevice::setAdvType(uint8_t advType) {
+void NimBLEAdvertisedDevice::setAdvType(uint8_t advType, bool isLegacyAdv) {
m_advType = advType;
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ m_isLegacyAdv = isLegacyAdv;
+#else
+ (void)isLegacyAdv;
+#endif
} // setAdvType
@@ -703,10 +753,10 @@ std::string NimBLEAdvertisedDevice::toString() {
res += val;
}
- if(haveServiceData()) {
- size_t count = getServiceDataCount();
+ if (haveServiceData()) {
+ uint8_t count = getServiceDataCount();
res += "\nService Data:";
- for(size_t i = 0; i < count; i++) {
+ for(uint8_t i = 0; i < count; i++) {
res += "\nUUID: " + std::string(getServiceDataUUID(i));
res += ", Data: " + getServiceData(i);
}
@@ -744,7 +794,7 @@ void NimBLEAdvertisedDevice::setPayload(const uint8_t *payload, uint8_t length,
/**
* @brief Get the length of the advertisement data in the payload.
- * @return The number of bytes in the payload that is from the advertisment.
+ * @return The number of bytes in the payload that is from the advertisement.
*/
uint8_t NimBLEAdvertisedDevice::getAdvLength() {
return m_advLength;
@@ -781,5 +831,34 @@ size_t NimBLEAdvertisedDevice::getPayloadLength() {
return m_payload.size();
} // getPayloadLength
+
+/**
+ * @brief Check if this device is advertising as connectable.
+ * @return True if the device is connectable.
+ */
+bool NimBLEAdvertisedDevice::isConnectable() {
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ if (m_isLegacyAdv) {
+ return m_advType == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND ||
+ m_advType == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
+ }
+#endif
+ return (m_advType & BLE_HCI_ADV_CONN_MASK) ||
+ (m_advType & BLE_HCI_ADV_DIRECT_MASK);
+} // isConnectable
+
+
+/**
+ * @brief Check if this advertisement is a legacy or extended type
+ * @return True if legacy (Bluetooth 4.x), false if extended (bluetooth 5.x).
+ */
+bool NimBLEAdvertisedDevice::isLegacyAdvertisement() {
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ return m_isLegacyAdv;
+# else
+ return true;
+#endif
+} // isLegacyAdvertisement
+
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_CENTRAL */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h
index 39410e665..772bab914 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertisedDevice.h
@@ -71,7 +71,7 @@ public:
std::string getName();
int getRSSI();
NimBLEScan* getScan();
- size_t getServiceDataCount();
+ uint8_t getServiceDataCount();
std::string getServiceData(uint8_t index = 0);
std::string getServiceData(const NimBLEUUID &uuid);
@@ -111,9 +111,9 @@ public:
NimBLEUUID getServiceDataUUID(uint8_t index = 0);
NimBLEUUID getServiceUUID(uint8_t index = 0);
- size_t getServiceUUIDCount();
+ uint8_t getServiceUUIDCount();
NimBLEAddress getTargetAddress(uint8_t index = 0);
- size_t getTargetAddressCount();
+ uint8_t getTargetAddressCount();
int8_t getTXPower();
uint8_t* getPayload();
uint8_t getAdvLength();
@@ -133,16 +133,30 @@ public:
bool haveTargetAddress();
bool haveURI();
std::string toString();
+ bool isConnectable();
+ bool isLegacyAdvertisement();
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ uint8_t getSetId();
+ uint8_t getPrimaryPhy();
+ uint8_t getSecondaryPhy();
+ uint16_t getPeriodicInterval();
+#endif
private:
friend class NimBLEScan;
void setAddress(NimBLEAddress address);
- void setAdvType(uint8_t advType);
+ void setAdvType(uint8_t advType, bool isLegacyAdv);
void setPayload(const uint8_t *payload, uint8_t length, bool append);
void setRSSI(int rssi);
- uint8_t findAdvField(uint8_t type, uint8_t index = 0, uint8_t *data_loc = nullptr);
- uint8_t findServiceData(uint8_t index, uint8_t* bytes);
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ void setSetId(uint8_t sid) { m_sid = sid; }
+ void setPrimaryPhy(uint8_t phy) { m_primPhy = phy; }
+ void setSecondaryPhy(uint8_t phy) { m_secPhy = phy; }
+ void setPeriodicInterval(uint16_t itvl) { m_periodicItvl = itvl; }
+#endif
+ uint8_t findAdvField(uint8_t type, uint8_t index = 0, size_t * data_loc = nullptr);
+ size_t findServiceData(uint8_t index, uint8_t* bytes);
NimBLEAddress m_address = NimBLEAddress("");
uint8_t m_advType;
@@ -150,6 +164,13 @@ private:
time_t m_timestamp;
bool m_callbackSent;
uint8_t m_advLength;
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ bool m_isLegacyAdv;
+ uint8_t m_sid;
+ uint8_t m_primPhy;
+ uint8_t m_secPhy;
+ uint16_t m_periodicItvl;
+#endif
std::vector m_payload;
};
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp
index a804130f8..e45316d69 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.cpp
@@ -14,7 +14,9 @@
*
*/
#include "nimconfig.h"
-#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
+#if (defined(CONFIG_BT_ENABLED) && \
+ defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
+ !CONFIG_BT_NIMBLE_EXT_ADV) || defined(_DOXYGEN_)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "services/gap/ble_svc_gap.h"
@@ -412,7 +414,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
// If already advertising just return
if(ble_gap_adv_active()) {
NIMBLE_LOGW(LOG_TAG, "Advertising already active");
- return false;
+ return true;
}
// Save the duration incase of host reset so we can restart with the same params
@@ -432,15 +434,16 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
if(m_advParams.conn_mode == BLE_GAP_CONN_MODE_NON) {
if(!m_scanResp) {
m_advParams.disc_mode = BLE_GAP_DISC_MODE_NON;
- m_advData.flags = BLE_HS_ADV_F_BREDR_UNSUP;
+ // non-connectable advertising does not require AD flags.
+ m_advData.flags = 0;
}
}
int rc = 0;
if (!m_customAdvData && !m_advDataSet) {
- //start with 3 bytes for the flags data
- uint8_t payloadLen = (2 + 1);
+ //start with 3 bytes for the flags data if required
+ uint8_t payloadLen = (m_advData.flags > 0) ? (2 + 1) : 0;
if(m_advData.mfg_data_len > 0)
payloadLen += (2 + m_advData.mfg_data_len);
@@ -625,7 +628,7 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
&m_advParams,
(pServer != nullptr) ? NimBLEServer::handleGapEvent :
NimBLEAdvertising::handleGapEvent,
- (pServer != nullptr) ? (void*)pServer : (void*)this);
+ (void*)this);
#else
rc = ble_gap_adv_start(NimBLEDevice::m_own_addr_type, NULL, duration,
&m_advParams, NimBLEAdvertising::handleGapEvent, this);
@@ -634,6 +637,10 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
case 0:
break;
+ case BLE_HS_EALREADY:
+ NIMBLE_LOGI(LOG_TAG, "Advertisement Already active");
+ break;
+
case BLE_HS_EINVAL:
NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Duration too long");
break;
@@ -656,24 +663,26 @@ bool NimBLEAdvertising::start(uint32_t duration, void (*advCompleteCB)(NimBLEAdv
}
NIMBLE_LOGD(LOG_TAG, "<< Advertising start");
- return (rc == 0);
+ return (rc == 0 || rc == BLE_HS_EALREADY);
} // start
/**
* @brief Stop advertising.
+ * @return True if advertising stopped successfully.
*/
-void NimBLEAdvertising::stop() {
+bool NimBLEAdvertising::stop() {
NIMBLE_LOGD(LOG_TAG, ">> stop");
int rc = ble_gap_adv_stop();
if (rc != 0 && rc != BLE_HS_EALREADY) {
NIMBLE_LOGE(LOG_TAG, "ble_gap_adv_stop rc=%d %s",
rc, NimBLEUtils::returnCodeToString(rc));
- return;
+ return false;
}
NIMBLE_LOGD(LOG_TAG, "<< stop");
+ return true;
} // stop
@@ -749,7 +758,7 @@ int NimBLEAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
*/
void NimBLEAdvertisementData::addData(const std::string &data) {
if ((m_payload.length() + data.length()) > BLE_HS_ADV_MAX_SZ) {
- NIMBLE_LOGE(LOG_TAG, "Advertisement data length exceded");
+ NIMBLE_LOGE(LOG_TAG, "Advertisement data length exceeded");
return;
}
m_payload.append(data);
@@ -1026,4 +1035,4 @@ std::string NimBLEAdvertisementData::getPayload() {
return m_payload;
} // getPayload
-#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
+#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h
index 63a21d846..dd72ede43 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAdvertising.h
@@ -15,7 +15,9 @@
#ifndef MAIN_BLEADVERTISING_H_
#define MAIN_BLEADVERTISING_H_
#include "nimconfig.h"
-#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
+#if (defined(CONFIG_BT_ENABLED) && \
+ defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
+ !CONFIG_BT_NIMBLE_EXT_ADV) || defined(_DOXYGEN_)
#if defined(CONFIG_NIMBLE_CPP_IDF)
#include "host/ble_gap.h"
@@ -89,7 +91,7 @@ public:
void addServiceUUID(const char* serviceUUID);
void removeServiceUUID(const NimBLEUUID &serviceUUID);
bool start(uint32_t duration = 0, void (*advCompleteCB)(NimBLEAdvertising *pAdv) = nullptr);
- void stop();
+ bool stop();
void setAppearance(uint16_t appearance);
void setName(const std::string &name);
void setManufacturerData(const std::string &data);
@@ -111,6 +113,7 @@ public:
private:
friend class NimBLEDevice;
+ friend class NimBLEServer;
void onHostSync();
static int handleGapEvent(struct ble_gap_event *event, void *arg);
@@ -134,5 +137,5 @@ private:
std::vector m_uri;
};
-#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER */
+#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && !CONFIG_BT_NIMBLE_EXT_ADV */
#endif /* MAIN_BLEADVERTISING_H_ */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAttValue.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAttValue.h
index 11cd3f8d7..be346d502 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAttValue.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEAttValue.h
@@ -54,7 +54,7 @@ struct Has_c_str_len().c_str())),
/**
* @brief A specialized container class to hold BLE attribute values.
* @details This class is designed to be more memory efficient than using\n
- * standard container types for value storage, while being convertable to\n
+ * standard container types for value storage, while being convertible to\n
* many different container classes.
*/
class NimBLEAttValue
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp
index 996893ab1..df24ced93 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEBeacon.cpp
@@ -130,7 +130,7 @@ void NimBLEBeacon::setManufacturerId(uint16_t manufacturerId) {
*/
void NimBLEBeacon::setMinor(uint16_t minor) {
m_beaconData.minor = ENDIAN_CHANGE_U16(minor);
-} // setMinior
+} // setMinor
/**
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp
index 3b95030ce..03d8c55d6 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLECharacteristic.cpp
@@ -126,8 +126,8 @@ void NimBLECharacteristic::addDescriptor(NimBLEDescriptor *pDescriptor) {
/**
- * @brief Remove a descriptor from the characterisitc.
- * @param[in] pDescriptor A pointer to the descriptor instance to remove from the characterisitc.
+ * @brief Remove a descriptor from the characteristic.
+ * @param[in] pDescriptor A pointer to the descriptor instance to remove from the characteristic.
* @param[in] deleteDsc If true it will delete the descriptor instance and free it's resources.
*/
void NimBLECharacteristic::removeDescriptor(NimBLEDescriptor *pDescriptor, bool deleteDsc) {
@@ -273,11 +273,13 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){
switch(ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_CHR: {
- // If the packet header is only 8 bytes this is a follow up of a long read
- // so we don't want to call the onRead() callback again.
- if(ctxt->om->om_pkthdr_len > 8) {
- rc = ble_gap_conn_find(conn_handle, &desc);
- assert(rc == 0);
+ rc = ble_gap_conn_find(conn_handle, &desc);
+ assert(rc == 0);
+
+ // If the packet header is only 8 bytes this is a follow up of a long read
+ // so we don't want to call the onRead() callback again.
+ if(ctxt->om->om_pkthdr_len > 8 ||
+ pCharacteristic->m_value.size() <= (ble_att_mtu(desc.conn_handle) - 3)) {
pCharacteristic->m_pCallbacks->onRead(pCharacteristic);
pCharacteristic->m_pCallbacks->onRead(pCharacteristic, &desc);
}
@@ -440,7 +442,7 @@ void NimBLECharacteristic::notify(const uint8_t* value, size_t length, bool is_n
!(m_properties & NIMBLE_PROPERTY::INDICATE))
{
NIMBLE_LOGE(LOG_TAG,
- "<< notify-Error; Notify/indicate not enabled for characterisitc: %s",
+ "<< notify-Error; Notify/indicate not enabled for characteristic: %s",
std::string(getUUID()).c_str());
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp
index 0abb4088f..d923e6a0a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEClient.cpp
@@ -65,6 +65,11 @@ NimBLEClient::NimBLEClient(const NimBLEAddress &peerAddress) : m_peerAddress(pee
m_pTaskData = nullptr;
m_connEstablished = false;
m_lastErr = 0;
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ m_phyMask = BLE_GAP_LE_PHY_1M_MASK |
+ BLE_GAP_LE_PHY_2M_MASK |
+ BLE_GAP_LE_PHY_CODED_MASK;
+#endif
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
@@ -94,6 +99,8 @@ NimBLEClient::~NimBLEClient() {
delete m_pClientCallbacks;
}
+ ble_npl_callout_deinit(&m_dcTimer);
+
} // ~NimBLEClient
@@ -150,35 +157,35 @@ size_t NimBLEClient::deleteService(const NimBLEUUID &uuid) {
/**
* @brief Connect to the BLE Server.
- * @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
+ * @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
* have created and clears the vectors after successful connection.
* @return True on success.
*/
-bool NimBLEClient::connect(bool deleteAttibutes) {
- return connect(m_peerAddress, deleteAttibutes);
+bool NimBLEClient::connect(bool deleteAttributes) {
+ return connect(m_peerAddress, deleteAttributes);
}
/**
* @brief Connect to an advertising device.
* @param [in] device The device to connect to.
- * @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
+ * @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
* have created and clears the vectors after successful connection.
* @return True on success.
*/
-bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool deleteAttibutes) {
+bool NimBLEClient::connect(NimBLEAdvertisedDevice* device, bool deleteAttributes) {
NimBLEAddress address(device->getAddress());
- return connect(address, deleteAttibutes);
+ return connect(address, deleteAttributes);
}
/**
* @brief Connect to the BLE Server.
* @param [in] address The address of the server.
- * @param [in] deleteAttibutes If true this will delete any attribute objects this client may already\n
+ * @param [in] deleteAttributes If true this will delete any attribute objects this client may already\n
* have created and clears the vectors after successful connection.
* @return True on success.
*/
-bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
+bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttributes) {
NIMBLE_LOGD(LOG_TAG, ">> connect(%s)", address.toString().c_str());
if(!NimBLEDevice::m_synced) {
@@ -218,9 +225,22 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
* Loop on BLE_HS_EBUSY if the scan hasn't stopped yet.
*/
do {
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ rc = ble_gap_ext_connect(NimBLEDevice::m_own_addr_type,
+ &peerAddr_t,
+ m_connectTimeout,
+ m_phyMask,
+ &m_pConnParams,
+ &m_pConnParams,
+ &m_pConnParams,
+ NimBLEClient::handleGapEvent,
+ this);
+
+#else
rc = ble_gap_connect(NimBLEDevice::m_own_addr_type, &peerAddr_t,
m_connectTimeout, &m_pConnParams,
NimBLEClient::handleGapEvent, this);
+#endif
switch (rc) {
case 0:
break;
@@ -239,7 +259,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
break;
case BLE_HS_EALREADY:
- // Already attemting to connect to this device, cancel the previous
+ // Already attempting to connect to this device, cancel the previous
// attempt and report failure here so we don't get 2 connections.
NIMBLE_LOGE(LOG_TAG, "Already attempting to connect to %s - cancelling",
std::string(m_peerAddress).c_str());
@@ -297,7 +317,7 @@ bool NimBLEClient::connect(const NimBLEAddress &address, bool deleteAttibutes) {
NIMBLE_LOGI(LOG_TAG, "Connection established");
}
- if(deleteAttibutes) {
+ if(deleteAttributes) {
deleteServices();
}
@@ -370,8 +390,8 @@ int NimBLEClient::disconnect(uint8_t reason) {
// We use a timer to detect a controller error in the event that it does
// not inform the stack when disconnection is complete.
// This is a common error in certain esp-idf versions.
- // The disconnect timeout time is the supervison timeout time + 1 second.
- // In the case that the event happenss shortly after the supervision timeout
+ // The disconnect timeout time is the supervision timeout time + 1 second.
+ // In the case that the event happens shortly after the supervision timeout
// we don't want to prematurely reset the host.
ble_npl_time_t ticks;
ble_npl_time_ms_to_ticks((desc.supervision_timeout + 100) * 10, &ticks);
@@ -395,8 +415,23 @@ int NimBLEClient::disconnect(uint8_t reason) {
} // disconnect
+#if CONFIG_BT_NIMBLE_EXT_ADV
/**
- * @brief Set the connection paramaters to use when connecting to a server.
+ * @brief Set the PHY types to use when connecting to a server.
+ * @param [in] mask A bitmask indicating what PHYS to connect with.\n
+ * The available bits are:
+ * * 0x01 BLE_GAP_LE_PHY_1M_MASK
+ * * 0x02 BLE_GAP_LE_PHY_2M_MASK
+ * * 0x04 BLE_GAP_LE_PHY_CODED_MASK
+ */
+void NimBLEClient::setConnectPhy(uint8_t mask) {
+ m_phyMask = mask;
+}
+#endif
+
+
+/**
+ * @brief Set the connection parameters to use when connecting to a server.
* @param [in] minInterval The minimum connection interval in 1.25ms units.
* @param [in] maxInterval The maximum connection interval in 1.25ms units.
* @param [in] latency The number of packets allowed to skip (extends max interval).
@@ -464,8 +499,8 @@ void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
* @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
*/
void NimBLEClient::setDataLen(uint16_t tx_octets) {
-#if defined(CONFIG_NIMBLE_CPP_IDF) && defined(ESP_IDF_VERSION) && \
- ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 && ESP_IDF_VERSION_PATCH >= 2
+#if defined(CONFIG_NIMBLE_CPP_IDF) && !defined(ESP_IDF_VERSION) || \
+ (ESP_IDF_VERSION_MAJOR * 100 + ESP_IDF_VERSION_MINOR * 10 + ESP_IDF_VERSION_PATCH) < 432
return;
#else
uint16_t tx_time = (tx_octets + 14) * 8;
@@ -618,7 +653,11 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
{
NimBLEUUID uuid128(uuid);
uuid128.to128();
- return getService(uuid128);
+ if(retrieveServices(&uuid128)) {
+ if(m_servicesVector.size() > prev_size) {
+ return m_servicesVector.back();
+ }
+ }
} else {
// If the request was successful but the 128 bit uuid not found
// try again with the 16 bit uuid.
@@ -626,7 +665,11 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID &uuid) {
uuid16.to16();
// if the uuid was 128 bit but not of the BLE base type this check will fail
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
- return getService(uuid16);
+ if(retrieveServices(&uuid16)) {
+ if(m_servicesVector.size() > prev_size) {
+ return m_servicesVector.back();
+ }
+ }
}
}
}
@@ -660,13 +703,29 @@ std::vector* NimBLEClient::getServices(bool refresh) {
/**
* @brief Retrieves the full database of attributes that the peripheral has available.
+ * @return True if successful.
*/
-void NimBLEClient::discoverAttributes() {
- for(auto svc: *getServices(true)) {
- for(auto chr: *svc->getCharacteristics(true)) {
- chr->getDescriptors(true);
+bool NimBLEClient::discoverAttributes() {
+ deleteServices();
+
+ if (!retrieveServices()){
+ return false;
+ }
+
+
+ for(auto svc: m_servicesVector) {
+ if (!svc->retrieveCharacteristics()) {
+ return false;
+ }
+
+ for(auto chr: svc->m_characteristicVector) {
+ if (!chr->retrieveDescriptors()) {
+ return false;
+ }
}
}
+
+ return true;
} // discoverAttributes
@@ -758,7 +817,7 @@ int NimBLEClient::serviceDiscoveredCB(
if(error->status == BLE_HS_EDONE) {
pTaskData->rc = 0;
} else {
- NIMBLE_LOGE(LOG_TAG, "characteristicDiscCB() rc=%d %s",
+ NIMBLE_LOGE(LOG_TAG, "serviceDiscoveredCB() rc=%d %s",
error->status,
NimBLEUtils::returnCodeToString(error->status));
pTaskData->rc = error->status;
@@ -766,7 +825,7 @@ int NimBLEClient::serviceDiscoveredCB(
xTaskNotifyGive(pTaskData->task);
- NIMBLE_LOGD(LOG_TAG,"<< << Service Discovered");
+ NIMBLE_LOGD(LOG_TAG,"<< Service Discovered");
return error->status;
}
@@ -791,7 +850,7 @@ NimBLEAttValue NimBLEClient::getValue(const NimBLEUUID &serviceUUID, const NimBL
}
}
- NIMBLE_LOGD(LOG_TAG, "< m_servicesVector;
@@ -131,7 +137,7 @@ public:
* @brief Called when server requests to update the connection parameters.
* @param [in] pClient A pointer to the calling client object.
* @param [in] params A pointer to the struct containing the connection parameters requested.
- * @return True to accept the parmeters.
+ * @return True to accept the parameters.
*/
virtual bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp
index 3429d1324..e2e6c1bc8 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDescriptor.cpp
@@ -155,6 +155,7 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
const ble_uuid_t *uuid;
int rc;
+ struct ble_gap_conn_desc desc;
NimBLEDescriptor* pDescriptor = (NimBLEDescriptor*)arg;
NIMBLE_LOGD(LOG_TAG, "Descriptor %s %s event", pDescriptor->getUUID().toString().c_str(),
@@ -164,9 +165,13 @@ int NimBLEDescriptor::handleGapEvent(uint16_t conn_handle, uint16_t attr_handle,
if(ble_uuid_cmp(uuid, &pDescriptor->getUUID().getNative()->u) == 0){
switch(ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_DSC: {
- // If the packet header is only 8 bytes this is a follow up of a long read
- // so we don't want to call the onRead() callback again.
- if(ctxt->om->om_pkthdr_len > 8) {
+ rc = ble_gap_conn_find(conn_handle, &desc);
+ assert(rc == 0);
+
+ // If the packet header is only 8 bytes this is a follow up of a long read
+ // so we don't want to call the onRead() callback again.
+ if(ctxt->om->om_pkthdr_len > 8 ||
+ pDescriptor->m_value.size() <= (ble_att_mtu(desc.conn_handle) - 3)) {
pDescriptor->m_pCallbacks->onRead(pDescriptor);
}
@@ -256,7 +261,7 @@ void NimBLEDescriptor::setValue(const std::vector& vec) {
/**
* @brief Set the characteristic this descriptor belongs to.
- * @param [in] pChar A pointer to the characteristic this descriptior belongs to.
+ * @param [in] pChar A pointer to the characteristic this descriptor belongs to.
*/
void NimBLEDescriptor::setCharacteristic(NimBLECharacteristic* pChar) {
m_pCharacteristic = pChar;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp
index 8c205aff9..a7b6a558e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.cpp
@@ -69,7 +69,11 @@ NimBLEServer* NimBLEDevice::m_pServer = nullptr;
uint32_t NimBLEDevice::m_passkey = 123456;
bool NimBLEDevice::m_synced = false;
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
+# if CONFIG_BT_NIMBLE_EXT_ADV
+NimBLEExtAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
+# else
NimBLEAdvertising* NimBLEDevice::m_bleAdvertising = nullptr;
+# endif
#endif
gap_event_handler NimBLEDevice::m_customGapHandler = nullptr;
@@ -114,6 +118,45 @@ uint8_t NimBLEDevice::m_scanFilterMode = CONFIG_BTDM_SCAN_DU
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
+# if CONFIG_BT_NIMBLE_EXT_ADV
+/**
+ * @brief Get the instance of the advertising object.
+ * @return A pointer to the advertising object.
+ */
+NimBLEExtAdvertising* NimBLEDevice::getAdvertising() {
+ if(m_bleAdvertising == nullptr) {
+ m_bleAdvertising = new NimBLEExtAdvertising();
+ }
+ return m_bleAdvertising;
+}
+
+
+/**
+ * @brief Convenience function to begin advertising.
+ * @param [in] inst_id The extended advertisement instance ID to start.
+ * @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
+ * @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
+ * @return True if advertising started successfully.
+ */
+bool NimBLEDevice::startAdvertising(uint8_t inst_id,
+ int duration,
+ int max_events) {
+ return getAdvertising()->start(inst_id, duration, max_events);
+} // startAdvertising
+
+
+/**
+ * @brief Convenience function to stop advertising a data set.
+ * @param [in] inst_id The extended advertisement instance ID to stop advertising.
+ * @return True if advertising stopped successfully.
+ */
+bool NimBLEDevice::stopAdvertising(uint8_t inst_id) {
+ return getAdvertising()->stop(inst_id);
+} // stopAdvertising
+
+# endif
+
+# if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
/**
* @brief Get the instance of the advertising object.
* @return A pointer to the advertising object.
@@ -128,17 +171,19 @@ NimBLEAdvertising* NimBLEDevice::getAdvertising() {
/**
* @brief Convenience function to begin advertising.
+ * @return True if advertising started successfully.
*/
-void NimBLEDevice::startAdvertising() {
- getAdvertising()->start();
+bool NimBLEDevice::startAdvertising() {
+ return getAdvertising()->start();
} // startAdvertising
-
+# endif
/**
- * @brief Convenience function to stop advertising.
+ * @brief Convenience function to stop all advertising.
+ * @return True if advertising stopped successfully.
*/
-void NimBLEDevice::stopAdvertising() {
- getAdvertising()->stop();
+bool NimBLEDevice::stopAdvertising() {
+ return getAdvertising()->stop();
} // stopAdvertising
#endif // #if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
@@ -757,7 +802,7 @@ void NimBLEDevice::onSync(void)
}
#endif
- // Yield for houskeeping before returning to operations.
+ // Yield for housekeeping before returning to operations.
// Occasionally triggers exception without.
taskYIELD();
@@ -806,7 +851,7 @@ void NimBLEDevice::init(const std::string &deviceName) {
esp_err_t errRc = ESP_OK;
#ifdef CONFIG_ENABLE_ARDUINO_DEPENDS
- // make sure the linker includes esp32-hal-bt.c so ardruino init doesn't release BLE memory.
+ // make sure the linker includes esp32-hal-bt.c so Arduino init doesn't release BLE memory.
btStarted();
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h
index 94ad29478..b7e804b8f 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEDevice.h
@@ -23,7 +23,11 @@
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
-#include "NimBLEAdvertising.h"
+# if CONFIG_BT_NIMBLE_EXT_ADV
+# include "NimBLEExtAdvertising.h"
+# else
+# include "NimBLEAdvertising.h"
+# endif
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_CENTRAL)
@@ -139,9 +143,18 @@ public:
static void removeIgnored(const NimBLEAddress &address);
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
- static NimBLEAdvertising* getAdvertising();
- static void startAdvertising();
- static void stopAdvertising();
+# if CONFIG_BT_NIMBLE_EXT_ADV
+ static NimBLEExtAdvertising* getAdvertising();
+ static bool startAdvertising(uint8_t inst_id,
+ int duration = 0,
+ int max_events = 0);
+ static bool stopAdvertising(uint8_t inst_id);
+ static bool stopAdvertising();
+# else
+ static NimBLEAdvertising* getAdvertising();
+ static bool startAdvertising();
+ static bool stopAdvertising();
+# endif
#endif
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
@@ -178,6 +191,10 @@ private:
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
friend class NimBLEAdvertising;
+# if CONFIG_BT_NIMBLE_EXT_ADV
+ friend class NimBLEExtAdvertising;
+ friend class NimBLEExtAdvertisement;
+# endif
#endif
static void onReset(int reason);
@@ -194,7 +211,11 @@ private:
#endif
#if defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER)
+# if CONFIG_BT_NIMBLE_EXT_ADV
+ static NimBLEExtAdvertising* m_bleAdvertising;
+# else
static NimBLEAdvertising* m_bleAdvertising;
+# endif
#endif
#if defined( CONFIG_BT_NIMBLE_ROLE_CENTRAL)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp
index 255131c02..7a9c5102c 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneTLM.cpp
@@ -85,8 +85,8 @@ float NimBLEEddystoneTLM::getTemp() {
} // getTemp
/**
- * @brief Get the count of advertisments sent.
- * @return The number of advertisments.
+ * @brief Get the count of advertisements sent.
+ * @return The number of advertisements.
*/
uint32_t NimBLEEddystoneTLM::getCount() {
return ENDIAN_CHANGE_U32(m_eddystoneData.advCount);
@@ -94,8 +94,8 @@ uint32_t NimBLEEddystoneTLM::getCount() {
/**
- * @brief Get the advertisment time.
- * @return The advertisment time.
+ * @brief Get the advertisement time.
+ * @return The advertisement time.
*/
uint32_t NimBLEEddystoneTLM::getTime() {
return (ENDIAN_CHANGE_U32(m_eddystoneData.tmil)) / 10;
@@ -158,7 +158,7 @@ std::string NimBLEEddystoneTLM::toString() {
/**
- * @brief Set the raw data for the beacon advertisment.
+ * @brief Set the raw data for the beacon advertisement.
* @param [in] data The raw data to advertise.
*/
void NimBLEEddystoneTLM::setData(const std::string &data) {
@@ -208,8 +208,8 @@ void NimBLEEddystoneTLM::setTemp(float temp) {
/**
- * @brief Set the advertisment count.
- * @param [in] advCount The advertisment number.
+ * @brief Set the advertisement count.
+ * @param [in] advCount The advertisement number.
*/
void NimBLEEddystoneTLM::setCount(uint32_t advCount) {
m_eddystoneData.advCount = advCount;
@@ -217,8 +217,8 @@ void NimBLEEddystoneTLM::setCount(uint32_t advCount) {
/**
- * @brief Set the advertisment time.
- * @param [in] tmil The advertisment time in milliseconds.
+ * @brief Set the advertisement time.
+ * @param [in] tmil The advertisement time in milliseconds.
*/
void NimBLEEddystoneTLM::setTime(uint32_t tmil) {
m_eddystoneData.tmil = tmil;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp
index 424df958e..73829d79e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEEddystoneURL.cpp
@@ -152,7 +152,7 @@ std::string NimBLEEddystoneURL::getDecodedURL() {
/**
- * @brief Set the raw data for the beacon advertisment.
+ * @brief Set the raw data for the beacon advertisement.
* @param [in] data The raw data to advertise.
*/
void NimBLEEddystoneURL::setData(const std::string &data) {
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.cpp
new file mode 100644
index 000000000..b979c9fd0
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.cpp
@@ -0,0 +1,870 @@
+/*
+ * NimBLEExtAdvertising.cpp
+ *
+ * Created: on February 6, 2022
+ * Author H2zero
+ */
+
+#include "nimconfig.h"
+#if defined(CONFIG_BT_ENABLED) && \
+ defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
+ CONFIG_BT_NIMBLE_EXT_ADV
+
+#if defined(CONFIG_NIMBLE_CPP_IDF)
+#include "services/gap/ble_svc_gap.h"
+#else
+#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h"
+#endif
+#include "NimBLEExtAdvertising.h"
+#include "NimBLEDevice.h"
+#include "NimBLEServer.h"
+#include "NimBLEUtils.h"
+#include "NimBLELog.h"
+
+static NimBLEExtAdvertisingCallbacks defaultCallbacks;
+static const char* LOG_TAG = "NimBLEExtAdvertising";
+
+
+/**
+ * @brief Destructor: deletes callback instances if requested.
+ */
+NimBLEExtAdvertising::~NimBLEExtAdvertising() {
+ if(m_deleteCallbacks && m_pCallbacks != &defaultCallbacks) {
+ delete m_pCallbacks;
+ }
+}
+
+
+/**
+ * @brief Register the extended advertisement data.
+ * @param [in] inst_id The extended advertisement instance ID to assign to this data.
+ * @param [in] adv The extended advertisement instance with the data to set.
+ * @return True if advertising started successfully.
+ */
+bool NimBLEExtAdvertising::setInstanceData(uint8_t inst_id, NimBLEExtAdvertisement& adv) {
+ adv.m_params.sid = inst_id;
+
+ // Legacy advertising as connectable requires the scannable flag also.
+ if (adv.m_params.legacy_pdu && adv.m_params.connectable) {
+ adv.m_params.scannable = true;
+ }
+
+ // If connectable or not scannable disable the callback for scan response requests
+ if (adv.m_params.connectable || !adv.m_params.scannable) {
+ adv.m_params.scan_req_notif = false;
+ }
+
+#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
+ NimBLEServer* pServer = NimBLEDevice::getServer();
+ if (pServer != nullptr) {
+ if (!pServer->m_gattsStarted) {
+ pServer->start();
+ }
+ }
+
+ int rc = ble_gap_ext_adv_configure(inst_id,
+ &adv.m_params,
+ NULL,
+ (pServer != nullptr) ? NimBLEServer::handleGapEvent :
+ NimBLEExtAdvertising::handleGapEvent,
+ NULL);
+#else
+ int rc = ble_gap_ext_adv_configure(inst_id,
+ &data.m_params,
+ NULL,
+ NimBLEExtAdvertising::handleGapEvent,
+ NULL);
+#endif
+
+ if (rc != 0) {
+ NIMBLE_LOGE(LOG_TAG, "Advertising config error: rc = %d", rc);
+ } else {
+ os_mbuf *buf;
+ buf = os_msys_get_pkthdr(adv.m_payload.size(), 0);
+ if (!buf) {
+ NIMBLE_LOGE(LOG_TAG, "Data buffer allocation failed");
+ return false;
+ }
+
+ rc = os_mbuf_append(buf, &adv.m_payload[0], adv.m_payload.size());
+ if (rc != 0) {
+ NIMBLE_LOGE(LOG_TAG, "Unable to copy data: rc = %d", rc);
+ return false;
+ } else {
+ if (adv.m_params.scannable && !adv.m_params.legacy_pdu) {
+ rc = ble_gap_ext_adv_rsp_set_data(inst_id, buf);
+ } else {
+ rc = ble_gap_ext_adv_set_data(inst_id, buf);
+ }
+
+ if (rc != 0) {
+ NIMBLE_LOGE(LOG_TAG, "Invalid advertisement data: rc = %d", rc);
+ } else {
+ if (adv.m_advAddress != NimBLEAddress("")) {
+ ble_addr_t addr;
+ memcpy(&addr.val, adv.m_advAddress.getNative(), 6);
+ // Custom advertising address must be random.
+ addr.type = BLE_OWN_ADDR_RANDOM;
+ rc = ble_gap_ext_adv_set_addr(inst_id, &addr);
+ }
+
+ if (rc != 0) {
+ NIMBLE_LOGE(LOG_TAG, "Error setting advertisement address: rc = %d", rc);
+ return false;
+ }
+ }
+ }
+ }
+
+ return (rc == 0);
+}
+
+
+/**
+ * @brief Set the scan response data for a legacy advertisement.
+ * @param [in] inst_id The extended advertisement instance ID to assign to this data.
+ * @param [in] lsr A reference to a NimBLEExtAdvertisement that contains the data.
+ */
+bool NimBLEExtAdvertising::setScanResponseData(uint8_t inst_id, NimBLEExtAdvertisement & lsr) {
+ os_mbuf *buf = os_msys_get_pkthdr(lsr.m_payload.size(), 0);
+ if (!buf) {
+ NIMBLE_LOGE(LOG_TAG, "Data buffer allocation failed");
+ return false;
+ }
+
+ int rc = os_mbuf_append(buf, &lsr.m_payload[0], lsr.m_payload.size());
+
+ if (rc != 0) {
+ NIMBLE_LOGE(LOG_TAG, "Unable to copy scan data: rc = %d", rc);
+ return false;
+ } else {
+ rc = ble_gap_ext_adv_rsp_set_data(inst_id, buf);
+ }
+ return (rc == 0);
+}
+
+
+/**
+ * @brief Start extended advertising.
+ * @param [in] inst_id The extended advertisement instance ID to start.
+ * @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
+ * @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
+ * @return True if advertising started successfully.
+ */
+bool NimBLEExtAdvertising::start(uint8_t inst_id, int duration, int max_events) {
+ NIMBLE_LOGD(LOG_TAG, ">> Extended Advertising start");
+
+ // If Host is not synced we cannot start advertising.
+ if(!NimBLEDevice::m_synced) {
+ NIMBLE_LOGE(LOG_TAG, "Host reset, wait for sync.");
+ return false;
+ }
+
+ int rc = ble_gap_ext_adv_start(inst_id, duration / 10, max_events);
+
+ switch (rc) {
+ case 0:
+ m_advStatus[inst_id] = true;
+ break;
+
+ case BLE_HS_EINVAL:
+ NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Value Error");
+ break;
+
+ case BLE_HS_EALREADY:
+ NIMBLE_LOGI(LOG_TAG, "Advertisement Already active");
+ break;
+
+ case BLE_HS_ETIMEOUT_HCI:
+ case BLE_HS_EOS:
+ case BLE_HS_ECONTROLLER:
+ case BLE_HS_ENOTSYNCED:
+ NIMBLE_LOGE(LOG_TAG, "Unable to advertise - Host Reset");
+ break;
+
+ default:
+ NIMBLE_LOGE(LOG_TAG, "Error enabling advertising; rc=%d, %s",
+ rc, NimBLEUtils::returnCodeToString(rc));
+ break;
+ }
+
+ NIMBLE_LOGD(LOG_TAG, "<< Extended Advertising start");
+ return (rc == 0 || rc == BLE_HS_EALREADY);
+} // start
+
+
+/**
+ * @brief Stop and remove this instance data from the advertisement set.
+ * @param [in] inst_id The extended advertisement instance to stop advertising.
+ * @return True if successful.
+ */
+bool NimBLEExtAdvertising::removeInstance(uint8_t inst_id) {
+ if (stop(inst_id)) {
+ int rc = ble_gap_ext_adv_remove(inst_id);
+ if (rc != 0 && rc != BLE_HS_EALREADY) {
+ NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_remove rc = %d %s",
+ rc, NimBLEUtils::returnCodeToString(rc));
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+} // removeInstance
+
+
+/**
+ * @brief Stop and remove all advertising instance data.
+ * @return True if successful.
+ */
+bool NimBLEExtAdvertising::removeAll() {
+ if (stop()) {
+ int rc = ble_gap_ext_adv_clear();
+ if (rc == 0 || rc == BLE_HS_EALREADY) {
+ return true;
+ } else {
+ NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_clear rc = %d %s",
+ rc, NimBLEUtils::returnCodeToString(rc));
+ }
+ }
+
+ return false;
+} // removeAll
+
+
+/**
+ * @brief Stop advertising this instance data.
+ * @param [in] inst_id The extended advertisement instance to stop advertising.
+ * @return True if successful.
+ */
+bool NimBLEExtAdvertising::stop(uint8_t inst_id) {
+ int rc = ble_gap_ext_adv_stop(inst_id);
+ if (rc != 0 && rc != BLE_HS_EALREADY) {
+ NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_stop rc = %d %s",
+ rc, NimBLEUtils::returnCodeToString(rc));
+ return false;
+ }
+
+ m_advStatus[inst_id] = false;
+ return true;
+} // stop
+
+
+/**
+ * @brief Stop all advertisements.
+ * @return True if successful.
+ */
+bool NimBLEExtAdvertising::stop() {
+ int rc = ble_gap_ext_adv_clear();
+ if (rc != 0 && rc != BLE_HS_EALREADY) {
+ NIMBLE_LOGE(LOG_TAG, "ble_gap_ext_adv_stop rc = %d %s",
+ rc, NimBLEUtils::returnCodeToString(rc));
+ return false;
+ }
+
+ for(auto it : m_advStatus) {
+ it = false;
+ }
+
+ return true;
+} // stop
+
+
+/**
+ * @brief Set a callback to call when the advertisement stops.
+ * @param [in] pCallbacks A pointer to a callback to be invoked when an advertisement stops.
+ * @param [in] deleteCallbacks if true callback class will be deleted when advertising is destructed.
+ */
+void NimBLEExtAdvertising::setCallbacks(NimBLEExtAdvertisingCallbacks* pCallbacks,
+ bool deleteCallbacks) {
+ if (pCallbacks != nullptr){
+ m_pCallbacks = pCallbacks;
+ m_deleteCallbacks = deleteCallbacks;
+ } else {
+ m_pCallbacks = &defaultCallbacks;
+ }
+} // setCallbacks
+
+
+/**
+ * @brief Check if currently advertising.
+ * @param [in] inst_id The instance ID of the advertised data to get the status of.
+ * @return True if advertising is active.
+ */
+bool NimBLEExtAdvertising::isActive(uint8_t inst_id) {
+ return m_advStatus[inst_id];
+} // isAdvertising
+
+
+/**
+ * @brief Check if any instances are currently advertising.
+ * @return True if any instance is active.
+ */
+bool NimBLEExtAdvertising::isAdvertising() {
+ for (auto it : m_advStatus) {
+ if (it) {
+ return true;
+ }
+ }
+ return false;
+} // isAdvertising
+
+
+/*
+ * Host reset seems to clear advertising data,
+ * we need clear the flag so it reloads it.
+ */
+void NimBLEExtAdvertising::onHostSync() {
+ NIMBLE_LOGD(LOG_TAG, "Host re-synced");
+ for(auto it : m_advStatus) {
+ it = false;
+ }
+} // onHostSync
+
+
+/**
+ * @brief Handler for gap events when not using peripheral role.
+ * @param [in] event the event data.
+ * @param [in] arg pointer to the advertising instance.
+ */
+/*STATIC*/
+int NimBLEExtAdvertising::handleGapEvent(struct ble_gap_event *event, void *arg) {
+ (void)arg;
+ NimBLEExtAdvertising* pAdv = NimBLEDevice::getAdvertising();
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_ADV_COMPLETE: {
+ switch (event->adv_complete.reason) {
+ // Don't call the callback if host reset, we want to
+ // preserve the active flag until re-sync to restart advertising.
+ case BLE_HS_ETIMEOUT_HCI:
+ case BLE_HS_EOS:
+ case BLE_HS_ECONTROLLER:
+ case BLE_HS_ENOTSYNCED:
+ NIMBLE_LOGC(LOG_TAG, "host reset, rc = %d", event->adv_complete.reason);
+ NimBLEDevice::onReset(event->adv_complete.reason);
+ return 0;
+ default:
+ break;
+ }
+ pAdv->m_advStatus[event->adv_complete.instance] = false;
+ pAdv->m_pCallbacks->onStopped(pAdv, event->adv_complete.reason,
+ event->adv_complete.instance);
+ break;
+ }
+
+ case BLE_GAP_EVENT_SCAN_REQ_RCVD: {
+ pAdv->m_pCallbacks->onScanRequest(pAdv, event->scan_req_rcvd.instance,
+ NimBLEAddress(event->scan_req_rcvd.scan_addr));
+ break;
+ }
+ }
+
+ return 0;
+} // handleGapEvent
+
+
+/** Default callback handlers */
+void NimBLEExtAdvertisingCallbacks::onStopped(NimBLEExtAdvertising *pAdv,
+ int reason, uint8_t inst_id) {
+ NIMBLE_LOGD("NimBLEExtAdvertisingCallbacks", "onStopped: Default");
+} // onStopped
+
+
+void NimBLEExtAdvertisingCallbacks::onScanRequest(NimBLEExtAdvertising *pAdv,
+ uint8_t inst_id, NimBLEAddress addr) {
+ NIMBLE_LOGD("NimBLEExtAdvertisingCallbacks", "onScanRequest: Default");
+} // onScanRequest
+
+
+/**
+ * @brief Construct a BLE extended advertisement.
+ * @param [in] priPhy The primary Phy to advertise on, can be one of:
+ * * BLE_HCI_LE_PHY_1M
+ * * BLE_HCI_LE_PHY_CODED
+ * @param [in] secPhy The secondary Phy to advertise on, can be one of:
+ * * BLE_HCI_LE_PHY_1M
+ * * BLE_HCI_LE_PHY_2M
+ * * BLE_HCI_LE_PHY_CODED
+ */
+NimBLEExtAdvertisement::NimBLEExtAdvertisement(uint8_t priPhy, uint8_t secPhy)
+: m_advAddress("")
+{
+ memset (&m_params, 0, sizeof(m_params));
+ m_params.own_addr_type = NimBLEDevice::m_own_addr_type;
+ m_params.primary_phy = priPhy;
+ m_params.secondary_phy = secPhy;
+ m_params.tx_power = 127;
+} // NimBLEExtAdvertisement
+
+
+/**
+ * @brief Sets wether the advertisement should use legacy (BLE 4.0, 31 bytes max) advertising.
+ * @param [in] val true = using legacy advertising.
+ */
+void NimBLEExtAdvertisement::setLegacyAdvertising(bool val) {
+ m_params.legacy_pdu = val;
+} // setLegacyAdvertising
+
+
+/**
+ * @brief Sets wether the advertisement has scan response data available.
+ * @param [in] val true = scan response is available.
+ */
+void NimBLEExtAdvertisement::setScannable(bool val) {
+ m_params.scannable = val;
+} // setScannable
+
+
+
+/**
+ * @brief Sets the transmission power level for this advertisement.
+ * @param [in] dbm the transmission power to use in dbm.
+ * @details The allowable value range depends on device hardware. \n
+ * The ESP32C3 and ESP32S3 have a range of -27 to +18.
+ */
+void NimBLEExtAdvertisement::setTxPower(int8_t dbm) {
+ m_params.tx_power = dbm;
+}
+
+
+/**
+ * @brief Sets wether this advertisement should advertise as a connectable device.
+ * @param [in] val True = connectable.
+ */
+void NimBLEExtAdvertisement::setConnectable(bool val) {
+#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
+ m_params.connectable = val;
+#endif
+} // setConnectable
+
+
+/**
+ * @brief Set the address to use for this advertisement.
+ * @param [in] addr The address to use.
+ */
+void NimBLEExtAdvertisement::setAddress(const NimBLEAddress & addr) {
+ m_advAddress = addr;
+ // Must use random address type.
+ m_params.own_addr_type = BLE_OWN_ADDR_RANDOM;
+}
+
+
+/**
+ * @brief Sets The primary channels to advertise on.
+ * @param [in] ch37 Advertise on channel 37.
+ * @param [in] ch38 Advertise on channel 38.
+ * @param [in] ch39 Advertise on channel 39.
+ * @details This will set a bitmask using the input parameters to allow different \n
+ * combinations. If all inputs are false then all 3 channels will be used.
+ */
+void NimBLEExtAdvertisement::setPrimaryChannels(bool ch37, bool ch38, bool ch39) {
+ m_params.channel_map = (ch37 | (ch38 << 1) | (ch39 << 2));
+} // setPrimaryChannels
+
+
+/**
+ * @brief Set the filtering for the scan filter.
+ * @param [in] scanRequestWhitelistOnly If true, only allow scan requests from those on the white list.
+ * @param [in] connectWhitelistOnly If true, only allow connections from those on the white list.
+ */
+void NimBLEExtAdvertisement::setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly) {
+ if (!scanRequestWhitelistOnly && !connectWhitelistOnly) {
+ m_params.filter_policy = BLE_HCI_ADV_FILT_NONE;
+ return;
+ }
+ if (scanRequestWhitelistOnly && !connectWhitelistOnly) {
+ m_params.filter_policy = BLE_HCI_ADV_FILT_SCAN;
+ return;
+ }
+ if (!scanRequestWhitelistOnly && connectWhitelistOnly) {
+ m_params.filter_policy = BLE_HCI_ADV_FILT_CONN;
+ return;
+ }
+ if (scanRequestWhitelistOnly && connectWhitelistOnly) {
+ m_params.filter_policy = BLE_HCI_ADV_FILT_BOTH;
+ return;
+ }
+} // setScanFilter
+
+
+/**
+ * @brief Sets the peer to directly advertise to.
+ * @param [in] addr The address of the peer to direct the advertisements.
+ */
+void NimBLEExtAdvertisement::setDirectedPeer(const NimBLEAddress & addr) {
+ ble_addr_t peerAddr;
+ memcpy(&peerAddr.val, addr.getNative(), 6);
+ peerAddr.type = addr.getType();
+ m_params.peer = peerAddr;
+} // setDirectedPeer
+
+
+/**
+ * @brief Enable or disable direct advertisements to the peer set with `NimBLEExtAdvertisement::setDirectedPeer`
+ * @param [in] val true = send directed advertisements to peer.
+ * @param [in] high_duty true = use fast advertising rate, default - true.
+ */
+void NimBLEExtAdvertisement::setDirected(bool val, bool high_duty) {
+ m_params.directed = val;
+ m_params.high_duty_directed = high_duty;
+} // setDirected
+
+
+/**
+ * @brief Set the minimum advertising interval.
+ * @param [in] mininterval Minimum value for advertising interval in 0.625ms units, 0 = use default.
+ */
+void NimBLEExtAdvertisement::setMinInterval(uint32_t mininterval) {
+ m_params.itvl_min = mininterval;
+} // setMinInterval
+
+
+/**
+ * @brief Set the maximum advertising interval.
+ * @param [in] maxinterval Maximum value for advertising interval in 0.625ms units, 0 = use default.
+ */
+void NimBLEExtAdvertisement::setMaxInterval(uint32_t maxinterval) {
+ m_params.itvl_max = maxinterval;
+} // setMaxInterval
+
+
+/**
+ * @brief Set the primary advertising PHY to use
+ * @param [in] phy Can be one of following constants:
+ * * BLE_HCI_LE_PHY_1M
+ * * BLE_HCI_LE_PHY_CODED
+ */
+void NimBLEExtAdvertisement::setPrimaryPhy(uint8_t phy) {
+ m_params.primary_phy = phy;
+} // setPrimaryPhy
+
+
+/**
+ * @brief Set the secondary advertising PHY to use
+ * @param [in] phy Can be one of following constants:
+ * * BLE_HCI_LE_PHY_1M
+ * * BLE_HCI_LE_PHY_2M
+ * * BLE_HCI_LE_PHY_CODED
+ */
+void NimBLEExtAdvertisement::setSecondaryPhy(uint8_t phy) {
+ m_params.secondary_phy = phy;
+} // setSecondaryPhy
+
+
+/**
+ * @brief Sets whether the advertisement should be anonymous.
+ * @param [in] val Set to true to enable anonymous advertising.
+ *
+ * @details Anonymous advertising omits the device's address from the advertisement.
+ */
+void NimBLEExtAdvertisement::setAnonymous(bool val) {
+ m_params.anonymous = val;
+} // setAnonymous
+
+
+/**
+ * @brief Sets whether the scan response request callback should be called.
+ * @param [in] enable If true the scan response request callback will be called for this advertisement.
+ */
+void NimBLEExtAdvertisement::enableScanRequestCallback(bool enable) {
+ m_params.scan_req_notif = enable;
+} // enableScanRequestCallback
+
+
+/**
+ * @brief Clears the data stored in this instance, does not change settings.
+ * @details This will clear all data but preserves advertising parameter settings.
+ */
+void NimBLEExtAdvertisement::clearData() {
+ std::vector swap;
+ std::swap(m_payload, swap);
+}
+
+
+/**
+ * @brief Get the size of the current data.
+ */
+size_t NimBLEExtAdvertisement::getDataSize() {
+ return m_payload.size();
+} // getDataSize
+
+
+/**
+ * @brief Set the advertisement data.
+ * @param [in] data The data to be set as the payload.
+ * @param [in] length The size of data.
+ * @details This will completely replace any data that was previously set.
+ */
+void NimBLEExtAdvertisement::setData(const uint8_t * data, size_t length) {
+ m_payload.assign(data, data + length);
+} // setData
+
+
+/**
+ * @brief Add data to the payload to be advertised.
+ * @param [in] data The data to be added to the payload.
+ */
+void NimBLEExtAdvertisement::addData(const std::string &data) {
+ addData((uint8_t*)data.data(), data.length());
+} // addData
+
+
+/**
+ * @brief Add data to the payload to be advertised.
+ * @param [in] data The data to be added to the payload.
+ * @param [in] length The size of data to be added to the payload.
+ */
+void NimBLEExtAdvertisement::addData(const uint8_t * data, size_t length) {
+ m_payload.insert(m_payload.end(), data, data + length);
+} // addData
+
+
+/**
+ * @brief Set the appearance.
+ * @param [in] appearance The appearance code value.
+ *
+ * See also:
+ * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
+ */
+void NimBLEExtAdvertisement::setAppearance(uint16_t appearance) {
+ char cdata[2];
+ cdata[0] = 3;
+ cdata[1] = BLE_HS_ADV_TYPE_APPEARANCE; // 0x19
+ addData(std::string(cdata, 2) + std::string((char*) &appearance, 2));
+} // setAppearance
+
+
+/**
+ * @brief Set the advertisement flags.
+ * @param [in] flag The flags to be set in the advertisement.
+ * * BLE_HS_ADV_F_DISC_LTD
+ * * BLE_HS_ADV_F_DISC_GEN
+ * * BLE_HS_ADV_F_BREDR_UNSUP - must always use with NimBLE
+ */
+void NimBLEExtAdvertisement::setFlags(uint8_t flag) {
+ char cdata[3];
+ cdata[0] = 2;
+ cdata[1] = BLE_HS_ADV_TYPE_FLAGS; // 0x01
+ cdata[2] = flag | BLE_HS_ADV_F_BREDR_UNSUP;
+ addData(std::string(cdata, 3));
+} // setFlags
+
+
+/**
+ * @brief Set manufacturer specific data.
+ * @param [in] data The manufacturer data to advertise.
+ */
+void NimBLEExtAdvertisement::setManufacturerData(const std::string &data) {
+ char cdata[2];
+ cdata[0] = data.length() + 1;
+ cdata[1] = BLE_HS_ADV_TYPE_MFG_DATA ; // 0xff
+ addData(std::string(cdata, 2) + data);
+} // setManufacturerData
+
+
+/**
+ * @brief Set the URI to advertise.
+ * @param [in] uri The uri to advertise.
+ */
+void NimBLEExtAdvertisement::setURI(const std::string &uri) {
+ char cdata[2];
+ cdata[0] = uri.length() + 1;
+ cdata[1] = BLE_HS_ADV_TYPE_URI;
+ addData(std::string(cdata, 2) + uri);
+} // setURI
+
+
+/**
+ * @brief Set the complete name of this device.
+ * @param [in] name The name to advertise.
+ */
+void NimBLEExtAdvertisement::setName(const std::string &name) {
+ char cdata[2];
+ cdata[0] = name.length() + 1;
+ cdata[1] = BLE_HS_ADV_TYPE_COMP_NAME; // 0x09
+ addData(std::string(cdata, 2) + name);
+} // setName
+
+
+/**
+ * @brief Set a single service to advertise as a complete list of services.
+ * @param [in] uuid The service to advertise.
+ */
+void NimBLEExtAdvertisement::setCompleteServices(const NimBLEUUID &uuid) {
+ setServices(true, uuid.bitSize(), {uuid});
+} // setCompleteServices
+
+
+/**
+ * @brief Set the complete list of 16 bit services to advertise.
+ * @param [in] v_uuid A vector of 16 bit UUID's to advertise.
+ */
+void NimBLEExtAdvertisement::setCompleteServices16(const std::vector& v_uuid) {
+ setServices(true, 16, v_uuid);
+} // setCompleteServices16
+
+
+/**
+ * @brief Set the complete list of 32 bit services to advertise.
+ * @param [in] v_uuid A vector of 32 bit UUID's to advertise.
+ */
+void NimBLEExtAdvertisement::setCompleteServices32(const std::vector& v_uuid) {
+ setServices(true, 32, v_uuid);
+} // setCompleteServices32
+
+
+/**
+ * @brief Set a single service to advertise as a partial list of services.
+ * @param [in] uuid The service to advertise.
+ */
+void NimBLEExtAdvertisement::setPartialServices(const NimBLEUUID &uuid) {
+ setServices(false, uuid.bitSize(), {uuid});
+} // setPartialServices
+
+
+/**
+ * @brief Set the partial list of services to advertise.
+ * @param [in] v_uuid A vector of 16 bit UUID's to advertise.
+ */
+void NimBLEExtAdvertisement::setPartialServices16(const std::vector& v_uuid) {
+ setServices(false, 16, v_uuid);
+} // setPartialServices16
+
+
+/**
+ * @brief Set the partial list of services to advertise.
+ * @param [in] v_uuid A vector of 32 bit UUID's to advertise.
+ */
+void NimBLEExtAdvertisement::setPartialServices32(const std::vector& v_uuid) {
+ setServices(false, 32, v_uuid);
+} // setPartialServices32
+
+
+/**
+ * @brief Utility function to create the list of service UUID's from a vector.
+ * @param [in] complete If true the vector is the complete set of services.
+ * @param [in] size The bit size of the UUID's in the vector. (16, 32, or 128).
+ * @param [in] v_uuid The vector of service UUID's to advertise.
+ */
+void NimBLEExtAdvertisement::setServices(const bool complete, const uint8_t size,
+ const std::vector &v_uuid)
+{
+ char cdata[2];
+ cdata[0] = (size / 8) * v_uuid.size() + 1;
+ switch(size) {
+ case 16:
+ cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS16 : BLE_HS_ADV_TYPE_INCOMP_UUIDS16;
+ break;
+ case 32:
+ cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS32 : BLE_HS_ADV_TYPE_INCOMP_UUIDS32;
+ break;
+ case 128:
+ cdata[1] = complete ? BLE_HS_ADV_TYPE_COMP_UUIDS128 : BLE_HS_ADV_TYPE_INCOMP_UUIDS128;
+ break;
+ default:
+ return;
+ }
+
+ std::string uuids;
+
+ for(auto &it : v_uuid){
+ if(it.bitSize() != size) {
+ NIMBLE_LOGE(LOG_TAG, "Service UUID(%d) invalid", size);
+ return;
+ } else {
+ switch(size) {
+ case 16:
+ uuids += std::string((char*)&it.getNative()->u16.value, 2);
+ break;
+ case 32:
+ uuids += std::string((char*)&it.getNative()->u32.value, 4);
+ break;
+ case 128:
+ uuids += std::string((char*)&it.getNative()->u128.value, 16);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ addData(std::string(cdata, 2) + uuids);
+} // setServices
+
+
+/**
+ * @brief Set the service data (UUID + data)
+ * @param [in] uuid The UUID to set with the service data.
+ * @param [in] data The data to be associated with the service data advertised.
+ */
+void NimBLEExtAdvertisement::setServiceData(const NimBLEUUID &uuid, const std::string &data) {
+ char cdata[2];
+ switch (uuid.bitSize()) {
+ case 16: {
+ // [Len] [0x16] [UUID16] data
+ cdata[0] = data.length() + 3;
+ cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID16; // 0x16
+ addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u16.value, 2) + data);
+ break;
+ }
+
+ case 32: {
+ // [Len] [0x20] [UUID32] data
+ cdata[0] = data.length() + 5;
+ cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID32; // 0x20
+ addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u32.value, 4) + data);
+ break;
+ }
+
+ case 128: {
+ // [Len] [0x21] [UUID128] data
+ cdata[0] = data.length() + 17;
+ cdata[1] = BLE_HS_ADV_TYPE_SVC_DATA_UUID128; // 0x21
+ addData(std::string(cdata, 2) + std::string((char*) &uuid.getNative()->u128.value, 16) + data);
+ break;
+ }
+
+ default:
+ return;
+ }
+} // setServiceData
+
+
+/**
+ * @brief Set the short name.
+ * @param [in] name The short name of the device.
+ */
+void NimBLEExtAdvertisement::setShortName(const std::string &name) {
+ char cdata[2];
+ cdata[0] = name.length() + 1;
+ cdata[1] = BLE_HS_ADV_TYPE_INCOMP_NAME; // 0x08
+ addData(std::string(cdata, 2) + name);
+} // setShortName
+
+
+/**
+ * @brief Adds Tx power level to the advertisement data.
+ */
+void NimBLEExtAdvertisement::addTxPower() {
+ m_params.include_tx_power = 1;
+} // addTxPower
+
+
+/**
+ * @brief Set the preferred connection interval parameters.
+ * @param [in] min The minimum interval desired.
+ * @param [in] max The maximum interval desired.
+ */
+void NimBLEExtAdvertisement::setPreferredParams(uint16_t min, uint16_t max) {
+ uint8_t data[6];
+ data[0] = BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN + 1;
+ data[1] = BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE;
+ data[2] = min;
+ data[3] = min >> 8;
+ data[4] = max;
+ data[5] = max >> 8;
+ addData(data, 6);
+} // setPreferredParams
+
+#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.h
new file mode 100644
index 000000000..b1f21fc78
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEExtAdvertising.h
@@ -0,0 +1,152 @@
+/*
+ * NimBLEExtAdvertising.h
+ *
+ * Created: on February 6, 2022
+ * Author H2zero
+ */
+
+#ifndef MAIN_BLEEXTADVERTISING_H_
+#define MAIN_BLEEXTADVERTISING_H_
+#include "nimconfig.h"
+#if defined(CONFIG_BT_ENABLED) && \
+ defined(CONFIG_BT_NIMBLE_ROLE_BROADCASTER) && \
+ CONFIG_BT_NIMBLE_EXT_ADV
+
+# if defined(CONFIG_NIMBLE_CPP_IDF)
+# include "host/ble_gap.h"
+# else
+# include "nimble/nimble/host/include/host/ble_gap.h"
+# endif
+
+/**** FIX COMPILATION ****/
+#undef min
+#undef max
+/**************************/
+
+#include "NimBLEAddress.h"
+#include "NimBLEUUID.h"
+
+#include
+
+class NimBLEExtAdvertisingCallbacks;
+
+
+/**
+ * @brief Extended advertisement data
+ */
+class NimBLEExtAdvertisement {
+public:
+ NimBLEExtAdvertisement(uint8_t priPhy = BLE_HCI_LE_PHY_1M,
+ uint8_t secPhy = BLE_HCI_LE_PHY_1M);
+ void setAppearance(uint16_t appearance);
+ void setCompleteServices(const NimBLEUUID &uuid);
+ void setCompleteServices16(const std::vector &v_uuid);
+ void setCompleteServices32(const std::vector &v_uuid);
+ void setFlags(uint8_t flag);
+ void setManufacturerData(const std::string &data);
+ void setURI(const std::string &uri);
+ void setName(const std::string &name);
+ void setPartialServices(const NimBLEUUID &uuid);
+ void setPartialServices16(const std::vector &v_uuid);
+ void setPartialServices32(const std::vector &v_uuid);
+ void setServiceData(const NimBLEUUID &uuid, const std::string &data);
+ void setShortName(const std::string &name);
+ void setData(const uint8_t * data, size_t length);
+ void addData(const std::string &data);
+ void addData(const uint8_t * data, size_t length);
+ void addTxPower();
+ void setPreferredParams(uint16_t min, uint16_t max);
+ void setLegacyAdvertising(bool val);
+ void setConnectable(bool val);
+ void setScannable(bool val);
+ void setMinInterval(uint32_t mininterval);
+ void setMaxInterval(uint32_t maxinterval);
+ void setPrimaryPhy(uint8_t phy);
+ void setSecondaryPhy(uint8_t phy);
+ void setScanFilter(bool scanRequestWhitelistOnly, bool connectWhitelistOnly);
+ void setDirectedPeer(const NimBLEAddress & addr);
+ void setDirected(bool val, bool high_duty = true);
+ void setAnonymous(bool val);
+ void setPrimaryChannels(bool ch37, bool ch38, bool ch39);
+ void setTxPower(int8_t dbm);
+ void setAddress(const NimBLEAddress & addr);
+ void enableScanRequestCallback(bool enable);
+ void clearData();
+ size_t getDataSize();
+
+private:
+ friend class NimBLEExtAdvertising;
+
+ void setServices(const bool complete, const uint8_t size,
+ const std::vector &v_uuid);
+
+ std::vector m_payload;
+ ble_gap_ext_adv_params m_params;
+ NimBLEAddress m_advAddress;
+}; // NimBLEExtAdvertisement
+
+
+/**
+ * @brief Extended advertising class.
+ */
+class NimBLEExtAdvertising {
+public:
+ /**
+ * @brief Construct an extended advertising object.
+ */
+ NimBLEExtAdvertising() :m_advStatus(CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES + 1, false) {}
+ ~NimBLEExtAdvertising();
+ bool start(uint8_t inst_id, int duration = 0, int max_events = 0);
+ bool setInstanceData(uint8_t inst_id, NimBLEExtAdvertisement& adv);
+ bool setScanResponseData(uint8_t inst_id, NimBLEExtAdvertisement & data);
+ bool removeInstance(uint8_t inst_id);
+ bool removeAll();
+ bool stop(uint8_t inst_id);
+ bool stop();
+ bool isActive(uint8_t inst_id);
+ bool isAdvertising();
+ void setCallbacks(NimBLEExtAdvertisingCallbacks* callbacks,
+ bool deleteCallbacks = true);
+
+private:
+ friend class NimBLEDevice;
+ friend class NimBLEServer;
+
+ void onHostSync();
+ static int handleGapEvent(struct ble_gap_event *event, void *arg);
+
+ bool m_scanResp;
+ bool m_deleteCallbacks;
+ NimBLEExtAdvertisingCallbacks* m_pCallbacks;
+ ble_gap_ext_adv_params m_advParams;
+ std::vector m_advStatus;
+};
+
+
+/**
+ * @brief Callbacks associated with NimBLEExtAdvertising class.
+ */
+class NimBLEExtAdvertisingCallbacks {
+public:
+ virtual ~NimBLEExtAdvertisingCallbacks() {};
+
+ /**
+ * @brief Handle an advertising stop event.
+ * @param [in] pAdv A convenience pointer to the extended advertising interface.
+ * @param [in] reason The reason code for stopping the advertising.
+ * @param [in] inst_id The instance ID of the advertisement that was stopped.
+ */
+ virtual void onStopped(NimBLEExtAdvertising *pAdv, int reason, uint8_t inst_id);
+
+ /**
+ * @brief Handle a scan response request.
+ * This is called when a scanning device requests a scan response.
+ * @param [in] pAdv A convenience pointer to the extended advertising interface.
+ * @param [in] inst_id The instance ID of the advertisement that the scan response request was made.
+ * @param [in] addr The address of the device making the request.
+ */
+ virtual void onScanRequest(NimBLEExtAdvertising *pAdv, uint8_t inst_id, NimBLEAddress addr);
+}; // NimBLEExtAdvertisingCallbacks
+
+#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && CONFIG_BT_NIMBLE_EXT_ADV */
+#endif /* MAIN_BLEADVERTISING_H_ */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp
index 78c8fea3c..29150ce63 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEHIDDevice.cpp
@@ -99,7 +99,7 @@ void NimBLEHIDDevice::manufacturer(std::string name) {
}
/**
- * @brief Sets the Plug n Play characterisc value.
+ * @brief Sets the Plug n Play characteristic value.
* @param [in] sig The vendor ID source number.
* @param [in] vid The vendor ID number.
* @param [in] pid The product ID number.
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp
index d25bce14f..68982f89e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.cpp
@@ -266,6 +266,10 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(const NimBLEUUID *uuid_filt
}
}
+ if (m_handle == m_endHandle) {
+ return true;
+ }
+
desc_filter_t filter = {uuid_filter, &taskData};
rc = ble_gattc_disc_all_dscs(getRemoteService()->getClient()->getConnId(),
@@ -323,7 +327,11 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
{
NimBLEUUID uuid128(uuid);
uuid128.to128();
- return getDescriptor(uuid128);
+ if(retrieveDescriptors(&uuid128)) {
+ if(m_descriptorVector.size() > prev_size) {
+ return m_descriptorVector.back();
+ }
+ }
} else {
// If the request was successful but the 128 bit uuid not found
// try again with the 16 bit uuid.
@@ -331,7 +339,11 @@ NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUU
uuid16.to16();
// if the uuid was 128 bit but not of the BLE base type this check will fail
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
- return getDescriptor(uuid16);
+ if(retrieveDescriptors(&uuid16)) {
+ if(m_descriptorVector.size() > prev_size) {
+ return m_descriptorVector.back();
+ }
+ }
}
}
}
@@ -604,6 +616,7 @@ bool NimBLERemoteCharacteristic::setNotify(uint16_t val, notify_callback notifyC
NIMBLE_LOGD(LOG_TAG, "<< setNotify()");
+ response = true; // Always write with response as per Bluetooth core specification.
return desc->writeValue((uint8_t *)&val, 2, response);
} // setNotify
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h
index 353d83221..7042b19bf 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteCharacteristic.h
@@ -73,8 +73,8 @@ public:
bool subscribe(bool notifications = true,
notify_callback notifyCallback = nullptr,
- bool response = false);
- bool unsubscribe(bool response = false);
+ bool response = true);
+ bool unsubscribe(bool response = true);
bool registerForNotify(notify_callback notifyCallback,
bool notifications = true,
bool response = true)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp
index 218396d3f..5a72fe368 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLERemoteService.cpp
@@ -116,7 +116,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
{
NimBLEUUID uuid128(uuid);
uuid128.to128();
- return getCharacteristic(uuid128);
+ if (retrieveCharacteristics(&uuid128)) {
+ if(m_characteristicVector.size() > prev_size) {
+ return m_characteristicVector.back();
+ }
+ }
} else {
// If the request was successful but the 128 bit uuid not found
// try again with the 16 bit uuid.
@@ -124,7 +128,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
uuid16.to16();
// if the uuid was 128 bit but not of the BLE base type this check will fail
if (uuid16.bitSize() == BLE_UUID_TYPE_16) {
- return getCharacteristic(uuid16);
+ if(retrieveCharacteristics(&uuid16)) {
+ if(m_characteristicVector.size() > prev_size) {
+ return m_characteristicVector.back();
+ }
+ }
}
}
}
@@ -157,7 +165,7 @@ std::vector* NimBLERemoteService::getCharacteristic
/**
- * @brief Callback for Characterisic discovery.
+ * @brief Callback for Characteristic discovery.
* @return success == 0 or error code.
*/
int NimBLERemoteService::characteristicDiscCB(uint16_t conn_handle,
@@ -248,7 +256,9 @@ bool NimBLERemoteService::retrieveCharacteristics(const NimBLEUUID *uuid_filter)
}
}
- m_characteristicVector.back()->m_endHandle = getEndHandle();
+ if (m_characteristicVector.size() > 0) {
+ m_characteristicVector.back()->m_endHandle = getEndHandle();
+ }
}
NIMBLE_LOGD(LOG_TAG, "<< retrieveCharacteristics()");
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp
index 57a5df365..d1c4879be 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEScan.cpp
@@ -34,7 +34,7 @@ NimBLEScan::NimBLEScan() {
m_scan_params.itvl = 0; // This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. (units=0.625 msec)
m_scan_params.window = 0; // The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval (units=0.625 msec)
m_scan_params.limited = 0; // If set, only discover devices in limited discoverable mode.
- m_scan_params.filter_duplicates = 0; // If set, the controller ignores all but the first advertisement from each device.
+ m_scan_params.filter_duplicates = 1; // If set, the controller ignores all but the first advertisement from each device.
m_pAdvertisedDeviceCallbacks = nullptr;
m_ignoreResults = false;
m_pTaskData = nullptr;
@@ -56,18 +56,27 @@ NimBLEScan::~NimBLEScan() {
* @param [in] param Parameter data for this event.
*/
/*STATIC*/int NimBLEScan::handleGapEvent(ble_gap_event* event, void* arg) {
-
- NimBLEScan* pScan = (NimBLEScan*)arg;
+ (void)arg;
+ NimBLEScan* pScan = NimBLEDevice::getScan();
switch(event->type) {
+ case BLE_GAP_EVENT_EXT_DISC:
case BLE_GAP_EVENT_DISC: {
if(pScan->m_ignoreResults) {
NIMBLE_LOGI(LOG_TAG, "Scan op in progress - ignoring results");
return 0;
}
-
- NimBLEAddress advertisedAddress(event->disc.addr);
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ const auto& disc = event->ext_disc;
+ const bool isLegacyAdv = disc.props & BLE_HCI_ADV_LEGACY_MASK;
+ const auto event_type = isLegacyAdv ? disc.legacy_event_type : disc.props;
+#else
+ const auto& disc = event->disc;
+ const bool isLegacyAdv = true;
+ const auto event_type = disc.event_type;
+#endif
+ NimBLEAddress advertisedAddress(disc.addr);
// Examine our list of ignored addresses and stop processing if we don't want to see it or are already connected
if(NimBLEDevice::isIgnored(advertisedAddress)) {
@@ -79,7 +88,12 @@ NimBLEScan::~NimBLEScan() {
// If we've seen this device before get a pointer to it from the vector
for(auto &it: pScan->m_scanResults.m_advertisedDevicesVector) {
- if(it->getAddress() == advertisedAddress) {
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ // Same address but different set ID should create a new advertised device.
+ if (it->getAddress() == advertisedAddress && it->getSetId() == disc.sid) {
+#else
+ if (it->getAddress() == advertisedAddress) {
+#endif
advertisedDevice = it;
break;
}
@@ -87,20 +101,27 @@ NimBLEScan::~NimBLEScan() {
// If we haven't seen this device before; create a new instance and insert it in the vector.
// Otherwise just update the relevant parameters of the already known device.
- if(advertisedDevice == nullptr && event->disc.event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP){
+ if (advertisedDevice == nullptr &&
+ (!isLegacyAdv || event_type != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP)) {
// Check if we have reach the scan results limit, ignore this one if so.
// We still need to store each device when maxResults is 0 to be able to append the scan results
- if(pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
- (pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults))
- {
+ if (pScan->m_maxResults > 0 && pScan->m_maxResults < 0xFF &&
+ (pScan->m_scanResults.m_advertisedDevicesVector.size() >= pScan->m_maxResults)) {
return 0;
}
+
advertisedDevice = new NimBLEAdvertisedDevice();
advertisedDevice->setAddress(advertisedAddress);
- advertisedDevice->setAdvType(event->disc.event_type);
+ advertisedDevice->setAdvType(event_type, isLegacyAdv);
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ advertisedDevice->setSetId(disc.sid);
+ advertisedDevice->setPrimaryPhy(disc.prim_phy);
+ advertisedDevice->setSecondaryPhy(disc.sec_phy);
+ advertisedDevice->setPeriodicInterval(disc.periodic_adv_itvl);
+#endif
pScan->m_scanResults.m_advertisedDevicesVector.push_back(advertisedDevice);
NIMBLE_LOGI(LOG_TAG, "New advertiser: %s", advertisedAddress.toString().c_str());
- } else if(advertisedDevice != nullptr) {
+ } else if (advertisedDevice != nullptr) {
NIMBLE_LOGI(LOG_TAG, "Updated advertiser: %s", advertisedAddress.toString().c_str());
} else {
// Scan response from unknown device
@@ -108,14 +129,18 @@ NimBLEScan::~NimBLEScan() {
}
advertisedDevice->m_timestamp = time(nullptr);
- advertisedDevice->setRSSI(event->disc.rssi);
- advertisedDevice->setPayload(event->disc.data, event->disc.length_data,
- event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP);
+ advertisedDevice->setRSSI(disc.rssi);
+ advertisedDevice->setPayload(disc.data, disc.length_data, (isLegacyAdv &&
+ event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP));
if (pScan->m_pAdvertisedDeviceCallbacks) {
+ if (pScan->m_scan_params.filter_duplicates && advertisedDevice->m_callbackSent) {
+ return 0;
+ }
+
// If not active scanning or scan response is not available
- // report the result to the callback now.
- if(pScan->m_scan_params.passive ||
+ // or extended advertisement scanning, report the result to the callback now.
+ if(pScan->m_scan_params.passive || !isLegacyAdv ||
(advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_IND &&
advertisedDevice->getAdvType() != BLE_HCI_ADV_TYPE_ADV_SCAN_IND))
{
@@ -123,7 +148,7 @@ NimBLEScan::~NimBLEScan() {
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
// Otherwise, wait for the scan response so we can report the complete data.
- } else if (event->disc.event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
+ } else if (isLegacyAdv && event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) {
advertisedDevice->m_callbackSent = true;
pScan->m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
}
@@ -139,7 +164,7 @@ NimBLEScan::~NimBLEScan() {
NIMBLE_LOGD(LOG_TAG, "discovery complete; reason=%d",
event->disc_complete.reason);
- // If a device advertised with scan reponse available and it was not received
+ // If a device advertised with scan response available and it was not received
// the callback would not have been invoked, so do it here.
if(pScan->m_pAdvertisedDeviceCallbacks) {
for(auto &it : pScan->m_scanResults.m_advertisedDevicesVector) {
@@ -186,7 +211,7 @@ void NimBLEScan::setActiveScan(bool active) {
* from devices it has not already seen.
* @param [in] enabled If true, scanned devices will only be reported once.
* @details The controller has a limited buffer and will start reporting
- * dupicate devices once the limit is reached.
+ * duplicate devices once the limit is reached.
*/
void NimBLEScan::setDuplicateFilter(bool enabled) {
m_scan_params.filter_duplicates = enabled;
@@ -211,7 +236,7 @@ void NimBLEScan::setLimitedOnly(bool enabled) {
* directed, connectable advertising packets not sent to the scanner.
* * BLE_HCI_SCAN_FILT_USE_WL (1)
* Scanner processes advertisements from white list only. A connectable,\n
- * directed advertisment is ignored unless it contains scanners address.
+ * directed advertisement is ignored unless it contains scanners address.
* * BLE_HCI_SCAN_FILT_NO_WL_INITA (2)
* Scanner process all advertising packets (white list not used). A\n
* connectable, directed advertisement shall not be ignored if the InitA
@@ -304,9 +329,28 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
m_ignoreResults = true;
}
- int rc = ble_gap_disc(NimBLEDevice::m_own_addr_type, duration, &m_scan_params,
- NimBLEScan::handleGapEvent, this);
-
+# if CONFIG_BT_NIMBLE_EXT_ADV
+ ble_gap_ext_disc_params scan_params;
+ scan_params.passive = m_scan_params.passive;
+ scan_params.itvl = m_scan_params.itvl;
+ scan_params.window = m_scan_params.window;
+ int rc = ble_gap_ext_disc(NimBLEDevice::m_own_addr_type,
+ duration/10,
+ 0,
+ m_scan_params.filter_duplicates,
+ m_scan_params.filter_policy,
+ m_scan_params.limited,
+ &scan_params,
+ &scan_params,
+ NimBLEScan::handleGapEvent,
+ NULL);
+#else
+ int rc = ble_gap_disc(NimBLEDevice::m_own_addr_type,
+ duration,
+ &m_scan_params,
+ NimBLEScan::handleGapEvent,
+ NULL);
+#endif
switch(rc) {
case 0:
if(!is_continue) {
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp
index df6d192b4..0a0b72ba3 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLESecurity.cpp
@@ -61,8 +61,8 @@ void NimBLESecurity::setCapability(esp_ble_io_cap_t iocap) {
/**
- * @brief Sets the keys we will distibute during encryption.
- * @param [in] init_key A bitmask of the keys we will distibute.\n
+ * @brief Sets the keys we will distribute during encryption.
+ * @param [in] init_key A bitmask of the keys we will distribute.\n
* Can be one or more of:
* * ESP_BLE_ENC_KEY_MASK (1 << 0)
* * ESP_BLE_ID_KEY_MASK (1 << 1)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp
index c7aeb648e..82fbc7a01 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.cpp
@@ -42,7 +42,9 @@ NimBLEServer::NimBLEServer() {
// m_svcChgChrHdl = 0xffff; // Future Use
m_pServerCallbacks = &defaultCallbacks;
m_gattsStarted = false;
+#if !CONFIG_BT_NIMBLE_EXT_ADV
m_advertiseOnDisconnect = true;
+#endif
m_svcChanged = false;
m_deleteCallbacks = true;
} // NimBLEServer
@@ -139,15 +141,26 @@ NimBLEService *NimBLEServer::getServiceByHandle(uint16_t handle) {
return nullptr;
}
+
+#if CONFIG_BT_NIMBLE_EXT_ADV
+/**
+ * @brief Retrieve the advertising object that can be used to advertise the existence of the server.
+ * @return An advertising object.
+ */
+NimBLEExtAdvertising* NimBLEServer::getAdvertising() {
+ return NimBLEDevice::getAdvertising();
+} // getAdvertising
+#endif
+
+#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
/**
* @brief Retrieve the advertising object that can be used to advertise the existence of the server.
- *
* @return An advertising object.
*/
NimBLEAdvertising* NimBLEServer::getAdvertising() {
return NimBLEDevice::getAdvertising();
} // getAdvertising
-
+#endif
/**
* @brief Sends a service changed notification and resets the GATT server.
@@ -240,6 +253,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
} // disconnect
+#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
/**
* @brief Set the server to automatically start advertising when a client disconnects.
* @param [in] aod true == advertise, false == don't advertise.
@@ -247,7 +261,7 @@ int NimBLEServer::disconnect(uint16_t connId, uint8_t reason) {
void NimBLEServer::advertiseOnDisconnect(bool aod) {
m_advertiseOnDisconnect = aod;
} // advertiseOnDisconnect
-
+#endif
/**
* @brief Return the number of connected clients.
@@ -323,8 +337,9 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
* @param [in] param
*
*/
-/*STATIC*/int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
- NimBLEServer* server = (NimBLEServer*)arg;
+/*STATIC*/
+int NimBLEServer::handleGapEvent(struct ble_gap_event *event, void *arg) {
+ NimBLEServer* server = NimBLEDevice::getServer();
NIMBLE_LOGD(LOG_TAG, ">> handleGapEvent: %s",
NimBLEUtils::gapEventToString(event->type));
int rc = 0;
@@ -336,7 +351,9 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
if (event->connect.status != 0) {
/* Connection failed; resume advertising */
NIMBLE_LOGE(LOG_TAG, "Connection failed");
+#if !CONFIG_BT_NIMBLE_EXT_ADV
NimBLEDevice::startAdvertising();
+#endif
}
else {
server->m_connectedPeersVec.push_back(event->connect.conn_handle);
@@ -356,7 +373,7 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
case BLE_GAP_EVENT_DISCONNECT: {
// If Host reset tell the device now before returning to prevent
- // any errors caused by calling host functions before resyncing.
+ // any errors caused by calling host functions before resync.
switch(event->disconnect.reason) {
case BLE_HS_ETIMEOUT_HCI:
case BLE_HS_EOS:
@@ -381,9 +398,11 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
server->m_pServerCallbacks->onDisconnect(server);
server->m_pServerCallbacks->onDisconnect(server, &event->disconnect.conn);
+#if !CONFIG_BT_NIMBLE_EXT_ADV
if(server->m_advertiseOnDisconnect) {
server->startAdvertising();
}
+#endif
return 0;
} // BLE_GAP_EVENT_DISCONNECT
@@ -471,11 +490,15 @@ NimBLEConnInfo NimBLEServer::getPeerIDInfo(uint16_t id) {
return 0;
} // BLE_GAP_EVENT_NOTIFY_TX
- case BLE_GAP_EVENT_ADV_COMPLETE: {
- NIMBLE_LOGD(LOG_TAG, "Advertising Complete");
- NimBLEDevice::getAdvertising()->advCompleteCB();
- return 0;
- }
+
+ case BLE_GAP_EVENT_ADV_COMPLETE:
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ case BLE_GAP_EVENT_SCAN_REQ_RCVD:
+ return NimBLEExtAdvertising::handleGapEvent(event, arg);
+#else
+ return NimBLEAdvertising::handleGapEvent(event, arg);
+#endif
+ // BLE_GAP_EVENT_ADV_COMPLETE | BLE_GAP_EVENT_SCAN_REQ_RCVD
case BLE_GAP_EVENT_CONN_UPDATE: {
NIMBLE_LOGD(LOG_TAG, "Connection parameters updated.");
@@ -613,7 +636,7 @@ void NimBLEServer::setCallbacks(NimBLEServerCallbacks* pCallbacks, bool deleteCa
* @brief Remove a service from the server.
*
* @details Immediately removes access to the service by clients, sends a service changed indication,
- * and removes the service (if applicable) from the advertisments.
+ * and removes the service (if applicable) from the advertisements.
* The service is not deleted unless the deleteSvc parameter is true, otherwise the service remains
* available and can be re-added in the future. If desired a removed but not deleted service can
* be deleted later by calling this method with deleteSvc set to true.
@@ -652,7 +675,9 @@ void NimBLEServer::removeService(NimBLEService* service, bool deleteSvc) {
service->m_removed = deleteSvc ? NIMBLE_ATT_REMOVE_DELETE : NIMBLE_ATT_REMOVE_HIDE;
serviceChanged();
+#if !CONFIG_BT_NIMBLE_EXT_ADV
NimBLEDevice::getAdvertising()->removeServiceUUID(service->getUUID());
+#endif
}
@@ -715,22 +740,52 @@ void NimBLEServer::resetGATT() {
}
+#if CONFIG_BT_NIMBLE_EXT_ADV
/**
* @brief Start advertising.
- *
- * Start the server advertising its existence. This is a convenience function and is equivalent to
+ * @param [in] inst_id The extended advertisement instance ID to start.
+ * @param [in] duration How long to advertise for in milliseconds, 0 = forever (default).
+ * @param [in] max_events Maximum number of advertisement events to send, 0 = no limit (default).
+ * @return True if advertising started successfully.
+ * @details Start the server advertising its existence. This is a convenience function and is equivalent to
* retrieving the advertising object and invoking start upon it.
*/
-void NimBLEServer::startAdvertising() {
- NimBLEDevice::startAdvertising();
+bool NimBLEServer::startAdvertising(uint8_t inst_id,
+ int duration,
+ int max_events) {
+ return getAdvertising()->start(inst_id, duration, max_events);
} // startAdvertising
/**
- * @brief Stop advertising.
+ * @brief Convenience function to stop advertising a data set.
+ * @param [in] inst_id The extended advertisement instance ID to stop advertising.
+ * @return True if advertising stopped successfully.
*/
-void NimBLEServer::stopAdvertising() {
- NimBLEDevice::stopAdvertising();
+bool NimBLEServer::stopAdvertising(uint8_t inst_id) {
+ return getAdvertising()->stop(inst_id);
+} // stopAdvertising
+#endif
+
+#if !CONFIG_BT_NIMBLE_EXT_ADV|| defined(_DOXYGEN_)
+/**
+ * @brief Start advertising.
+ * @return True if advertising started successfully.
+ * @details Start the server advertising its existence. This is a convenience function and is equivalent to
+ * retrieving the advertising object and invoking start upon it.
+ */
+bool NimBLEServer::startAdvertising() {
+ return getAdvertising()->start();
+} // startAdvertising
+#endif
+
+
+/**
+ * @brief Stop advertising.
+ * @return True if advertising stopped successfully.
+ */
+bool NimBLEServer::stopAdvertising() {
+ return getAdvertising()->stop();
} // stopAdvertising
@@ -782,8 +837,8 @@ void NimBLEServer::updateConnParams(uint16_t conn_handle,
* @param [in] tx_octets The preferred number of payload octets to use (Range 0x001B-0x00FB).
*/
void NimBLEServer::setDataLen(uint16_t conn_handle, uint16_t tx_octets) {
-#if defined(CONFIG_NIMBLE_CPP_IDF) && defined(ESP_IDF_VERSION) && \
- ESP_IDF_VERSION_MAJOR >= 4 && ESP_IDF_VERSION_MINOR >= 3 && ESP_IDF_VERSION_PATCH >= 2
+#if defined(CONFIG_NIMBLE_CPP_IDF) && !defined(ESP_IDF_VERSION) || \
+ (ESP_IDF_VERSION_MAJOR * 100 + ESP_IDF_VERSION_MINOR * 10 + ESP_IDF_VERSION_PATCH) < 432
return;
#else
uint16_t tx_time = (tx_octets + 14) * 8;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h
index 605445aab..19fecfdde 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEServer.h
@@ -25,7 +25,11 @@
#include "NimBLEUtils.h"
#include "NimBLEAddress.h"
+#if CONFIG_BT_NIMBLE_EXT_ADV
+#include "NimBLEExtAdvertising.h"
+#else
#include "NimBLEAdvertising.h"
+#endif
#include "NimBLEService.h"
#include "NimBLESecurity.h"
#include "NimBLEConnInfo.h"
@@ -46,11 +50,19 @@ public:
NimBLEService* createService(const NimBLEUUID &uuid);
void removeService(NimBLEService* service, bool deleteSvc = false);
void addService(NimBLEService* service);
- NimBLEAdvertising* getAdvertising();
void setCallbacks(NimBLEServerCallbacks* pCallbacks,
bool deleteCallbacks = true);
- void startAdvertising();
- void stopAdvertising();
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ NimBLEExtAdvertising* getAdvertising();
+ bool startAdvertising(uint8_t inst_id,
+ int duration = 0,
+ int max_events = 0);
+ bool stopAdvertising(uint8_t inst_id);
+#else
+ NimBLEAdvertising* getAdvertising();
+ bool startAdvertising();
+#endif
+ bool stopAdvertising();
void start();
NimBLEService* getServiceByUUID(const char* uuid, uint16_t instanceId = 0);
NimBLEService* getServiceByUUID(const NimBLEUUID &uuid, uint16_t instanceId = 0);
@@ -66,7 +78,9 @@ public:
NimBLEConnInfo getPeerInfo(size_t index);
NimBLEConnInfo getPeerInfo(const NimBLEAddress& address);
NimBLEConnInfo getPeerIDInfo(uint16_t id);
+#if !CONFIG_BT_NIMBLE_EXT_ADV || defined(_DOXYGEN_)
void advertiseOnDisconnect(bool);
+#endif
private:
NimBLEServer();
@@ -75,9 +89,15 @@ private:
friend class NimBLEService;
friend class NimBLEDevice;
friend class NimBLEAdvertising;
+#if CONFIG_BT_NIMBLE_EXT_ADV
+ friend class NimBLEExtAdvertising;
+ friend class NimBLEExtAdvertisementData;
+#endif
bool m_gattsStarted;
+#if !CONFIG_BT_NIMBLE_EXT_ADV
bool m_advertiseOnDisconnect;
+#endif
bool m_svcChanged;
NimBLEServerCallbacks* m_pServerCallbacks;
bool m_deleteCallbacks;
@@ -131,7 +151,7 @@ public:
* @brief Handle a client disconnection.
* This is called when a client discconnects.
* @param [in] pServer A pointer to the %BLE server that received the client disconnection.
- * @param [in] desc A pointer to the connection description structure containig information
+ * @param [in] desc A pointer to the connection description structure containing information
* about the connection.
*/
virtual void onDisconnect(NimBLEServer* pServer, ble_gap_conn_desc* desc);
@@ -139,7 +159,7 @@ public:
/**
* @brief Called when the connection MTU changes.
* @param [in] MTU The new MTU value.
- * @param [in] desc A pointer to the connection description structure containig information
+ * @param [in] desc A pointer to the connection description structure containing information
* about the connection.
*/
virtual void onMTUChange(uint16_t MTU, ble_gap_conn_desc* desc);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp
index 255f77177..b14eae160 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUUID.cpp
@@ -297,7 +297,7 @@ std::string NimBLEUUID::toString() const {
/**
- * @brief Convienience operator to check if this UUID is equal to another.
+ * @brief Convenience operator to check if this UUID is equal to another.
*/
bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
if(m_valueSet && rhs.m_valueSet) {
@@ -336,7 +336,7 @@ bool NimBLEUUID::operator ==(const NimBLEUUID & rhs) const {
/**
- * @brief Convienience operator to check if this UUID is not equal to another.
+ * @brief Convenience operator to check if this UUID is not equal to another.
*/
bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
return !this->operator==(rhs);
@@ -344,7 +344,7 @@ bool NimBLEUUID::operator !=(const NimBLEUUID & rhs) const {
/**
- * @brief Convienience operator to convert this UUID to string representation.
+ * @brief Convenience operator to convert this UUID to string representation.
* @details This allows passing NimBLEUUID to functions
* that accept std::string and/or or it's methods as a parameter.
*/
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp
index c6bd823ff..60ea541f2 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp
+++ b/lib/libesp32_div/NimBLE-Arduino/src/NimBLEUtils.cpp
@@ -355,7 +355,7 @@ const char* NimBLEUtils::returnCodeToString(int rc) {
* @return A string representation of the advertising flags.
*/
const char* NimBLEUtils::advTypeToString(uint8_t advType) {
-#if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
+#if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
switch(advType) {
case BLE_HCI_ADV_TYPE_ADV_IND : //0
return "Undirected - Connectable / Scannable";
@@ -370,10 +370,10 @@ const char* NimBLEUtils::advTypeToString(uint8_t advType) {
default:
return "Unknown flag";
}
-#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
+#else // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
(void)advType;
return "";
-#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT)
+#endif // #if defined(CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT)
} // adFlagsToString
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md b/lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md
index 37103be08..96c636634 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/README.md
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/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/lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md b/lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md
index 3bdd31ad0..99810a718 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/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/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h
index b1052e62e..4b32c8b15 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/console/console.h
@@ -7,7 +7,7 @@
extern "C" {
#endif
-#define console_printf printf
+#define console_printf(_fmt, ...) printf(_fmt, ##__VA_ARGS__)
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h
index 46fdcc551..fb00ae115 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h
@@ -922,6 +922,10 @@
#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
@@ -1043,6 +1047,10 @@
#endif
#endif
+#ifndef MYNEWT_VAL_BLE_MESH_CDB
+#define MYNEWT_VAL_BLE_MESH_CDB (0)
+#endif
+
#ifndef MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL
#define MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL (1)
#endif
@@ -1088,6 +1096,14 @@
#define MYNEWT_VAL_BLE_MESH_RX_SDU_MAX (72)
#endif
+#ifndef MYNEWT_VAL_BLE_MESH_SEG_BUFS
+#define MYNEWT_VAL_BLE_MESH_SEG_BUFS (72)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MAX
+#define MYNEWT_VAL_BLE_MESH_RX_SEG_MAX (3)
+#endif
+
#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT
#define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (2)
#endif
@@ -1100,6 +1116,63 @@
#define MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE (128)
#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_PB_ADV_RETRANS_TIMEOUT
+#define MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT (500)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_RELAY_ENABLED
+#define MYNEWT_VAL_BLE_MESH_RELAY_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_FRIEND_ENABLED
+#define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_BEACON_ENABLED
+#define MYNEWT_VAL_BLE_MESH_BEACON_ENABLED (1)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL
+#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20)
+#endif
+
/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */
#ifndef MYNEWT_VAL_BLE_MESH_SETTINGS
#define MYNEWT_VAL_BLE_MESH_SETTINGS (0)
@@ -1158,6 +1231,10 @@
#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (4)
#endif
+#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 */
#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT
#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0)
@@ -1370,6 +1447,18 @@
#define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1)
#endif
+#ifndef CONFIG_BLE_TX_CCA_ENABLED
+#define MYNEWT_VAL_BLE_TX_CCA_ENABLED (0)
+#else
+#define MYNEWT_VAL_BLE_TX_CCA_ENABLED (CONFIG_BLE_TX_CCA_ENABLED)
+#endif
+
+#ifndef CONFIG_BLE_CCA_RSSI_THRESH
+#define MYNEWT_VAL_BLE_CCA_RSSI_THRESH (50)
+#else
+#define MYNEWT_VAL_BLE_CCA_RSSI_THRESH (CONFIG_BLE_CCA_RSSI_THRESH)
+#endif
+
#ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG
#define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1)
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c
new file mode 100644
index 000000000..7e1899db6
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c
@@ -0,0 +1,44 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef ESP_PLATFORM
+
+#include "esp_attr.h"
+#include "esp_heap_caps.h"
+#include "nimconfig.h"
+#include "../include/esp_nimble_mem.h"
+
+IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
+{
+#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
+ return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
+ return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
+#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
+ return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+#else
+ return malloc(size);
+#endif
+}
+
+IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
+{
+#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
+ return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
+ return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
+#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
+ return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+#else
+ return calloc(n, size);
+#endif
+}
+
+IRAM_ATTR void nimble_platform_mem_free(void *ptr)
+{
+ heap_caps_free(ptr);
+}
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.cpp b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.cpp
deleted file mode 100644
index 407091c7f..000000000
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#ifdef ESP_PLATFORM
-
-#include "esp_attr.h"
-#include "esp_heap_caps.h"
-#include "nimconfig.h"
-#include "../include/esp_nimble_mem.h"
-
-//Tasmota Patch
-extern void *special_malloc(uint32_t size);
-extern void *special_calloc(size_t num, size_t size);
-
-
-extern "C" {
-IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
-{
- return special_malloc((uint32_t)size);
-// #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
-// return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
-// return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
-// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
-// return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-// #else
-// return malloc(size);
-// #endif
-}
-
-IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
-{
- return special_calloc(n,size);
-// #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
-// return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
-// return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
-// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
-// return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-// #else
-// return calloc(n, size);
-// #endif
-}
-
-IRAM_ATTR void nimble_platform_mem_free(void *ptr)
-{
- heap_caps_free(ptr);
-}
-} //extern "C"
-#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h
index 3b165a706..a289ed00b 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll.h
@@ -69,6 +69,29 @@ extern "C" {
/* Timing jitter as per spec is +/16 usecs */
#define BLE_LL_JITTER_USECS (16)
+
+#if MYNEWT_VAL(BLE_LL_SCA) < 0
+#error Invalid SCA value
+#elif MYNEWT_VAL(BLE_LL_SCA) <= 20
+#define BLE_LL_SCA_ENUM 7
+#elif MYNEWT_VAL(BLE_LL_SCA) <= 30
+#define BLE_LL_SCA_ENUM 6
+#elif MYNEWT_VAL(BLE_LL_SCA) <= 50
+#define BLE_LL_SCA_ENUM 5
+#elif MYNEWT_VAL(BLE_LL_SCA) <= 75
+#define BLE_LL_SCA_ENUM 4
+#elif MYNEWT_VAL(BLE_LL_SCA) <= 100
+#define BLE_LL_SCA_ENUM 3
+#elif MYNEWT_VAL(BLE_LL_SCA) <= 150
+#define BLE_LL_SCA_ENUM 2
+#elif MYNEWT_VAL(BLE_LL_SCA) <= 250
+#define BLE_LL_SCA_ENUM 1
+#elif MYNEWT_VAL(BLE_LL_SCA) <= 500
+#define BLE_LL_SCA_ENUM 0
+#else
+#error Invalid SCA value
+#endif
+
/* Packet queue header definition */
STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr);
@@ -373,6 +396,12 @@ struct ble_dev_addr
#define BLE_LL_LLID_DATA_START (2)
#define BLE_LL_LLID_CTRL (3)
+#define BLE_LL_LLID_IS_CTRL(hdr) \
+ (((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL)
+#define BLE_LL_LLID_IS_DATA(hdr) \
+ ((((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_START) || \
+ (((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_FRAG))
+
/*
* CONNECT_REQ
* -> InitA (6 bytes)
@@ -415,6 +444,14 @@ struct ble_dev_addr
#define BLE_LL_ADDR_SUBTYPE_RPA (1)
#define BLE_LL_ADDR_SUBTYPE_NRPA (2)
+/* ACAD data types */
+#define BLE_LL_ACAD_CHANNEL_MAP_UPDATE_IND 0x28
+
+struct ble_ll_acad_channel_map_update_ind {
+ uint8_t map[5];
+ uint16_t instant;
+} __attribute__((packed));
+
/*--- External API ---*/
/* Initialize the Link Layer */
void ble_ll_init(void);
@@ -545,6 +582,7 @@ void ble_ll_rand_sample(uint8_t rnum);
int ble_ll_rand_data_get(uint8_t *buf, uint8_t len);
void ble_ll_rand_prand_get(uint8_t *prand);
int ble_ll_rand_start(void);
+uint32_t ble_ll_rand(void);
static inline int
ble_ll_get_addr_type(uint8_t txrxflag)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h
index 178d67117..34512a1a4 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_conn.h
@@ -58,6 +58,8 @@ extern "C" {
/* Definition for RSSI when the RSSI is unknown */
#define BLE_LL_CONN_UNKNOWN_RSSI (127)
+#define BLE_LL_CONN_HANDLE_ISO_OFFSET (0x0100)
+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
/*
* Encryption states for a connection
@@ -69,6 +71,7 @@ extern "C" {
enum conn_enc_state {
CONN_ENC_S_UNENCRYPTED = 1,
CONN_ENC_S_ENCRYPTED,
+ CONN_ENC_S_ENC_RSP_TO_BE_SENT,
CONN_ENC_S_ENC_RSP_WAIT,
CONN_ENC_S_PAUSE_ENC_RSP_WAIT,
CONN_ENC_S_PAUSED,
@@ -270,6 +273,10 @@ struct ble_ll_conn_sm
uint8_t last_rxd_hdr_byte; /* note: possibly can make 1 bit since we
only use the MD bit now */
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+ uint16_t cth_flow_pending;
+#endif
+
/* connection event mgmt */
uint8_t reject_reason;
uint8_t host_reply_opcode;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h
index b0da1e736..15a45b2a0 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -39,7 +39,9 @@ extern "C" {
#define BLE_LL_CTRL_PROC_LE_PING (7)
#define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8)
#define BLE_LL_CTRL_PROC_PHY_UPDATE (9)
-#define BLE_LL_CTRL_PROC_NUM (10)
+#define BLE_LL_CTRL_PROC_SCA_UPDATE (10)
+#define BLE_LL_CTRL_PROC_CIS_CREATE (11)
+#define BLE_LL_CTRL_PROC_NUM (12)
#define BLE_LL_CTRL_PROC_IDLE (255)
/* Checks if a particular control procedure is running */
@@ -54,45 +56,51 @@ extern "C" {
* -> Opcode (1 byte)
* -> Data (0 - 26 bytes)
*/
-#define BLE_LL_CTRL_CONN_UPDATE_IND (0)
-#define BLE_LL_CTRL_CHANNEL_MAP_REQ (1)
-#define BLE_LL_CTRL_TERMINATE_IND (2)
-#define BLE_LL_CTRL_ENC_REQ (3)
-#define BLE_LL_CTRL_ENC_RSP (4)
-#define BLE_LL_CTRL_START_ENC_REQ (5)
-#define BLE_LL_CTRL_START_ENC_RSP (6)
-#define BLE_LL_CTRL_UNKNOWN_RSP (7)
-#define BLE_LL_CTRL_FEATURE_REQ (8)
-#define BLE_LL_CTRL_FEATURE_RSP (9)
-#define BLE_LL_CTRL_PAUSE_ENC_REQ (10)
-#define BLE_LL_CTRL_PAUSE_ENC_RSP (11)
-#define BLE_LL_CTRL_VERSION_IND (12)
-#define BLE_LL_CTRL_REJECT_IND (13)
-#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (14)
-#define BLE_LL_CTRL_CONN_PARM_REQ (15)
-#define BLE_LL_CTRL_CONN_PARM_RSP (16)
-#define BLE_LL_CTRL_REJECT_IND_EXT (17)
-#define BLE_LL_CTRL_PING_REQ (18)
-#define BLE_LL_CTRL_PING_RSP (19)
-#define BLE_LL_CTRL_LENGTH_REQ (20)
-#define BLE_LL_CTRL_LENGTH_RSP (21)
-#define BLE_LL_CTRL_PHY_REQ (22)
-#define BLE_LL_CTRL_PHY_RSP (23)
-#define BLE_LL_CTRL_PHY_UPDATE_IND (24)
-#define BLE_LL_CTRL_MIN_USED_CHAN_IND (25)
-#define BLE_LL_CTRL_CTE_REQ (26)
-#define BLE_LL_CTRL_CTE_RSP (27)
-#define BLE_LL_CTRL_PERIODIC_SYNC_IND (28)
-#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (29)
-#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (30)
+#define BLE_LL_CTRL_CONN_UPDATE_IND (0x00)
+#define BLE_LL_CTRL_CHANNEL_MAP_REQ (0x01)
+#define BLE_LL_CTRL_TERMINATE_IND (0x02)
+#define BLE_LL_CTRL_ENC_REQ (0x03)
+#define BLE_LL_CTRL_ENC_RSP (0x04)
+#define BLE_LL_CTRL_START_ENC_REQ (0x05)
+#define BLE_LL_CTRL_START_ENC_RSP (0x06)
+#define BLE_LL_CTRL_UNKNOWN_RSP (0x07)
+#define BLE_LL_CTRL_FEATURE_REQ (0x08)
+#define BLE_LL_CTRL_FEATURE_RSP (0x09)
+#define BLE_LL_CTRL_PAUSE_ENC_REQ (0x0A)
+#define BLE_LL_CTRL_PAUSE_ENC_RSP (0x0B)
+#define BLE_LL_CTRL_VERSION_IND (0x0C)
+#define BLE_LL_CTRL_REJECT_IND (0x0D)
+#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (0x0E)
+#define BLE_LL_CTRL_CONN_PARM_REQ (0x0F)
+#define BLE_LL_CTRL_CONN_PARM_RSP (0x10)
+#define BLE_LL_CTRL_REJECT_IND_EXT (0x11)
+#define BLE_LL_CTRL_PING_REQ (0x12)
+#define BLE_LL_CTRL_PING_RSP (0x13)
+#define BLE_LL_CTRL_LENGTH_REQ (0x14)
+#define BLE_LL_CTRL_LENGTH_RSP (0x15)
+#define BLE_LL_CTRL_PHY_REQ (0x16)
+#define BLE_LL_CTRL_PHY_RSP (0x17)
+#define BLE_LL_CTRL_PHY_UPDATE_IND (0x18)
+#define BLE_LL_CTRL_MIN_USED_CHAN_IND (0x19)
+#define BLE_LL_CTRL_CTE_REQ (0x1A)
+#define BLE_LL_CTRL_CTE_RSP (0x1B)
+#define BLE_LL_CTRL_PERIODIC_SYNC_IND (0x1C)
+#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (0x1D)
+#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (0x1E)
+#define BLE_LL_CTRL_CIS_REQ (0x1F)
+#define BLE_LL_CTRL_CIS_RSP (0x20)
+#define BLE_LL_CTRL_CIS_IND (0x21)
+#define BLE_LL_CTRL_CIS_TERMINATE_IND (0x22)
/* Maximum opcode value */
-#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CLOCK_ACCURACY_RSP + 1)
+#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CIS_TERMINATE_IND + 1)
extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES];
/* Maximum LL control PDU size */
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
+#if MYNEWT_VAL(BLE_ISO)
+#define BLE_LL_CTRL_MAX_PDU_LEN (42)
+#elif MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
#define BLE_LL_CTRL_MAX_PDU_LEN (35)
#else
#define BLE_LL_CTRL_MAX_PDU_LEN (27)
@@ -261,6 +269,12 @@ struct ble_ll_len_req
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN (1)
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN (1)
+/* BLE ISO */
+#define BLE_LL_CTRL_CIS_REQ_LEN (42)
+#define BLE_LL_CTRL_CIS_RSP_LEN (8)
+#define BLE_LL_CTRL_CIS_IND_LEN (15)
+#define BLE_LL_CTRL_CIS_TERMINATE_LEN (3)
+
/* API */
struct ble_ll_conn_sm;
void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc);
@@ -306,6 +320,11 @@ void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line);
uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask);
uint8_t ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask);
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+void ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm,
+ uint8_t status, uint8_t peer_sca);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h
index 5806f6737..9f51edf7a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_hci.h
@@ -27,7 +27,7 @@ extern "C" {
#include "nimble/nimble/include/nimble/hci_common.h"
/* For supported commands */
-#define BLE_LL_SUPP_CMD_LEN (42)
+#define BLE_LL_SUPP_CMD_LEN (45)
extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN];
/* The largest event the controller will send. */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_iso.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_iso.h
new file mode 100644
index 000000000..2944b0747
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_ll_iso.h
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_LL_ISO
+#define H_BLE_LL_ISO
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
+int ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
+int ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
+int ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
+int ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h
index 8a6fd174e..49bb14ad4 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/include/controller/ble_phy.h
@@ -225,6 +225,8 @@ static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options)
if (phy == BLE_PHY_CODED && phy_options == BLE_HCI_LE_PHY_CODED_S2_PREF) {
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
}
+#else
+ (void)phy_options;
#endif
return phy_mode;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c
index 651393ee2..9e4cf41c2 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c
@@ -248,9 +248,6 @@ uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
/** Our random address */
uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
-/** Our supported features which can be controller by the host */
-uint64_t g_ble_ll_supported_host_features = 0;
-
static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] =
{
[BLE_PHY_MODE_1M] =
@@ -715,6 +712,7 @@ ble_ll_tx_pkt_in(void)
uint16_t pb;
struct os_mbuf_pkthdr *pkthdr;
struct os_mbuf *om;
+ os_sr_t sr;
/* Drain all packets off the queue */
while (STAILQ_FIRST(&g_ble_ll_data.ll_tx_pkt_q)) {
@@ -723,7 +721,9 @@ ble_ll_tx_pkt_in(void)
om = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf));
/* Remove from queue */
+ OS_ENTER_CRITICAL(sr);
STAILQ_REMOVE_HEAD(&g_ble_ll_data.ll_tx_pkt_q, omp_next);
+ OS_EXIT_CRITICAL(sr);
/* Strip HCI ACL header to get handle and length */
handle = get_le16(om->om_data);
@@ -1210,8 +1210,6 @@ ble_ll_task(void *arg)
/* Tell the host that we are ready to receive packets */
ble_ll_hci_send_noop();
- ble_ll_rand_start();
-
while (1) {
ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER);
assert(ev);
@@ -1309,10 +1307,6 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len)
mask = (uint64_t)1 << (cmd->bit_num);
if (!(mask & BLE_LL_HOST_CONTROLLED_FEATURES)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
-
- if (!(mask & g_ble_ll_supported_host_features)) {
return BLE_ERR_UNSUPPORTED;
}
@@ -1376,6 +1370,20 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr)
ble_hdr->txinfo.hdr_byte = hdr;
}
+static void
+ble_ll_validate_task(void)
+{
+#ifdef MYNEWT
+#ifndef NDEBUG
+ struct os_task_info oti;
+
+ os_task_info_get(&g_ble_ll_task, &oti);
+
+ BLE_LL_ASSERT(oti.oti_stkusage < oti.oti_stksize);
+#endif
+#endif
+}
+
/**
* Called to reset the controller. This performs a "software reset" of the link
* layer; it does not perform a HW reset of the controller nor does it reset
@@ -1392,6 +1400,9 @@ ble_ll_reset(void)
int rc;
os_sr_t sr;
+ /* do sanity check on LL task stack */
+ ble_ll_validate_task();
+
OS_ENTER_CRITICAL(sr);
ble_phy_disable();
ble_ll_sched_stop();
@@ -1451,23 +1462,6 @@ ble_ll_reset(void)
return rc;
}
-static void
-ble_ll_seed_prng(void)
-{
- uint32_t seed;
- int i;
-
- /* Seed random number generator with least significant bytes of device
- * address.
- */
- seed = 0;
- for (i = 0; i < 4; ++i) {
- seed |= g_dev_addr[i];
- seed <<= 8;
- }
- srand(seed);
-}
-
uint32_t
ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode)
{
@@ -1685,16 +1679,24 @@ ble_ll_init(void)
features |= BLE_LL_FEAT_SYNC_TRANS_SEND;
#endif
- /* Initialize random number generation */
- ble_ll_rand_init();
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+ features |= BLE_LL_FEAT_SCA_UPDATE;
+#endif
- /* XXX: This really doesn't belong here, as the address probably has not
- * been set yet.
- */
- ble_ll_seed_prng();
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+ features |= BLE_LL_FEAT_CIS_MASTER;
+ features |= BLE_LL_FEAT_CIS_SLAVE;
+ features |= BLE_LL_FEAT_ISO_BROADCASTER;
+ features |= BLE_LL_FEAT_ISO_HOST_SUPPORT;
+#endif
lldata->ll_supp_features = features;
+ /* Initialize random number generation */
+ ble_ll_rand_init();
+ /* Start the random number generator */
+ ble_ll_rand_start();
+
rc = stats_init_and_reg(STATS_HDR(ble_ll_stats),
STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32),
STATS_NAME_INIT_PARMS(ble_ll_stats),
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c
index 83fd2506c..4e1b74887 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c
@@ -144,6 +144,7 @@ struct ble_ll_adv_sm
uint8_t aux_index : 1;
uint8_t aux_first_pdu : 1;
uint8_t aux_not_scanned : 1;
+ uint8_t aux_dropped : 1;
struct ble_mbuf_hdr *rx_ble_hdr;
struct os_mbuf **aux_data;
struct ble_ll_adv_aux aux[2];
@@ -698,7 +699,7 @@ ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm,
dptr[8] = advsm->periodic_chanmap[4] & 0x1f;
/* SCA (3 bits) */
- dptr[8] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
+ dptr[8] |= BLE_LL_SCA_ENUM << 5;
/* AA (4 bytes) */
put_le32(&dptr[9], advsm->periodic_access_addr);
@@ -1282,7 +1283,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
rc = ble_phy_tx_set_start_time(txstart, sch->remainder);
if (rc) {
STATS_INC(ble_ll_stats, adv_late_starts);
- goto adv_tx_done;
+ goto adv_aux_dropped;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
@@ -1317,7 +1318,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
/* Transmit advertisement */
rc = ble_phy_tx(pducb, advsm, end_trans);
if (rc) {
- goto adv_tx_done;
+ goto adv_aux_dropped;
}
/* Enable/disable whitelisting based on filter policy */
@@ -1335,7 +1336,8 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
return BLE_LL_SCHED_STATE_RUNNING;
-adv_tx_done:
+adv_aux_dropped:
+ advsm->aux_dropped = 1;
ble_ll_adv_tx_done(advsm);
return BLE_LL_SCHED_STATE_DONE;
}
@@ -1390,7 +1392,7 @@ ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm,
g_ble_ll_conn_params.num_used_chans,
g_ble_ll_conn_params.master_chan_map);
#else
- aux->chan = ble_ll_utils_remapped_channel(rand() % BLE_PHY_NUM_DATA_CHANS,
+ aux->chan = ble_ll_utils_remapped_channel(ble_ll_rand() % BLE_PHY_NUM_DATA_CHANS,
g_ble_ll_conn_params.master_chan_map);
#endif
@@ -1567,6 +1569,7 @@ ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm)
advsm->aux_index = 0;
advsm->aux_first_pdu = 1;
advsm->aux_not_scanned = 0;
+ advsm->aux_dropped = 0;
aux = AUX_CURRENT(advsm);
ble_ll_adv_aux_calculate(advsm, aux, 0);
@@ -1866,7 +1869,7 @@ ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm)
* the previously used value.
*/
do {
- advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff);
+ advsm->adi = (advsm->adi & 0xf000) | (ble_ll_rand() & 0x0fff);
} while (old_adi == advsm->adi);
}
#endif
@@ -2557,11 +2560,11 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm)
advsm->periodic_num_used_chans = g_ble_ll_conn_params.num_used_chans;
advsm->periodic_event_cntr = 0;
/* for chaining we start with random counter as we share access addr */
- advsm->periodic_chain_event_cntr = rand();
+ advsm->periodic_chain_event_cntr = ble_ll_rand();
advsm->periodic_access_addr = ble_ll_utils_calc_access_addr();
advsm->periodic_channel_id = ((advsm->periodic_access_addr & 0xffff0000) >> 16) ^
(advsm->periodic_access_addr & 0x0000ffff);
- advsm->periodic_crcinit = rand() & 0xffffff;
+ advsm->periodic_crcinit = ble_ll_rand() & 0xffffff;
usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL;
ticks = os_cputime_usecs_to_ticks(usecs);
@@ -2750,7 +2753,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
*/
earliest_start_time = ble_ll_rfmgmt_enable_now();
- start_delay_us = rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
+ start_delay_us = ble_ll_rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
advsm->adv_pdu_start_time = os_cputime_get32() +
os_cputime_usecs_to_ticks(start_delay_us);
@@ -4032,8 +4035,8 @@ ble_ll_adv_periodic_send_sync_ind(struct ble_ll_adv_sm *advsm,
/* SID, AType, SCA */
sync_ind[24] = (advsm->adi >> 12);
- sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4 ;
- sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
+ sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4;
+ sync_ind[24] |= BLE_LL_SCA_ENUM << 5;
/* PHY */
sync_ind[25] = (0x01 << (advsm->sec_phy - 1));
@@ -4849,6 +4852,11 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
/* We don't need RF anymore */
ble_ll_rfmgmt_release();
+ if (advsm->aux_dropped) {
+ ble_ll_adv_drop_event(advsm);
+ return;
+ }
+
if (advsm->aux_not_scanned) {
ble_ll_sched_rmv_elem(&aux_next->sch);
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c
index b3788de1d..c77e9a8b1 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c
@@ -232,6 +232,166 @@ STATS_NAME_END(ble_ll_conn_stats)
static void ble_ll_conn_event_end(struct ble_npl_event *ev);
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+struct ble_ll_conn_cth_flow {
+ bool enabled;
+ uint16_t max_buffers;
+ uint16_t num_buffers;
+};
+
+static struct ble_ll_conn_cth_flow g_ble_ll_conn_cth_flow;
+
+static struct ble_npl_event g_ble_ll_conn_cth_flow_error_ev;
+
+static bool
+ble_ll_conn_cth_flow_is_enabled(void)
+{
+ return g_ble_ll_conn_cth_flow.enabled;
+}
+
+static bool
+ble_ll_conn_cth_flow_alloc_credit(struct ble_ll_conn_sm *connsm)
+{
+ struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
+ os_sr_t sr;
+
+ OS_ENTER_CRITICAL(sr);
+
+ if (!cth->num_buffers) {
+ OS_EXIT_CRITICAL(sr);
+ return false;
+ }
+
+ connsm->cth_flow_pending++;
+ cth->num_buffers--;
+
+ OS_EXIT_CRITICAL(sr);
+
+ return true;
+}
+
+static void
+ble_ll_conn_cth_flow_free_credit(struct ble_ll_conn_sm *connsm, uint16_t credits)
+{
+ struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
+ os_sr_t sr;
+
+ OS_ENTER_CRITICAL(sr);
+
+ /*
+ * It's not quite clear what we should do if host gives back more credits
+ * that we have allocated. For now let's just set invalid values back to
+ * sane values and continue.
+ */
+
+ cth->num_buffers += credits;
+ if (cth->num_buffers > cth->max_buffers) {
+ cth->num_buffers = cth->max_buffers;
+ }
+
+ if (connsm->cth_flow_pending < credits) {
+ connsm->cth_flow_pending = 0;
+ } else {
+ connsm->cth_flow_pending -= credits;
+ }
+
+ OS_EXIT_CRITICAL(sr);
+}
+
+static void
+ble_ll_conn_cth_flow_error_fn(struct ble_npl_event *ev)
+{
+ struct ble_hci_ev *hci_ev;
+ struct ble_hci_ev_command_complete *hci_ev_cp;
+ uint16_t opcode;
+
+ hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+ if (!hci_ev) {
+ /* Not much we can do anyway... */
+ return;
+ }
+
+ /*
+ * We are here in case length of HCI_Host_Number_Of_Completed_Packets was
+ * invalid. We will send an error back to host and we can only hope host is
+ * reasonable and will do some actions to recover, e.g. it should disconnect
+ * all connections to guarantee that all credits are back in pool and we're
+ * back in sync (although spec does not really say what should happen).
+ */
+
+ opcode = BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
+ BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS);
+
+ hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE;
+ hci_ev->length = sizeof(*hci_ev_cp);
+
+ hci_ev_cp = (void *)hci_ev->data;
+ hci_ev_cp->num_packets = BLE_LL_CFG_NUM_HCI_CMD_PKTS;
+ hci_ev_cp->opcode = htole16(opcode);
+ hci_ev_cp->status = BLE_ERR_INV_HCI_CMD_PARMS;
+
+ ble_ll_hci_event_send(hci_ev);
+}
+
+void
+ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers)
+{
+ BLE_LL_ASSERT(num_buffers);
+
+ g_ble_ll_conn_cth_flow.max_buffers = num_buffers;
+ g_ble_ll_conn_cth_flow.num_buffers = num_buffers;
+}
+
+bool
+ble_ll_conn_cth_flow_enable(bool enabled)
+{
+ struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
+
+ if (cth->enabled == enabled) {
+ return true;
+ }
+
+ if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) {
+ return false;
+ }
+
+ cth->enabled = enabled;
+
+ return true;
+}
+
+void
+ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf)
+{
+ const struct ble_hci_cmd *cmd;
+ const struct ble_hci_cb_host_num_comp_pkts_cp *cp;
+ struct ble_ll_conn_sm *connsm;
+ int i;
+
+ cmd = (const void *)cmdbuf;
+ cp = (const void *)cmd->data;
+
+ if (cmd->length != sizeof(cp->handles) + cp->handles * sizeof(cp->h[0])) {
+ ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_conn_cth_flow_error_ev);
+ return;
+ }
+
+ for (i = 0; i < cp->handles; i++) {
+ /*
+ * It's probably ok that we do not have active connection with given
+ * handle - this can happen if disconnection already happened in LL but
+ * host sent credits back before processing disconnection event. In such
+ * case we can simply ignore command for that connection since credits
+ * are returned by LL already.
+ */
+ connsm = ble_ll_conn_find_active_conn(cp->h[i].handle);
+ if (connsm) {
+ ble_ll_conn_cth_flow_free_credit(connsm, cp->h[i].count);
+ }
+ }
+}
+#endif
+
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
/**
* Checks to see if we should start a PHY update procedure
@@ -339,7 +499,7 @@ ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2)
int rc;
/* Set time that we last serviced the schedule */
- if ((int32_t)(s1->last_scheduled - s2->last_scheduled) < 0) {
+ if (CPUTIME_LT(s1->last_scheduled, s2->last_scheduled)) {
rc = 1;
} else {
rc = 0;
@@ -862,8 +1022,14 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
/*
* If we are encrypting, we are only allowed to send certain
* kinds of LL control PDU's. If none is enqueued, send empty pdu!
+ *
+ * In Slave role, we are allowed to send unencrypted packets until
+ * LL_ENC_RSP is sent.
*/
- if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) {
+ if (((connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) &&
+ CONN_IS_MASTER(connsm)) ||
+ ((connsm->enc_data.enc_state > CONN_ENC_S_ENC_RSP_TO_BE_SENT) &&
+ CONN_IS_SLAVE(connsm))) {
if (!ble_ll_ctrl_enc_allowed_pdu_tx(pkthdr)) {
CONN_F_EMPTY_PDU_TXD(connsm) = 1;
goto conn_tx_pdu;
@@ -998,10 +1164,10 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
}
ticks = os_cputime_usecs_to_ticks(ticks);
- if ((int32_t)((os_cputime_get32() + ticks) - next_event_time) < 0) {
+ if (CPUTIME_LT(os_cputime_get32() + ticks, next_event_time)) {
md = 1;
}
- }
+ }
/* If we send an empty PDU we need to initialize the header */
conn_tx_pdu:
@@ -1457,10 +1623,10 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
*/
connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN + 1;
connsm->tx_win_off = 0;
- connsm->master_sca = MYNEWT_VAL(BLE_LL_MASTER_SCA);
+ connsm->master_sca = BLE_LL_SCA_ENUM;
/* Hop increment is a random value between 5 and 16. */
- connsm->hop_inc = (rand() % 12) + 5;
+ connsm->hop_inc = (ble_ll_rand() % 12) + 5;
/* Set channel map to map requested by host */
connsm->num_used_chans = g_ble_ll_conn_params.num_used_chans;
@@ -1469,7 +1635,7 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
/* Calculate random access address and crc initialization value */
connsm->access_addr = ble_ll_utils_calc_access_addr();
- connsm->crcinit = rand() & 0xffffff;
+ connsm->crcinit = ble_ll_rand() & 0xffffff;
/* Set initial schedule callback */
connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb;
@@ -1868,6 +2034,10 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
/* Remove from the active connection list */
SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+ ble_ll_conn_cth_flow_free_credit(connsm, connsm->cth_flow_pending);
+#endif
+
/* Free the current transmit pdu if there is one. */
if (connsm->cur_tx_pdu) {
os_mbuf_free_chain(connsm->cur_tx_pdu);
@@ -3246,6 +3416,13 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
*/
memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
}
+ } else if (!ble_ll_is_rpa(adv_addr, adv_addr_type)) {
+ /* undirected with ID address, assure privacy if on RL */
+ rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type);
+ if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
+ rl->rl_has_peer) {
+ goto init_rx_isr_exit;
+ }
}
#endif
@@ -3459,129 +3636,142 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
uint16_t acl_hdr;
struct ble_ll_conn_sm *connsm;
- if (BLE_MBUF_HDR_CRC_OK(hdr)) {
- /* XXX: there is a chance that the connection was thrown away and
- re-used before processing packets here. Fix this. */
- /* We better have a connection state machine */
- connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle);
- if (connsm) {
- /* Check state machine */
- ble_ll_conn_chk_csm_flags(connsm);
+ /* Packets with invalid CRC are not sent to LL */
+ BLE_LL_ASSERT(BLE_MBUF_HDR_CRC_OK(hdr));
- /* Validate rx data pdu */
- rxbuf = rxpdu->om_data;
- hdr_byte = rxbuf[0];
- acl_len = rxbuf[1];
- llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
+ /* XXX: there is a chance that the connection was thrown away and
+ re-used before processing packets here. Fix this. */
+ /* We better have a connection state machine */
+ connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle);
+ if (!connsm) {
+ STATS_INC(ble_ll_conn_stats, no_conn_sm);
+ goto conn_rx_data_pdu_end;
+ }
- /*
- * Check that the LLID and payload length are reasonable.
- * Empty payload is only allowed for LLID == 01b.
- * */
- if ((llid == 0) ||
- ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) {
- STATS_INC(ble_ll_conn_stats, rx_bad_llid);
- goto conn_rx_data_pdu_end;
- }
+ /* Check state machine */
+ ble_ll_conn_chk_csm_flags(connsm);
+
+ /* Validate rx data pdu */
+ rxbuf = rxpdu->om_data;
+ hdr_byte = rxbuf[0];
+ acl_len = rxbuf[1];
+ llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
+
+ /*
+ * Check that the LLID and payload length are reasonable.
+ * Empty payload is only allowed for LLID == 01b.
+ * */
+ if ((llid == 0) || ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) {
+ STATS_INC(ble_ll_conn_stats, rx_bad_llid);
+ goto conn_rx_data_pdu_end;
+ }
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
- /* Check if PDU is allowed when encryption is started. If not,
- * terminate connection.
- *
- * Reference: Core 5.0, Vol 6, Part B, 5.1.3.1
- */
- if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT) &&
- !ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) {
- ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
- goto conn_rx_data_pdu_end;
- }
+ /* Check if PDU is allowed when encryption is started. If not,
+ * terminate connection.
+ *
+ * Reference: Core 5.0, Vol 6, Part B, 5.1.3.1
+ */
+ if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT &&
+ CONN_IS_MASTER(connsm)) ||
+ (connsm->enc_data.enc_state >= CONN_ENC_S_ENC_RSP_TO_BE_SENT &&
+ CONN_IS_SLAVE(connsm))) {
+ if (!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) {
+ ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
+ goto conn_rx_data_pdu_end;
+ }
+ }
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
- /*
- * Reset authenticated payload timeout if valid MIC. NOTE: we dont
- * check the MIC failure bit as that would have terminated the
- * connection
- */
- if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) &&
- CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) {
- ble_ll_conn_auth_pyld_timer_start(connsm);
- }
+ /*
+ * Reset authenticated payload timeout if valid MIC. NOTE: we dont
+ * check the MIC failure bit as that would have terminated the
+ * connection
+ */
+ if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) &&
+ CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) {
+ ble_ll_conn_auth_pyld_timer_start(connsm);
+ }
#endif
- /* Update RSSI */
- connsm->conn_rssi = hdr->rxinfo.rssi;
+ /* Update RSSI */
+ connsm->conn_rssi = hdr->rxinfo.rssi;
- /*
- * If we are a slave, we can only start to use slave latency
- * once we have received a NESN of 1 from the master
- */
- if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
- if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) {
- connsm->csmflags.cfbit.allow_slave_latency = 1;
- }
- }
-
- /*
- * Discard the received PDU if the sequence number is the same
- * as the last received sequence number
- */
- rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK;
- if (rxd_sn != connsm->last_rxd_sn) {
- /* Update last rxd sn */
- connsm->last_rxd_sn = rxd_sn;
-
- /* No need to do anything if empty pdu */
- if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) {
- goto conn_rx_data_pdu_end;
- }
-
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
- /*
- * XXX: should we check to see if we are in a state where we
- * might expect to get an encrypted PDU?
- */
- if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) {
- STATS_INC(ble_ll_conn_stats, mic_failures);
- ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
- goto conn_rx_data_pdu_end;
- }
-#endif
-
- if (llid == BLE_LL_LLID_CTRL) {
- /* Process control frame */
- STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus);
- if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) {
- STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus);
- }
- } else {
- /* Count # of received l2cap frames and byes */
- STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus);
- STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len);
-
- /* NOTE: there should be at least two bytes available */
- BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2);
- os_mbuf_prepend(rxpdu, 2);
- rxbuf = rxpdu->om_data;
-
- acl_hdr = (llid << 12) | connsm->conn_handle;
- put_le16(rxbuf, acl_hdr);
- put_le16(rxbuf + 2, acl_len);
- ble_hci_trans_ll_acl_tx(rxpdu);
- }
-
- /* NOTE: we dont free the mbuf since we handed it off! */
- return;
- } else {
- STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup);
- }
- } else {
- STATS_INC(ble_ll_conn_stats, no_conn_sm);
+ /*
+ * If we are a slave, we can only start to use slave latency
+ * once we have received a NESN of 1 from the master
+ */
+ if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+ if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) {
+ connsm->csmflags.cfbit.allow_slave_latency = 1;
}
}
+ /*
+ * Discard the received PDU if the sequence number is the same
+ * as the last received sequence number
+ */
+ rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK;
+ if (rxd_sn == connsm->last_rxd_sn) {
+ STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup);
+ goto conn_rx_data_pdu_end;
+ }
+
+ /* Update last rxd sn */
+ connsm->last_rxd_sn = rxd_sn;
+
+ /* No need to do anything if empty pdu */
+ if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) {
+ goto conn_rx_data_pdu_end;
+ }
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
+ /*
+ * XXX: should we check to see if we are in a state where we
+ * might expect to get an encrypted PDU?
+ */
+ if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) {
+ STATS_INC(ble_ll_conn_stats, mic_failures);
+ ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
+ goto conn_rx_data_pdu_end;
+ }
+#endif
+
+ if (llid == BLE_LL_LLID_CTRL) {
+ /* Process control frame */
+ STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus);
+ if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) {
+ STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus);
+ }
+ } else {
+ /* Count # of received l2cap frames and byes */
+ STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus);
+ STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len);
+
+ /* NOTE: there should be at least two bytes available */
+ BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2);
+ os_mbuf_prepend(rxpdu, 2);
+ rxbuf = rxpdu->om_data;
+
+ acl_hdr = (llid << 12) | connsm->conn_handle;
+ put_le16(rxbuf, acl_hdr);
+ put_le16(rxbuf + 2, acl_len);
+ ble_hci_trans_ll_acl_tx(rxpdu);
+ }
+
+ /* NOTE: we dont free the mbuf since we handed it off! */
+ return;
+
/* Free buffer */
conn_rx_data_pdu_end:
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+ /* Need to give credit back if we allocated one for this PDU */
+ if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_CONN_CREDIT) {
+ ble_ll_conn_cth_flow_free_credit(connsm, 1);
+ }
+#endif
+
os_mbuf_free_chain(rxpdu);
}
@@ -3602,7 +3792,6 @@ int
ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
{
int rc;
- int is_ctrl;
uint8_t hdr_byte;
uint8_t hdr_sn;
uint8_t hdr_nesn;
@@ -3616,14 +3805,43 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
uint32_t add_usecs;
struct os_mbuf *txpdu;
struct ble_ll_conn_sm *connsm;
- struct os_mbuf *rxpdu;
+ struct os_mbuf *rxpdu = NULL;
struct ble_mbuf_hdr *txhdr;
int rx_phy_mode;
+ bool alloc_rxpdu = true;
+
+ rc = -1;
+ connsm = g_ble_ll_conn_cur_sm;
/* Retrieve the header and payload length */
hdr_byte = rxbuf[0];
rx_pyld_len = rxbuf[1];
+ /*
+ * No need to alloc rxpdu for packets with invalid CRC, we would throw them
+ * away instantly from LL anyway.
+ */
+ if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) {
+ alloc_rxpdu = false;
+ }
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+ /*
+ * If flow control is enabled, we need to have credit available for each
+ * non-empty data packet that LL may send to host. If there are no credits
+ * available, we don't need to allocate buffer for this packet so LL will
+ * nak it.
+ */
+ if (alloc_rxpdu && ble_ll_conn_cth_flow_is_enabled() &&
+ BLE_LL_LLID_IS_DATA(hdr_byte) && (rx_pyld_len > 0)) {
+ if (ble_ll_conn_cth_flow_alloc_credit(connsm)) {
+ rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT;
+ } else {
+ alloc_rxpdu = false;
+ }
+ }
+#endif
+
/*
* We need to attempt to allocate a buffer here. The reason we do this
* now is that we should not ack the packet if we have no receive
@@ -3631,14 +3849,14 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
* acked, but we should not ack the received frame if we cant hand it up.
* NOTE: we hand up empty pdu's to the LL task!
*/
- rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN);
+ if (alloc_rxpdu) {
+ rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN);
+ }
/*
* We should have a current connection state machine. If we dont, we just
* hand the packet to the higher layer to count it.
*/
- rc = -1;
- connsm = g_ble_ll_conn_cur_sm;
if (!connsm) {
STATS_INC(ble_ll_conn_stats, rx_data_pdu_no_conn);
goto conn_exit;
@@ -3700,9 +3918,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
/* Set last received header byte */
connsm->last_rxd_hdr_byte = hdr_byte;
- is_ctrl = 0;
- if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) {
- is_ctrl = 1;
+ if (BLE_LL_LLID_IS_CTRL(hdr_byte)) {
opcode = rxbuf[2];
}
@@ -3791,7 +4007,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
/* Adjust payload for max TX time and octets */
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
- if (is_ctrl &&
+ if (BLE_LL_LLID_IS_CTRL(hdr_byte) &&
(connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) &&
(opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) {
connsm->phy_tx_transition =
@@ -3810,8 +4026,9 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
/* If this is a TERMINATE_IND, we have to reply */
chk_rx_terminate_ind:
/* If we received a terminate IND, we must set some flags */
- if (is_ctrl && (opcode == BLE_LL_CTRL_TERMINATE_IND)
- && (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) {
+ if (BLE_LL_LLID_IS_CTRL(hdr_byte) &&
+ (opcode == BLE_LL_CTRL_TERMINATE_IND) &&
+ (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) {
connsm->csmflags.cfbit.terminate_ind_rxd = 1;
connsm->rxd_disconnect_reason = rxbuf[3];
}
@@ -4233,6 +4450,12 @@ ble_ll_conn_module_reset(void)
g_ble_ll_conn_sync_transfer_params.mode = 0;
g_ble_ll_conn_sync_transfer_params.sync_timeout_us = 0;
#endif
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+ g_ble_ll_conn_cth_flow.enabled = false;
+ g_ble_ll_conn_cth_flow.max_buffers = 1;
+ g_ble_ll_conn_cth_flow.num_buffers = 1;
+#endif
}
/* Initialize the connection module */
@@ -4272,6 +4495,11 @@ ble_ll_conn_module_init(void)
"ble_ll_conn");
BLE_LL_ASSERT(rc == 0);
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+ ble_npl_event_init(&g_ble_ll_conn_cth_flow_error_ev,
+ ble_ll_conn_cth_flow_error_fn, NULL);
+#endif
+
/* Call reset to finish reset of initialization */
ble_ll_conn_module_reset();
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c
index 19ceebf50..78cac66f5 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_hci.c
@@ -1129,16 +1129,11 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
* @return int
*/
int
-ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len)
+ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd)
{
int rc;
uint16_t handle;
struct ble_ll_conn_sm *connsm;
- const struct ble_hci_lc_disconnect_cp *cmd = (const void *) cmdbuf;
-
- if (len != sizeof (*cmd)) {
- return BLE_ERR_INV_HCI_CMD_PARMS;
- }
/* Check for valid parameters */
handle = le16toh(cmd->conn_handle);
@@ -1566,6 +1561,34 @@ ltk_key_cmd_complete:
}
#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+int
+ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
+ uint8_t *rspbuf, uint8_t *rsplen)
+{
+ const struct ble_hci_le_request_peer_sca_cp *params = (const void *)cmdbuf;
+ struct ble_ll_conn_sm *connsm;
+
+ connsm = ble_ll_conn_find_active_conn(params->conn_handle);
+ if (!connsm) {
+ return BLE_ERR_UNK_CONN_ID;
+ }
+
+ if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SCA_UPDATE >> 24))) {
+ return BLE_ERR_UNSUPP_REM_FEATURE;
+ }
+
+ if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE)) {
+ /* Not really specified what we should return */
+ return BLE_ERR_CTLR_BUSY;
+ }
+
+ ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
+
+ return 0;
+}
+#endif
+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
/**
* Read authenticated payload timeout (OGF=3, OCF==0x007B)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h
index e4ade10f9..93a478c42 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn_priv.h
@@ -164,7 +164,7 @@ bool ble_ll_conn_init_pending_aux_conn_rsp(void);
void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
uint8_t reason);
void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
-int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len);
+int ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len);
@@ -196,12 +196,23 @@ int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+int ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
+ uint8_t *rspbuf, uint8_t *rsplen);
+#endif
+
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
#else
#define ble_ll_conn_auth_pyld_timer_start(x)
#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+void ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers);
+bool ble_ll_conn_cth_flow_enable(bool enabled);
+void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf);
+#endif
+
int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c
index 37b9e68f4..64bd1543c 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c
@@ -114,6 +114,10 @@ const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] =
BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN,
BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN,
BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN,
+ BLE_LL_CTRL_CIS_REQ_LEN,
+ BLE_LL_CTRL_CIS_RSP_LEN,
+ BLE_LL_CTRL_CIS_IND_LEN,
+ BLE_LL_CTRL_CIS_TERMINATE_LEN
};
/**
@@ -508,6 +512,12 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *
ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE;
break;
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+ case BLE_LL_CTRL_CLOCK_ACCURACY_REQ:
+ ble_ll_hci_ev_sca_update(connsm, BLE_ERR_UNSUPPORTED, 0);
+ ctrl_proc = BLE_LL_CTRL_PROC_SCA_UPDATE;
+ break;
#endif
default:
ctrl_proc = BLE_LL_CTRL_PROC_NUM;
@@ -839,6 +849,20 @@ ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
}
}
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+/**
+ * Create a LL_CLOCK_ACCURACY_REQ or LL_CLOCK_ACCURACY_RSP pdu
+ *
+ * @param connsm Pointer to connection state machine
+ * @param ctrdata: Pointer to where CtrData starts in pdu
+ */
+static void
+ble_ll_ctrl_sca_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
+{
+ ctrdata[0] = BLE_LL_SCA_ENUM;
+}
+#endif
+
static uint8_t
ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req,
uint8_t *rsp)
@@ -1043,11 +1067,70 @@ ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
connsm->sync_transfer_skip,
connsm->sync_transfer_sync_timeout);
}
-
return BLE_ERR_MAX;
}
#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+/**
+ * Called when a BLE_LL_CTRL_CLOCK_ACCURACY_REQ PDU is received
+ *
+ * @param connsm
+ * @param dptr
+ * @param rsp Pointer to CtrData of BLE_LL_CTRL_CLOCK_ACCURACY_RSP.
+ *
+ * @return uint8_t
+ */
+static uint8_t
+ble_ll_ctrl_rx_sca_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
+ uint8_t *rsp)
+{
+ ble_ll_ctrl_sca_req_rsp_make(connsm, rsp);
+ return BLE_LL_CTRL_CLOCK_ACCURACY_RSP;
+}
+
+/**
+ * Called when a BLE_LL_CTRL_CLOCK_ACCURACY_RSP PDU is received
+ *
+ * @param connsm
+ * @param dptr
+ *
+ * @return uint8_t
+ */
+static uint8_t
+ble_ll_ctrl_rx_sca_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
+{
+ if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_SCA_UPDATE) {
+ return BLE_LL_CTRL_UNKNOWN_RSP;
+ }
+ ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
+ ble_ll_hci_ev_sca_update(connsm, BLE_ERR_SUCCESS, dptr[0]);
+ return BLE_ERR_MAX;
+}
+
+#endif
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+static uint8_t
+ble_ll_ctrl_rx_cis_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
+ uint8_t *rspdata)
+{
+ return BLE_LL_CTRL_UNKNOWN_RSP;
+}
+
+static uint8_t
+ble_ll_ctrl_rx_cis_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
+ uint8_t *rspdata)
+{
+ return BLE_LL_CTRL_UNKNOWN_RSP;
+}
+
+static uint8_t
+ble_ll_ctrl_rx_cis_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
+{
+ return BLE_LL_CTRL_UNKNOWN_RSP;
+}
+#endif
/**
* Create a link layer length request or length response PDU.
*
@@ -1253,6 +1336,15 @@ ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm)
return rc;
}
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+static void
+ble_ll_ctrl_cis_create(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
+{
+ /* TODO Implement */
+ return;
+}
+#endif
+
/**
* Create a link layer control "encrypt request" PDU.
*
@@ -1354,7 +1446,7 @@ ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
return BLE_LL_CTRL_UNKNOWN_RSP;
}
- connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
+ connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_TO_BE_SENT;
/* In case we were already encrypted we need to reset packet counters */
connsm->enc_data.rx_pkt_cntr = 0;
@@ -1679,6 +1771,12 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
*/
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
break;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+ case BLE_LL_CTRL_PROC_SCA_UPDATE:
+ ble_ll_hci_ev_sca_update(connsm, ble_error, 0);
+ ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
+ break;
+#endif
default:
break;
}
@@ -2141,6 +2239,18 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
opcode = BLE_LL_CTRL_PHY_REQ;
ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata);
break;
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+ case BLE_LL_CTRL_PROC_SCA_UPDATE:
+ opcode = BLE_LL_CTRL_CLOCK_ACCURACY_REQ;
+ ble_ll_ctrl_sca_req_rsp_make(connsm, ctrdata);
+ break;
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+ case BLE_LL_CTRL_PROC_CIS_CREATE:
+ opcode = BLE_LL_CTRL_CIS_REQ;
+ ble_ll_ctrl_cis_create(connsm, ctrdata);
+ break;
#endif
default:
BLE_LL_ASSERT(0);
@@ -2571,6 +2681,26 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
rsp_opcode = ble_ll_ctrl_rx_phy_update_ind(connsm, dptr);
break;
#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+ case BLE_LL_CTRL_CLOCK_ACCURACY_REQ:
+ rsp_opcode = ble_ll_ctrl_rx_sca_req(connsm, dptr, rspdata);
+ break;
+ case BLE_LL_CTRL_CLOCK_ACCURACY_RSP:
+ rsp_opcode = ble_ll_ctrl_rx_sca_rsp(connsm, dptr);
+ break;
+#endif
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+ case BLE_LL_CTRL_CIS_REQ:
+ rsp_opcode = ble_ll_ctrl_rx_cis_req(connsm, dptr, rspdata);
+ break;
+ case BLE_LL_CTRL_CIS_RSP:
+ rsp_opcode = ble_ll_ctrl_rx_cis_rsp(connsm, dptr, rspdata);
+ break;
+ case BLE_LL_CTRL_CIS_IND:
+ rsp_opcode = ble_ll_ctrl_rx_cis_ind(connsm, dptr);
+ break;
+#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
case BLE_LL_CTRL_PERIODIC_SYNC_IND:
rsp_opcode = ble_ll_ctrl_rx_periodic_sync_ind(connsm, dptr);
@@ -2712,6 +2842,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm)
connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT;
break;
case BLE_LL_CTRL_ENC_RSP:
+ connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
connsm->csmflags.cfbit.send_ltk_req = 1;
break;
case BLE_LL_CTRL_START_ENC_RSP:
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c
index d83af2c01..f3faac637 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c
@@ -35,6 +35,7 @@
#include "../include/controller/ble_ll_whitelist.h"
#include "../include/controller/ble_ll_resolv.h"
#include "../include/controller/ble_ll_sync.h"
+#include "../include/controller/ble_ll_iso.h"
#include "ble_ll_priv.h"
#include "ble_ll_conn_priv.h"
@@ -329,6 +330,31 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen)
return BLE_ERR_SUCCESS;
}
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+/**
+ * HCI read buffer size v2 command. Returns the ACL and ISO data packet length and
+ * num data packets.
+ *
+ * @param rspbuf Pointer to response buffer
+ * @param rsplen Length of response buffer
+ *
+ * @return int BLE error code
+ */
+static int
+ble_ll_hci_le_read_bufsize_v2(uint8_t *rspbuf, uint8_t *rsplen)
+{
+ struct ble_hci_le_rd_buf_size_v2_rp *rp = (void *) rspbuf;
+
+ rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size);
+ rp->data_packets = g_ble_ll_data.ll_num_acl_pkts;
+ rp->iso_data_len = 0;
+ rp->iso_data_packets = 0;
+
+ *rsplen = sizeof(*rp);
+ return BLE_ERR_SUCCESS;
+}
+#endif
+
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
/**
* Checks the preferred phy masks for validity and places the preferred masks
@@ -620,6 +646,9 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf)
case BLE_HCI_OCF_LE_GEN_DHKEY:
case BLE_HCI_OCF_LE_SET_PHY:
case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC:
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+ case BLE_HCI_OCF_LE_REQ_PEER_SCA:
+#endif
rc = 1;
break;
default:
@@ -1151,10 +1180,77 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
rc = ble_ll_set_default_sync_transfer_params(cmdbuf, len);
break;
#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+ case BLE_HCI_OCF_LE_READ_ISO_TX_SYNC:
+ rc = ble_ll_iso_read_tx_sync(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_SET_CIG_PARAM:
+ rc = ble_ll_iso_set_cig_param(cmdbuf, len, rspbuf, rsplen);
+ break;
+ case BLE_HCI_OCF_LE_CREATE_CIS:
+ rc = ble_ll_iso_create_cis(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_REMOVE_CIG:
+ rc = ble_ll_iso_remove_cig(cmdbuf, len, rspbuf, rsplen);
+ break;
+ case BLE_HCI_OCF_LE_ACCEPT_CIS_REQ:
+ rc = ble_ll_iso_accept_cis_req(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_REJECT_CIS_REQ:
+ rc = ble_ll_iso_reject_cis_req(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_CREATE_BIG:
+ rc = ble_ll_iso_create_big(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_TERMINATE_BIG:
+ rc = ble_ll_iso_terminate_big(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_BIG_CREATE_SYNC:
+ rc = ble_ll_iso_big_create_sync(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC:
+ rc = ble_ll_iso_big_terminate_sync(cmdbuf,len);
+ break;
+ case BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH:
+ rc = ble_ll_iso_setup_iso_data_path(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH:
+ rc = ble_ll_iso_remove_iso_data_path(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_RD_BUF_SIZE_V2:
+ rc = ble_ll_hci_le_read_bufsize_v2(rspbuf, rsplen);
+ break;
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST)
+ case BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST:
+ rc = ble_ll_iso_set_cig_param_test(cmdbuf, len, rspbuf, rsplen);
+ break;
+ case BLE_HCI_OCF_LE_CREATE_BIG_TEST:
+ rc = ble_ll_iso_create_big_test(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST:
+ rc = ble_ll_iso_transmit_test(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_ISO_RECEIVE_TEST:
+ rc = ble_ll_iso_receive_test(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS:
+ rc = ble_ll_iso_read_counters_test(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_LE_ISO_TEST_END:
+ rc = ble_ll_iso_end_test(cmdbuf, len);
+ break;
+#endif
#if MYNEWT_VAL(BLE_VERSION) >= 52
case BLE_HCI_OCF_LE_SET_HOST_FEAT:
rc = ble_ll_set_host_feat(cmdbuf, len);
break;
+#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+ case BLE_HCI_OCF_LE_REQ_PEER_SCA:
+ rc = ble_ll_conn_req_peer_sca(cmdbuf, len,
+ rspbuf, rsplen);
+ break;
#endif
default:
rc = BLE_ERR_UNKNOWN_HCI_CMD;
@@ -1176,6 +1272,26 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
return rc;
}
+static int
+ble_ll_hci_disconnect(const uint8_t *cmdbuf, uint8_t len)
+{
+ const struct ble_hci_lc_disconnect_cp *cmd;
+
+ cmd = (const void *) cmdbuf;
+
+ if (len != sizeof (*cmd)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+ if (le16toh(cmd->conn_handle) >= BLE_LL_CONN_HANDLE_ISO_OFFSET) {
+ return ble_ll_iso_disconnect_cmd(cmd);
+ }
+#endif
+
+ return ble_ll_conn_hci_disconnect_cmd(cmd);
+}
+
/**
* Process a link control command sent from the host to the controller. The HCI
* command has a 3 byte command header followed by data. The header is:
@@ -1196,7 +1312,7 @@ ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf)
switch (ocf) {
case BLE_HCI_OCF_DISCONNECT_CMD:
- rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf, len);
+ rc = ble_ll_hci_disconnect(cmdbuf, len);
/* Send command status instead of command complete */
rc += (BLE_ERR_MAX + 1);
break;
@@ -1229,6 +1345,64 @@ ble_ll_hci_cb_set_event_mask(const uint8_t *cmdbuf, uint8_t len)
return BLE_ERR_SUCCESS;
}
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+static int
+ble_ll_hci_cb_set_ctrlr_to_host_fc(const uint8_t *cmdbuf, uint8_t len)
+{
+ const struct ble_hci_cb_ctlr_to_host_fc_cp *cmd = (const void *) cmdbuf;
+
+ if (len != sizeof (*cmd)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* We only allow to either disable flow control or enable for ACL only */
+ if (cmd->enable > 1) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ if (!ble_ll_conn_cth_flow_enable(cmd->enable)) {
+ return BLE_ERR_CMD_DISALLOWED;
+ }
+
+ return BLE_ERR_SUCCESS;
+}
+
+static int
+ble_ll_hci_cb_host_buf_size(const uint8_t *cmdbuf, uint8_t len)
+{
+ const struct ble_hci_cb_host_buf_size_cp *cmd = (const void *) cmdbuf;
+ uint16_t acl_num;
+ uint16_t acl_data_len;
+
+ if (len != sizeof (*cmd)) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /* We do not support SCO so those parameters should be set to 0 */
+ if (cmd->sco_num || cmd->sco_data_len) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ /*
+ * Core 5.2 Vol 4 Part E section 7.3.39 states that "Both the Host and the
+ * Controller shall support command and event packets, where the data portion
+ * (excluding header) contained in the packets is 255 octets in size.".
+ * This means we can basically accept any allowed value since LL does not
+ * reassemble incoming data thus will not send more than 255 octets in single
+ * data packet.
+ */
+ acl_num = le16toh(cmd->acl_num);
+ acl_data_len = le16toh(cmd->acl_data_len);
+ if (acl_data_len < 255) {
+ return BLE_ERR_INV_HCI_CMD_PARMS;
+ }
+
+ ble_ll_conn_cth_flow_set_buffers(acl_num);
+
+ return BLE_ERR_SUCCESS;
+}
+#endif
+
static int
ble_ll_hci_cb_set_event_mask2(const uint8_t *cmdbuf, uint8_t len)
{
@@ -1261,6 +1435,22 @@ ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
rc = ble_ll_reset();
}
break;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+ case BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC:
+ rc = ble_ll_hci_cb_set_ctrlr_to_host_fc(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_CB_HOST_BUF_SIZE:
+ rc = ble_ll_hci_cb_host_buf_size(cmdbuf, len);
+ break;
+ case BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS:
+ /*
+ * HCI_Host_Number_Of_Completed_Packets is handled immediately when
+ * received from transport so we should never receive it here.
+ */
+ BLE_LL_ASSERT(0);
+ rc = BLE_ERR_UNKNOWN_HCI_CMD;
+ break;
+#endif
case BLE_HCI_OCF_CB_SET_EVENT_MASK2:
rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len);
break;
@@ -1337,6 +1527,47 @@ 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.
*
@@ -1396,6 +1627,11 @@ 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)
+ case BLE_HCI_OGF_VENDOR:
+ rc = ble_ll_hci_vs_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen);
+ break;
+#endif
default:
/* XXX: Need to support other OGF. For now, return unsupported */
rc = BLE_ERR_UNKNOWN_HCI_CMD;
@@ -1456,9 +1692,33 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
* BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion.
*/
int
-ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
+ble_ll_hci_cmd_rx(uint8_t *cmdbuf, void *arg)
{
struct ble_npl_event *ev;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+ const struct ble_hci_cmd *cmd;
+ uint16_t opcode;
+ uint16_t ocf;
+ uint16_t ogf;
+
+ cmd = (const void *)cmdbuf;
+ opcode = le16toh(cmd->opcode);
+ ogf = BLE_HCI_OGF(opcode);
+ ocf = BLE_HCI_OCF(opcode);
+
+ /*
+ * HCI_Host_Number_Of_Completed_Packets is processed outside standard flow
+ * thus it can be sent at any time, even if another command is already
+ * pending. This means we should better process it here and send an event to
+ * LL in case of error.
+ */
+ if ((ogf == BLE_HCI_OGF_CTLR_BASEBAND) &&
+ (ocf == BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS)) {
+ ble_ll_conn_cth_flow_process_cmd(cmdbuf);
+ ble_hci_trans_buf_free(cmdbuf);
+ return 0;
+ }
+#endif
/* Get an event structure off the queue */
ev = &g_ble_ll_hci_cmd_ev;
@@ -1467,7 +1727,7 @@ ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
}
/* Fill out the event and post to Link Layer */
- ble_npl_event_set_arg(ev, cmd);
+ ble_npl_event_set_arg(ev, cmdbuf);
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev);
return 0;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c
index b78b919ef..1ba4e815c 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci_ev.c
@@ -463,6 +463,37 @@ ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
}
#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+void
+ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm, uint8_t status,
+ uint8_t peer_sca)
+{
+ struct ble_hci_ev_le_subev_peer_sca_complete *ev;
+ struct ble_hci_ev *hci_ev;
+
+ if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP)) {
+ return;
+ }
+
+ hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+ if (!hci_ev) {
+ return;
+ }
+
+ hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
+ hci_ev->length = sizeof(*ev);
+ ev = (void *) hci_ev->data;
+
+ ev->subev_code = BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP;
+ ev->status = status;
+ ev->conn_handle = htole16(connsm->conn_handle);
+ ev->sca = peer_sca;
+
+ ble_ll_hci_event_send(hci_ev);
+}
+
+#endif
+
void
ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line)
{
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_iso.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_iso.c
new file mode 100644
index 000000000..ac8ca1e8a
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_iso.c
@@ -0,0 +1,147 @@
+/*
+ * 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 ESP_PLATFORM
+#include
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#include "nimble/nimble/include/nimble/ble.h"
+#include "nimble/nimble/include/nimble/hci_common.h"
+#include "../include/controller/ble_ll_iso.h"
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+
+int
+ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len,
+ uint8_t *rspbuf, uint8_t *rsplen)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len,
+ uint8_t *rspbuf, uint8_t *rsplen)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len)
+{
+ /* Nothing to do here for now when HCI is supported */
+ return 0;
+}
+int
+ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST)
+int
+ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len,
+ uint8_t *rspbuf, uint8_t *rsplen)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+
+int
+ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len)
+{
+ return BLE_ERR_UNSUPPORTED;
+}
+#endif
+#endif
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c
index dd89e04b0..d0b82ba5a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_rand.c
@@ -18,6 +18,9 @@
*/
#ifndef ESP_PLATFORM
+/* for jrand48 */
+#define _XOPEN_SOURCE
+#include
#include
#include
#include
@@ -121,6 +124,21 @@ ble_ll_rand_data_get(uint8_t *buf, uint8_t len)
return BLE_ERR_SUCCESS;
}
+/* Simple wrapper to allow easy replacement of rand() */
+uint32_t
+ble_ll_rand(void)
+{
+ static unsigned short xsubi[3];
+ static bool init = true;
+
+ if (init) {
+ init = false;
+ ble_ll_rand_data_get((uint8_t *)xsubi, sizeof(xsubi));
+ }
+
+ return (uint32_t) jrand48(xsubi);
+}
+
/**
* Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2
*
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c
index 03a683a76..feeb9360b 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c
@@ -295,7 +295,7 @@ ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success)
STATS_INC(ble_ll_stats, scan_req_txf);
}
- scansm->backoff_count = rand() & (scansm->upper_limit - 1);
+ scansm->backoff_count = ble_ll_rand() & (scansm->upper_limit - 1);
++scansm->backoff_count;
BLE_LL_ASSERT(scansm->backoff_count <= 256);
}
@@ -307,7 +307,7 @@ ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm)
ble_npl_time_t now;
now = ble_npl_time_get();
- if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) {
+ if (CPUTIME_GEQ(now, scansm->scan_nrpa_timer)) {
/* Generate new NRPA */
ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN);
scansm->scan_nrpa[5] &= ~0xc0;
@@ -619,7 +619,7 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd,
static int
ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype,
const uint8_t *addr, uint8_t addr_type,
- uint8_t rssi,
+ int8_t rssi,
uint8_t adv_data_len,
struct os_mbuf *adv_data,
const uint8_t *inita, uint8_t inita_type)
@@ -1127,6 +1127,22 @@ ble_ll_scan_sm_stop(int chk_disable)
scansm = &g_ble_ll_scan_sm;
os_cputime_timer_stop(&scansm->scan_timer);
+ /* Only set state if we are currently in a scan window */
+ if (chk_disable) {
+ OS_ENTER_CRITICAL(sr);
+ lls = ble_ll_state_get();
+
+ if ((lls == BLE_LL_STATE_SCANNING) ||
+ (lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
+ /* Disable phy */
+ ble_phy_disable();
+
+ /* Set LL state to standby */
+ ble_ll_state_set(BLE_LL_STATE_STANDBY);
+ }
+ OS_EXIT_CRITICAL(sr);
+ }
+
OS_ENTER_CRITICAL(sr);
/* Disable scanning state machine */
@@ -1151,22 +1167,6 @@ ble_ll_scan_sm_stop(int chk_disable)
/* Count # of times stopped */
STATS_INC(ble_ll_stats, scan_stops);
- /* Only set state if we are currently in a scan window */
- if (chk_disable) {
- OS_ENTER_CRITICAL(sr);
- lls = ble_ll_state_get();
-
- if ((lls == BLE_LL_STATE_SCANNING) ||
- (lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
- /* Disable phy */
- ble_phy_disable();
-
- /* Set LL state to standby */
- ble_ll_state_set(BLE_LL_STATE_STANDBY);
- }
- OS_EXIT_CRITICAL(sr);
- }
-
/* No need for RF anymore */
OS_ENTER_CRITICAL(sr);
ble_ll_rfmgmt_scan_changed(false, 0);
@@ -1993,10 +1993,10 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad
{
struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm;
struct ble_ll_scan_params *scanp = scansm->scanp;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data;
#endif
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo;
struct ble_ll_resolv_entry *rl = NULL;
#endif
@@ -2229,6 +2229,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf,
*/
if (aux_data->flags & BLE_LL_AUX_IS_MATCHED) {
rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
rxinfo->rpa_index = aux_data->rpa_index;
if (rxinfo->rpa_index >= 0) {
rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED;
@@ -2236,6 +2237,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf,
if (aux_data->flags & BLE_LL_AUX_IS_TARGETA_RESOLVED) {
rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED;
}
+#endif
goto done;
}
@@ -2687,10 +2689,16 @@ ble_ll_hci_send_ext_adv_report(uint8_t ptype, uint8_t *adva, uint8_t adva_type,
/*
* We need another event if either there are still some data left to
- * send in current PDU or scan is not completed. The only exception is
- * when this is a scannable event which is not a scan response.
+ * 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))) && !is_scannable_aux;
+ 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) {
/*
@@ -3021,7 +3029,8 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om,
if (!BLE_MBUF_HDR_DEVMATCH(hdr) ||
!BLE_MBUF_HDR_CRC_OK(hdr) ||
- BLE_MBUF_HDR_IGNORED(hdr)) {
+ BLE_MBUF_HDR_IGNORED(hdr) ||
+ !scansm->scan_enabled) {
return;
}
@@ -3060,10 +3069,6 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om,
bool send_hci_report;
int rc;
- if (!scansm->ext_scanning) {
- goto scan_continue;
- }
-
if (aux_data) {
aux_data->flags_ll |= aux_data->flags_isr;
}
@@ -3079,7 +3084,8 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om,
BLE_MBUF_HDR_IGNORED(hdr) ||
BLE_MBUF_HDR_AUX_INVALID(hdr) ||
(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) ||
- (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND)) {
+ (pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) ||
+ !scansm->scan_enabled) {
if (aux_data) {
ble_ll_scan_end_adv_evt(aux_data);
ble_ll_scan_aux_data_unref(aux_data);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c
index 77c107f82..dbe53e15c 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c
@@ -91,14 +91,14 @@ ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1,
int rc;
rc = 1;
- if ((int32_t)(s1->start_time - s2->start_time) < 0) {
+ if (CPUTIME_LT(s1->start_time, s2->start_time)) {
/* Make sure this event does not overlap current event */
- if ((int32_t)(s1->end_time - s2->start_time) <= 0) {
+ if (CPUTIME_LEQ(s1->end_time, s2->start_time)) {
rc = 0;
}
} else {
/* Check for overlap */
- if ((int32_t)(s1->start_time - s2->end_time) >= 0) {
+ if (CPUTIME_GEQ(s1->start_time, s2->end_time)) {
rc = 0;
}
}
@@ -119,7 +119,7 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch)
rc = 0;
if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) {
ce_end_time = ble_ll_conn_get_ce_end_time();
- if ((int32_t)(ce_end_time - sch->start_time) > 0) {
+ if (CPUTIME_GT(ce_end_time, sch->start_time)) {
rc = 1;
}
}
@@ -186,7 +186,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
sch->end_time = connsm->ce_end_time;
/* Better be past current time or we just leave */
- if ((int32_t)(sch->start_time - os_cputime_get32()) < 0) {
+ if (CPUTIME_LT(sch->start_time, os_cputime_get32())) {
return -1;
}
@@ -224,7 +224,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
end_overlap = entry;
}
} else {
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
break;
@@ -476,7 +476,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
sch->end_time = earliest_end;
/* We can insert if before entry in list */
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
if ((earliest_start - initial_start) <= itvl_t) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
@@ -663,7 +663,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
sch->end_time = earliest_end;
/* We can insert if before entry in list */
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
if ((earliest_start - initial_start) <= itvl_t) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
@@ -778,7 +778,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
while (1) {
next_sch = entry->link.tqe_next;
/* Insert if event ends before next starts */
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
break;
@@ -1055,7 +1055,7 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb,
os_cputime_timer_stop(&g_ble_ll_sched_timer);
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
/* We can insert if before entry in list */
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
TAILQ_INSERT_BEFORE(entry, sch, link);
break;
}
@@ -1119,7 +1119,7 @@ ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start,
os_cputime_timer_stop(&g_ble_ll_sched_timer);
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
/* We can insert if before entry in list */
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
TAILQ_INSERT_BEFORE(entry, sch, link);
break;
}
@@ -1208,7 +1208,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
end_overlap = entry;
}
} else {
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
before = entry;
break;
}
@@ -1241,7 +1241,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
sch->end_time = sch->start_time + duration;
while (1) {
next_sch = entry->link.tqe_next;
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
rand_ticks = entry->start_time - sch->end_time;
before = entry;
TAILQ_INSERT_BEFORE(before, sch, link);
@@ -1274,7 +1274,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
if (!rc) {
sch->enqueued = 1;
if (rand_ticks) {
- sch->start_time += rand() % rand_ticks;
+ sch->start_time += ble_ll_rand() % rand_ticks;
}
sch->end_time = sch->start_time + duration;
*start = sch->start_time;
@@ -1588,7 +1588,7 @@ ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode)
while (sch) {
/* Let's check if there is no scheduled item which want to start within
* given usecs.*/
- if ((int32_t)(sch->start_time - now + os_cputime_usecs_to_ticks(usec_dur)) > 0) {
+ if (CPUTIME_GT(sch->start_time, now + os_cputime_usecs_to_ticks(usec_dur))) {
/* We are fine. Have time for scan req */
return 0;
}
@@ -1678,7 +1678,7 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
os_cputime_timer_stop(&g_ble_ll_sched_timer);
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
/* We can insert if before entry in list */
- if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
+ if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
sch->enqueued = 1;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c
index 6ee912fa3..e4db5f778 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c
@@ -37,7 +37,22 @@
/* Octet 10 */
#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2)
-#define BLE_LL_SUPP_CMD_OCTET_10 (BLE_SUPP_CMD_RD_TX_PWR)
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (1 << 5)
+#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (1 << 6)
+#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (1 << 7)
+#else
+#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (0 << 5)
+#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (0 << 6)
+#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (0 << 7)
+#endif
+#define BLE_LL_SUPP_CMD_OCTET_10 \
+( \
+ BLE_SUPP_CMD_RD_TX_PWR | \
+ BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW | \
+ BLE_SUPP_CMD_HOST_BUFFER_SIZE | \
+ BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS \
+)
/* Octet 14 */
#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3)
@@ -405,10 +420,77 @@
#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0)
#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1)
#endif
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (1 << 5)
+#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (1 << 6)
+#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (1 << 7)
+#else
+#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (0 << 5)
+#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (0 << 6)
+#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (0 << 7)
+#endif
+
#define BLE_LL_SUPP_CMD_OCTET_41 \
( \
- BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \
- BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS \
+ BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \
+ BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS | \
+ BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 | \
+ BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC | \
+ BLE_SUPP_CMD_LE_SET_CIG_PARAM \
+)
+
+/* Octet 42 */
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
+#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (1 << 0)
+#define BLE_SUPP_CMD_LE_CREATE_CIS (1 << 1)
+#define BLE_SUPP_CMD_LE_REMOVE_CIG (1 << 2)
+#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (1 << 3)
+#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (1 << 4)
+#define BLE_SUPP_CMD_LE_CREATE_BIG (1 << 5)
+#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (1 << 6)
+#define BLE_SUPP_CMD_LE_TERMINATE_BIG (1 << 7)
+#else
+#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (0 << 0)
+#define BLE_SUPP_CMD_LE_CREATE_CIS (0 << 1)
+#define BLE_SUPP_CMD_LE_REMOVE_CIG (0 << 2)
+#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (0 << 3)
+#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (0 << 4)
+#define BLE_SUPP_CMD_LE_CREATE_BIG (0 << 5)
+#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (0 << 6)
+#define BLE_SUPP_CMD_LE_TERMINATE_BIG (0 << 7)
+#endif
+#define BLE_LL_SUPP_CMD_OCTET_42 \
+( \
+ BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST | \
+ BLE_SUPP_CMD_LE_CREATE_CIS | \
+ BLE_SUPP_CMD_LE_REMOVE_CIG | \
+ BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ | \
+ BLE_SUPP_CMD_LE_REJECT_CIS_REQ | \
+ BLE_SUPP_CMD_LE_CREATE_BIG | \
+ BLE_SUPP_CMD_LE_CREATE_BIG_TEST | \
+ BLE_SUPP_CMD_LE_TERMINATE_BIG \
+)
+
+/* Octet 43 */
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
+#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (1 << 2)
+#else
+#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (0 << 0)
+#endif
+#define BLE_LL_SUPP_CMD_OCTET_43 \
+( \
+ BLE_SUPP_CMD_LE_REQUEST_PEER_SCA \
+)
+
+/* Octet 44 */
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 0)
+#else
+#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 0)
+#endif
+#define BLE_LL_SUPP_CMD_OCTET_44 \
+( \
+ BLE_SUPP_CMD_LE_SET_HOST_FEATURE \
)
/* Defines the array of supported commands */
@@ -456,6 +538,9 @@ const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] =
BLE_LL_SUPP_CMD_OCTET_39,
BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */
BLE_LL_SUPP_CMD_OCTET_41,
+ BLE_LL_SUPP_CMD_OCTET_42,
+ BLE_LL_SUPP_CMD_OCTET_43,
+ BLE_LL_SUPP_CMD_OCTET_44,
};
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c
index 231a4d633..f1908c329 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c
@@ -61,6 +61,7 @@
#define BLE_LL_SYNC_SM_FLAG_DISABLED 0x0040
#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_CHMAP_LEN 5
#define BLE_LL_SYNC_ITVL_USECS 1250
@@ -76,6 +77,9 @@ struct ble_ll_sync_sm {
uint8_t chanmap[BLE_LL_SYNC_CHMAP_LEN];
uint8_t num_used_chans;
+ uint8_t chanmap_new[BLE_LL_SYNC_CHMAP_LEN];
+ uint16_t chanmap_new_instant;
+
uint8_t chan_index;
uint8_t chan_chain;
@@ -526,7 +530,8 @@ ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr)
}
static int
-ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power)
+ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power,
+ uint8_t **acad, uint8_t *acad_len)
{
uint8_t *rxbuf = om->om_data;
uint8_t ext_hdr_flags;
@@ -586,12 +591,17 @@ ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power)
i += BLE_LL_EXT_ADV_TX_POWER_SIZE;
}
- /* TODO Handle ACAD if needed */
-
/* sanity check */
if (i > ext_hdr_len) {
return -1;
}
+
+ /* ACAD */
+ if (ext_hdr_len > (i + 1)) {
+ *acad = ext_hdr + i;
+ *acad_len = ext_hdr_len - i - 1;
+ }
+
}
return pdu_len - ext_hdr_len - 1;
@@ -997,6 +1007,70 @@ ble_ll_sync_check_failed(struct ble_ll_sync_sm *sm)
ble_ll_sync_est_event_failed(BLE_ERR_CONN_ESTABLISHMENT);
}
+static bool
+ble_ll_sync_check_acad(struct ble_ll_sync_sm *sm,
+ const uint8_t *acad, uint8_t acad_len)
+{
+ const struct ble_ll_acad_channel_map_update_ind *chmu;
+ unsigned int ad_len;
+ uint8_t ad_type;
+
+ /* assume no empty fields */
+ while (acad_len > 2) {
+ ad_len = acad[0];
+ ad_type = acad[1];
+
+ /* early termination should not happen in ACAD */
+ if (ad_len == 0) {
+ return false;
+ }
+
+ /* check if not passing pass acad data */
+ if (ad_len + 1 > acad_len) {
+ return false;
+ }
+
+ switch (ad_type) {
+ case BLE_LL_ACAD_CHANNEL_MAP_UPDATE_IND:
+ chmu = (const void *)&acad[2];
+
+ if (ad_len - 1 != sizeof(*chmu)) {
+ return false;
+ }
+
+ /* Channels Mask (37 bits)
+ * TODO should we check this?
+ */
+ sm->chanmap_new[0] = chmu->map[0];
+ sm->chanmap_new[1] = chmu->map[1];
+ sm->chanmap_new[2] = chmu->map[2];
+ sm->chanmap_new[3] = chmu->map[3];
+ sm->chanmap_new[4] = chmu->map[4] & 0x1f;
+
+ /* drop if channel map is invalid */
+ if (ble_ll_utils_calc_num_used_chans(sm->chanmap_new) == 0) {
+ return false;
+ }
+
+ sm->chanmap_new_instant = le16toh(chmu->instant);
+ sm->flags |= BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP;
+ break;
+ default:
+ break;
+ }
+
+ acad += ad_len + 1;
+ acad_len -= ad_len + 1;
+ }
+
+ /* should have no trailing zeros */
+ if (acad_len) {
+ return false;
+ }
+
+ return true;
+}
+
void
ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
{
@@ -1004,7 +1078,10 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
bool aux_scheduled = false;
int8_t tx_power = 127; /* defaults to not available */
uint8_t *aux = NULL;
+ uint8_t *acad = NULL;
+ uint8_t acad_len;
int datalen;
+ bool reports_enabled;
BLE_LL_ASSERT(sm);
@@ -1049,36 +1126,43 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
goto end_event;
}
- if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) &&
- !(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED)) {
- /* get ext header data */
- datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power);
- if (datalen < 0) {
- /* we got bad packet, end event */
- goto end_event;
- }
+ /* get ext header data */
+ datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power, &acad, &acad_len);
+ if (datalen < 0) {
+ /* we got bad packet, end event */
+ goto end_event;
+ }
+ reports_enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) &&
+ !(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED);
+
+ /* no need to schedule for chain if reporting is disabled */
+ if (reports_enabled) {
/* if aux is present, we need to schedule ASAP */
if (aux && (ble_ll_sync_schedule_chain(sm, hdr, aux) == 0)) {
aux_scheduled = true;
}
+ }
- /* in case data reporting is enabled we need to send sync established here */
- if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) {
- ble_ll_sync_established(sm);
- }
+ /* check ACAD, needs to be done before rxpdu is adjusted for ADV data */
+ if (acad && !ble_ll_sync_check_acad(sm, acad, acad_len)) {
+ /* we got bad packet (bad ACAD data), end event */
+ goto end_event;
+ }
+ /* we need to establish link even if reporting was disabled */
+ if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) {
+ ble_ll_sync_established(sm);
+ }
+
+ /* only if reporting is enabled */
+ if (reports_enabled) {
/* Adjust rxpdu to contain advertising data only */
ble_ll_sync_adjust_ext_hdr(rxpdu);
/* send reports from this PDU */
ble_ll_sync_send_per_adv_rpt(sm, rxpdu, hdr->rxinfo.rssi, tx_power,
datalen, aux, aux_scheduled);
- } else {
- /* we need to establish link even if reporting was disabled */
- if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) {
- ble_ll_sync_established(sm);
- }
}
/* if chain was scheduled we don't end event yet */
@@ -1132,6 +1216,20 @@ ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust)
/* Set event counter to the next event */
sm->event_cntr += 1 + skip;
+ /* update channel map if needed */
+ if (sm->flags & BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP) {
+ if (((int16_t)(sm->event_cntr - sm->chanmap_new_instant)) >= 0) {
+ /* map was verified on reception */
+ sm->chanmap[0] = sm->chanmap_new[0];
+ sm->chanmap[1] = sm->chanmap_new[1];
+ sm->chanmap[2] = sm->chanmap_new[2];
+ sm->chanmap[3] = sm->chanmap_new[3];
+ sm->chanmap[4] = sm->chanmap_new[4];
+ sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap);
+ sm->flags &= ~BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP;
+ }
+ }
+
/* Calculate channel index of next event */
sm->chan_index = ble_ll_utils_calc_dci_csa2(sm->event_cntr, sm->channel_id,
sm->num_used_chans, sm->chanmap);
@@ -2092,10 +2190,10 @@ ble_ll_sync_send_sync_ind(struct ble_ll_sync_sm *syncsm,
if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) {
sync_ind[24] |= 1 << 4;
} else {
- sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4 ;
+ sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4;
}
- sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
+ sync_ind[24] |= BLE_LL_SCA_ENUM << 5;
/* PHY */
sync_ind[25] = (0x01 << (ble_ll_sync_phy_mode_to_hci(syncsm->phy_mode) - 1));
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c
index 3814e58a8..cdf6b60c6 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_utils.c
@@ -51,8 +51,8 @@ ble_ll_utils_calc_access_addr(void)
aa = 0;
while (1) {
/* Get two, 16-bit random numbers */
- aa_low = rand() & 0xFFFF;
- aa_high = rand() & 0xFFFF;
+ aa_low = ble_ll_rand() & 0xFFFF;
+ aa_high = ble_ll_rand() & 0xFFFF;
/* All four bytes cannot be equal */
if (aa_low == aa_high) {
@@ -293,8 +293,7 @@ ble_ll_utils_calc_window_widening(uint32_t anchor_point,
time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point);
if (time_since_last_anchor > 0) {
delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000;
- total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] +
- MYNEWT_VAL(BLE_LL_OUR_SCA);
+ total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + MYNEWT_VAL(BLE_LL_SCA);
window_widening = (total_sca_ppm * delta_msec) / 1000;
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c
index 3bfed096a..908664a73 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c
@@ -1508,7 +1508,7 @@ ble_phy_resolv_list_disable(void)
void
ble_phy_rfclk_enable(void)
{
-#if MYNEWT
+#if MYNEWT || ARDUINO
nrf51_clock_hfxo_request();
#else
NRF_CLOCK->TASKS_HFCLKSTART = 1;
@@ -1518,7 +1518,7 @@ ble_phy_rfclk_enable(void)
void
ble_phy_rfclk_disable(void)
{
-#if MYNEWT
+#if MYNEWT || ARDUINO
nrf51_clock_hfxo_release();
#else
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c
index 2ee29ab9c..08511c340 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-
+
#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES)
#include
@@ -2100,7 +2100,7 @@ void ble_phy_disable_dtm(void)
void
ble_phy_rfclk_enable(void)
{
-#if MYNEWT
+#if MYNEWT || ARDUINO
nrf52_clock_hfxo_request();
#else
NRF_CLOCK->TASKS_HFCLKSTART = 1;
@@ -2110,7 +2110,7 @@ ble_phy_rfclk_enable(void)
void
ble_phy_rfclk_disable(void)
{
-#if MYNEWT
+#if MYNEWT || ARDUINO
nrf52_clock_hfxo_release();
#else
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h
index edaf3bc4d..7f77d7fb6 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h
@@ -39,41 +39,47 @@ extern "C" {
struct hci_le_conn_complete;
struct hci_conn_update;
+#define BLE_GAP_ADV_ITVL_MS(t) ((t) * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_SCAN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_SCAN_WIN_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_CONN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_CONN_ITVL)
+#define BLE_GAP_SUPERVISION_TIMEOUT_MS(t) ((t) / 10)
+
/** 30 ms. */
-#define BLE_GAP_ADV_FAST_INTERVAL1_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_ADV_FAST_INTERVAL1_MIN BLE_GAP_ADV_ITVL_MS(30)
/** 60 ms. */
-#define BLE_GAP_ADV_FAST_INTERVAL1_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_ADV_FAST_INTERVAL1_MAX BLE_GAP_ADV_ITVL_MS(60)
/** 100 ms. */
-#define BLE_GAP_ADV_FAST_INTERVAL2_MIN (100 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_ADV_FAST_INTERVAL2_MIN BLE_GAP_ADV_ITVL_MS(100)
/** 150 ms. */
-#define BLE_GAP_ADV_FAST_INTERVAL2_MAX (150 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_ADV_FAST_INTERVAL2_MAX BLE_GAP_ADV_ITVL_MS(150)
/** 30 ms; active scanning. */
-#define BLE_GAP_SCAN_FAST_INTERVAL_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_SCAN_FAST_INTERVAL_MIN BLE_GAP_SCAN_ITVL_MS(30)
/** 60 ms; active scanning. */
-#define BLE_GAP_SCAN_FAST_INTERVAL_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
+#define BLE_GAP_SCAN_FAST_INTERVAL_MAX BLE_GAP_SCAN_ITVL_MS(60)
/** 11.25 ms; limited discovery interval. */
-#define BLE_GAP_LIM_DISC_SCAN_INT (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_LIM_DISC_SCAN_INT BLE_GAP_SCAN_ITVL_MS(11.25)
/** 11.25 ms; limited discovery window (not from the spec). */
-#define BLE_GAP_LIM_DISC_SCAN_WINDOW (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_LIM_DISC_SCAN_WINDOW BLE_GAP_SCAN_WIN_MS(11.25)
/** 30 ms; active scanning. */
-#define BLE_GAP_SCAN_FAST_WINDOW (30 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_SCAN_FAST_WINDOW BLE_GAP_SCAN_WIN_MS(30)
/* 30.72 seconds; active scanning. */
-#define BLE_GAP_SCAN_FAST_PERIOD (30.72 * 1000)
+#define BLE_GAP_SCAN_FAST_PERIOD BLE_GAP_SCAN_ITVL_MS(30.72)
/** 1.28 seconds; background scanning. */
-#define BLE_GAP_SCAN_SLOW_INTERVAL1 (1280 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_SCAN_SLOW_INTERVAL1 BLE_GAP_SCAN_ITVL_MS(1280)
/** 11.25 ms; background scanning. */
-#define BLE_GAP_SCAN_SLOW_WINDOW1 (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
+#define BLE_GAP_SCAN_SLOW_WINDOW1 BLE_GAP_SCAN_WIN_MS(11.25)
/** 10.24 seconds. */
#define BLE_GAP_DISC_DUR_DFLT (10.24 * 1000)
@@ -88,10 +94,10 @@ struct hci_conn_update;
#define BLE_GAP_CONN_PAUSE_PERIPHERAL (5 * 1000)
/* 30 ms. */
-#define BLE_GAP_INITIAL_CONN_ITVL_MIN (30 * 1000 / BLE_HCI_CONN_ITVL)
+#define BLE_GAP_INITIAL_CONN_ITVL_MIN BLE_GAP_CONN_ITVL_MS(30)
/* 50 ms. */
-#define BLE_GAP_INITIAL_CONN_ITVL_MAX (50 * 1000 / BLE_HCI_CONN_ITVL)
+#define BLE_GAP_INITIAL_CONN_ITVL_MAX BLE_GAP_CONN_ITVL_MS(50)
/** Default channels mask: all three channels are used. */
#define BLE_GAP_ADV_DFLT_CHANNEL_MAP 0x07
@@ -1156,6 +1162,38 @@ int ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields);
int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
uint16_t tx_time);
+/**
+ * Read host's suggested values for the controller's maximum transmitted number of payload octets
+ * and maximum packet transmission time (OGF = 0x08, OCF = 0x0024).
+ *
+ * @param out_sugg_max_tx_octets The Host's suggested value for the Controller's maximum transmitted
+ * number of payload octets in LL Data PDUs to be used for new
+ * connections. (Range 0x001B-0x00FB).
+ * @param out_sugg_max_tx_time The Host's suggested value for the Controller's maximum packet
+ * transmission time for packets containing LL Data PDUs to be used
+ * for new connections. (Range 0x0148-0x4290).
+ *
+ * @return 0 on success,
+ * other error code on failure.
+ */
+int ble_hs_hci_util_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets,
+ uint16_t *out_sugg_max_tx_time);
+/**
+ * Configure host's suggested maximum transmitted number of payload octets and maximum packet
+ * transmission time in controller (OGF = 0x08, OCF = 0x0024).
+ *
+ * @param sugg_max_tx_octets The Host's suggested value for the Controller's maximum transmitted
+ * number of payload octets in LL Data PDUs to be used for new
+ * connections. (Range 0x001B-0x00FB).
+ * @param sugg_max_tx_time The Host's suggested value for the Controller's maximum packet
+ * transmission time for packets containing LL Data PDUs to be used
+ * for new connections. (Range 0x0148-0x4290).
+ *
+ * @return 0 on success,
+ * other error code on failure.
+ */
+int ble_hs_hci_util_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_t sugg_max_tx_time);
+
#if MYNEWT_VAL(BLE_EXT_ADV)
/** @brief Extended advertising parameters */
struct ble_gap_ext_adv_params {
@@ -1837,6 +1875,37 @@ int ble_gap_update_params(uint16_t conn_handle,
*/
int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time);
+/**
+ * Read LE Suggested Default Data Length in controller (OGF = 0x08, OCF = 0x0024).
+ *
+ * @param out_sugg_max_tx_octets The Host's suggested value for the Controller's maximum transmitted
+ * number of payload octets in LL Data PDUs to be used for new
+ * connections. (Range 0x001B-0x00FB).
+ * @param out_sugg_max_tx_time The Host's suggested value for the Controller's maximum packet
+ * transmission time for packets containing LL Data PDUs to be used
+ * for new connections. (Range 0x0148-0x4290).
+ *
+ * @return 0 on success,
+ * other error code on failure.
+ */
+int ble_gap_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets,
+ uint16_t *out_sugg_max_tx_time);
+
+/**
+ * Configure LE Suggested Default Data Length in controller (OGF = 0x08, OCF = 0x0024).
+ *
+ * @param sugg_max_tx_octets The Host's suggested value for the Controller's maximum transmitted
+ * number of payload octets in LL Data PDUs to be used for new
+ * connections. (Range 0x001B-0x00FB).
+ * @param sugg_max_tx_time The Host's suggested value for the Controller's maximum packet
+ * transmission time for packets containing LL Data PDUs to be used
+ * for new connections. (Range 0x0148-0x4290).
+ *
+ * @return 0 on success,
+ * other error code on failure.
+ */
+int ble_gap_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_t sugg_max_tx_time);
+
/**
* Initiates the GAP security procedure.
*
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h
index 303b53c6e..0646b0bae 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs_log.h
@@ -21,6 +21,7 @@
#define H_BLE_HS_LOG_
#include "nimble/porting/nimble/include/modlog/modlog.h"
+#include "nimble/porting/nimble/include/log/log.h"
/* Only include the logcfg header if this version of newt can generate it. */
#if MYNEWT_VAL(NEWT_FEATURE_LOGCFG)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h
index 418d4e379..2c3602402 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_monitor.h
@@ -32,6 +32,7 @@ extern "C" {
int ble_monitor_log(int level, const char *fmt, ...);
int ble_monitor_out(int c);
+void ble_monitor_deinit(void);
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/access.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/access.h
index 1f99f412e..9f923cb9e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/access.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/access.h
@@ -28,14 +28,23 @@ extern "C" {
#define BT_MESH_ADDR_RELAYS 0xfffe
#define BT_MESH_KEY_UNUSED 0xffff
+#define BT_MESH_KEY_ANY 0xffff
#define BT_MESH_KEY_DEV 0xfffe
#define BT_MESH_KEY_DEV_LOCAL BT_MESH_KEY_DEV
#define BT_MESH_KEY_DEV_REMOTE 0xfffd
#define BT_MESH_KEY_DEV_ANY 0xfffc
+#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
+#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
+#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
+#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
+
#define BT_MESH_IS_DEV_KEY(key) (key == BT_MESH_KEY_DEV_LOCAL || \
key == BT_MESH_KEY_DEV_REMOTE)
+#define BT_MESH_APP_SEG_SDU_MAX 12
+#define BT_MESH_TX_SDU_MAX (CONFIG_BT_MESH_TX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
+#define BT_MESH_RX_SDU_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
/** Helper to define a mesh element within an array.
*
* In case the element has no SIG or Vendor models the helper
@@ -57,13 +66,13 @@ extern "C" {
/** Abstraction that describes a Mesh Element */
struct bt_mesh_elem {
/* Unicast Address. Set at runtime during provisioning. */
- u16_t addr;
+ uint16_t addr;
/* Location Descriptor (GATT Bluetooth Namespace Descriptors) */
- const u16_t loc;
+ const uint16_t loc;
- const u8_t model_count;
- const u8_t vnd_model_count;
+ const uint8_t model_count;
+ const uint8_t vnd_model_count;
struct bt_mesh_model * const models;
struct bt_mesh_model * const vnd_models;
@@ -132,33 +141,33 @@ struct bt_mesh_elem {
/** Message sending context. */
struct bt_mesh_msg_ctx {
/** NetKey Index of the subnet to send the message on. */
- u16_t net_idx;
+ uint16_t net_idx;
/** AppKey Index to encrypt the message with. */
- u16_t app_idx;
+ uint16_t app_idx;
/** Remote address. */
- u16_t addr;
+ uint16_t addr;
/** Destination address of a received message. Not used for sending. */
- u16_t recv_dst;
+ uint16_t recv_dst;
/** RSSI of received packet. Not used for sending. */
- s8_t recv_rssi;
+ int8_t recv_rssi;
/** Received TTL value. Not used for sending. */
- u8_t recv_ttl;
+ uint8_t recv_ttl;
/** Force sending reliably by using segment acknowledgement */
bool send_rel;
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
- u8_t send_ttl;
+ uint8_t send_ttl;
};
struct bt_mesh_model_op {
/* OpCode encoded using the BT_MESH_MODEL_OP_* macros */
- const u32_t opcode;
+ const uint32_t opcode;
/* Minimum required message length */
const size_t min_len;
@@ -324,7 +333,7 @@ struct bt_mesh_model_op {
*
* @return Transmission count (actual transmissions is N + 1).
*/
-#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (u8_t)BIT_MASK(3)))
+#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (uint8_t)BIT_MASK(3)))
/** @def BT_MESH_TRANSMIT_INT
*
@@ -375,23 +384,24 @@ struct bt_mesh_model_pub {
/** The model the context belongs to. Initialized by the stack. */
struct bt_mesh_model *mod;
- u16_t addr; /**< Publish Address. */
- u16_t key; /**< Publish AppKey Index. */
+ uint16_t addr; /**< Publish Address. */
+ uint16_t key; /**< Publish AppKey Index. */
- u8_t ttl; /**< Publish Time to Live. */
- u8_t retransmit; /**< Retransmit Count & Interval Steps. */
- u8_t period; /**< Publish Period. */
- u8_t period_div:4, /**< Divisor for the Period. */
+ 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. */
- u32_t period_start; /**< Start of the current period. */
+ uint32_t period_start; /**< Start of the current period. */
/** @brief Publication buffer, containing the publication message.
*
* The application is expected to initialize this with
- * a valid net_buf_simple pointer, with the help of e.g.
+ * a valid os_mbuf pointer, with the help of e.g.
* the NET_BUF_SIMPLE() macro. The publication buffer must
* contain a valid publication message before calling the
* bt_mesh_model_publish() API or after the publication's
@@ -414,6 +424,10 @@ struct bt_mesh_model_pub {
* will be called periodically and is expected to update
* @ref bt_mesh_model_pub.msg with a valid publication
* message.
+ *
+ * If the callback returns non-zero, the publication is skipped
+ * and will resume on the next periodic publishing interval.
+ *
*
* @param mod The Model the Publication Context belogs to.
*
@@ -432,16 +446,18 @@ struct bt_mesh_model_cb {
* @sa settings_handler::h_set
*
* @param model Model to set the persistent data of.
+ * @param name Name/key of the settings item.
* @param val Data from the backend.
*
* @return 0 on success, error otherwise.
*/
- int (*const settings_set)(struct bt_mesh_model *model, char *val);
+ int (*const settings_set)(struct bt_mesh_model *model,
+ const char *name, char *val);
- /** @brief Callback called when all settings have been loaded.
+ /** @brief Callback called when the mesh is started.
*
- * This handler gets called after the settings have been loaded in
- * full.
+ * This handler gets called after the node has been provisioned, or
+ * after all mesh data has been loaded from persistent storage.
*
* @sa settings_handler::h_commit
*
@@ -449,12 +465,17 @@ struct bt_mesh_model_cb {
*
* @return 0 on success, error otherwise.
*/
- int (*const settings_commit)(struct bt_mesh_model *model);
+ int (*const start)(struct bt_mesh_model *model);
/** @brief Model init callback.
*
* Called on every model instance during mesh initialization.
*
+ *
+ * If any of the model init callbacks return an error, the Mesh
+ * subsystem initialization will be aborted, and the error will be
+ * returned to the caller of @ref bt_mesh_init.
+ *
* @param model Model to be initialized.
*
* @return 0 on success, error otherwise.
@@ -466,6 +487,9 @@ struct bt_mesh_model_cb {
* Called when the mesh node is reset. All model data is deleted on
* reset, and the model should clear its state.
*
+ * @note If the model stores any persistent data, this needs to be
+ * erased manually.
+ *
* @param model Model this callback belongs to.
*/
void (*const reset)(struct bt_mesh_model *model);
@@ -474,26 +498,26 @@ struct bt_mesh_model_cb {
/** Abstraction that describes a Mesh Model instance */
struct bt_mesh_model {
union {
- const u16_t id;
+ const uint16_t id;
struct {
- u16_t company;
- u16_t id;
+ uint16_t company;
+ uint16_t id;
} vnd;
};
/* Internal information, mainly for persistent storage */
- u8_t elem_idx; /* Belongs to Nth element */
- u8_t mod_idx; /* Is the Nth model in the element */
- u16_t flags; /* Model flags for internal bookkeeping */
+ uint8_t elem_idx; /* Belongs to Nth element */
+ uint8_t mod_idx; /* Is the Nth model in the element */
+ uint16_t flags; /* Model flags for internal bookkeeping */
/* Model Publication */
struct bt_mesh_model_pub * const pub;
/* AppKey List */
- u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
+ uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
/* Subscription List (group or virtual addresses) */
- u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
+ uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
const struct bt_mesh_model_op * const op;
@@ -511,11 +535,11 @@ struct bt_mesh_model {
};
struct bt_mesh_send_cb {
- void (*start)(u16_t duration, int err, void *cb_data);
+ void (*start)(uint16_t duration, int err, void *cb_data);
void (*end)(int err, void *cb_data);
};
-void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode);
+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
@@ -574,7 +598,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
* if no SIG model with the given ID exists in the given element.
*/
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
- u16_t id);
+ uint16_t id);
/** @brief Find a vendor model.
*
@@ -586,7 +610,7 @@ struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
* if no vendor model with the given ID exists in the given element.
*/
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
- u16_t company, u16_t id);
+ uint16_t company, uint16_t id);
/** @brief Get whether the model is in the primary element of the device.
*
@@ -603,13 +627,14 @@ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod)
*
* @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 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 void *data, size_t data_len);
+ const char *name, const void *data, size_t data_len);
/** @brief Let a model extend another.
*
@@ -637,9 +662,9 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod,
/** Node Composition */
struct bt_mesh_comp {
- u16_t cid;
- u16_t pid;
- u16_t vid;
+ uint16_t cid;
+ uint16_t pid;
+ uint16_t vid;
size_t elem_count;
struct bt_mesh_elem *elem;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/atomic.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/atomic.h
new file mode 100644
index 000000000..2c7317948
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/atomic.h
@@ -0,0 +1,409 @@
+/* atomic operations */
+
+/*
+ * Copyright (c) 1997-2015, Wind River Systems, Inc.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __ATOMIC_H__
+#define __ATOMIC_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef int atomic_t;
+typedef atomic_t atomic_val_t;
+
+/**
+ * @defgroup atomic_apis Atomic Services APIs
+ * @ingroup kernel_apis
+ * @{
+ */
+
+/**
+ * @brief Atomic compare-and-set.
+ *
+ * This routine performs an atomic compare-and-set on @a target. If the current
+ * value of @a target equals @a old_value, @a target is set to @a new_value.
+ * If the current value of @a target does not equal @a old_value, @a target
+ * is left unchanged.
+ *
+ * @param target Address of atomic variable.
+ * @param old_value Original value to compare against.
+ * @param new_value New value to store.
+ * @return 1 if @a new_value is written, 0 otherwise.
+ */
+static inline int atomic_cas(atomic_t *target, atomic_val_t old_value,
+ atomic_val_t new_value)
+{
+ return __atomic_compare_exchange_n(target, &old_value, new_value,
+ 0, __ATOMIC_SEQ_CST,
+ __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic addition.
+ *
+ * This routine performs an atomic addition on @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to add.
+ *
+ * @return Previous value of @a target.
+ */
+static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic subtraction.
+ *
+ * This routine performs an atomic subtraction on @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to subtract.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic increment.
+ *
+ * This routine performs an atomic increment by 1 on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_inc(atomic_t *target)
+{
+ return atomic_add(target, 1);
+}
+
+/**
+ *
+ * @brief Atomic decrement.
+ *
+ * This routine performs an atomic decrement by 1 on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_dec(atomic_t *target)
+{
+ return atomic_sub(target, 1);
+}
+
+/**
+ *
+ * @brief Atomic get.
+ *
+ * This routine performs an atomic read on @a target.
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Value of @a target.
+ */
+
+static inline atomic_val_t atomic_get(const atomic_t *target)
+{
+ return __atomic_load_n(target, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic get-and-set.
+ *
+ * This routine atomically sets @a target to @a value and returns
+ * the previous value of @a target.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to write to @a target.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
+{
+ /* This builtin, as described by Intel, is not a traditional
+ * test-and-set operation, but rather an atomic exchange operation. It
+ * writes value into *ptr, and returns the previous contents of *ptr.
+ */
+ return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic clear.
+ *
+ * This routine atomically sets @a target to zero and returns its previous
+ * value. (Hence, it is equivalent to atomic_set(target, 0).)
+ *
+ * @param target Address of atomic variable.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_clear(atomic_t *target)
+{
+ return atomic_set(target, 0);
+}
+
+/**
+ *
+ * @brief Atomic bitwise inclusive OR.
+ *
+ * This routine atomically sets @a target to the bitwise inclusive OR of
+ * @a target and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to OR.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic bitwise exclusive OR (XOR).
+ *
+ * This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
+ * @a target and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to XOR
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic bitwise AND.
+ *
+ * This routine atomically sets @a target to the bitwise AND of @a target
+ * and @a value.
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to AND.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
+}
+
+/**
+ *
+ * @brief Atomic bitwise NAND.
+ *
+ * This routine atomically sets @a target to the bitwise NAND of @a target
+ * and @a value. (This operation is equivalent to target = ~(target & value).)
+ *
+ * @param target Address of atomic variable.
+ * @param value Value to NAND.
+ *
+ * @return Previous value of @a target.
+ */
+
+static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
+{
+ return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
+}
+
+ /**
+ * @brief Initialize an atomic variable.
+ *
+ * This macro can be used to initialize an atomic variable. For example,
+ * @code atomic_t my_var = ATOMIC_INIT(75); @endcode
+ *
+ * @param i Value to assign to atomic variable.
+ */
+#define ATOMIC_INIT(i) (i)
+
+ /**
+ * @cond INTERNAL_HIDDEN
+ */
+
+#define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
+#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1)))
+#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
+
+ /**
+ * INTERNAL_HIDDEN @endcond
+ */
+
+ /**
+ * @brief Define an array of atomic variables.
+ *
+ * This macro defines an array of atomic variables containing at least
+ * @a num_bits bits.
+ *
+ * @note
+ * If used from file scope, the bits of the array are initialized to zero;
+ * if used from within a function, the bits are left uninitialized.
+ *
+ * @param name Name of array of atomic variables.
+ * @param num_bits Number of bits needed.
+ */
+#define ATOMIC_DEFINE(name, num_bits) \
+ atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS]
+
+ /**
+ * @brief Atomically test a bit.
+ *
+ * This routine tests whether bit number @a bit of @a target is set or not.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return 1 if the bit was set, 0 if it wasn't.
+ */
+ static inline int
+ atomic_test_bit(const atomic_t *target, int bit)
+ {
+ atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
+
+ return (1 & (val >> (bit & (ATOMIC_BITS - 1))));
+ }
+
+ /**
+ * @brief Atomically test and clear a bit.
+ *
+ * Atomically clear bit number @a bit of @a target and return its old value.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return 1 if the bit was set, 0 if it wasn't.
+ */
+ static inline int
+ atomic_test_and_clear_bit(atomic_t *target, int bit)
+ {
+ atomic_val_t mask = ATOMIC_MASK(bit);
+ atomic_val_t old;
+
+ old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+
+ return (old & mask) != 0;
+ }
+
+ /**
+ * @brief Atomically set a bit.
+ *
+ * Atomically set bit number @a bit of @a target and return its old value.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return 1 if the bit was set, 0 if it wasn't.
+ */
+ static inline int
+ atomic_test_and_set_bit(atomic_t *target, int bit)
+ {
+ atomic_val_t mask = ATOMIC_MASK(bit);
+ atomic_val_t old;
+
+ old = atomic_or(ATOMIC_ELEM(target, bit), mask);
+
+ return (old & mask) != 0;
+ }
+
+ /**
+ * @brief Atomically clear a bit.
+ *
+ * Atomically clear bit number @a bit of @a target.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return N/A
+ */
+ static inline void
+ atomic_clear_bit(atomic_t *target, int bit)
+ {
+ atomic_val_t mask = ATOMIC_MASK(bit);
+
+ atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+ }
+
+ /**
+ * @brief Atomically set a bit.
+ *
+ * Atomically set bit number @a bit of @a target.
+ * The target may be a single atomic variable or an array of them.
+ *
+ * @param target Address of atomic variable or array.
+ * @param bit Bit number (starting from 0).
+ *
+ * @return N/A
+ */
+ static inline void
+ atomic_set_bit(atomic_t *target, int bit)
+ {
+ atomic_val_t mask = ATOMIC_MASK(bit);
+
+ atomic_or(ATOMIC_ELEM(target, bit), mask);
+ }
+
+/**
+* @brief Atomically set a bit to a given value.
+*
+* Atomically set bit number @a bit of @a target to value @a val.
+* The target may be a single atomic variable or an array of them.
+*
+* @param target Address of atomic variable or array.
+* @param bit Bit number (starting from 0).
+* @param val true for 1, false for 0.
+*
+* @return N/A
+*/
+static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
+{
+ atomic_val_t mask = ATOMIC_MASK(bit);
+
+ if (val) {
+ (void)atomic_or(ATOMIC_ELEM(target, bit), mask);
+ } else {
+ (void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
+ }
+}
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ATOMIC_H__ */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cdb.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cdb.h
new file mode 100644
index 000000000..050ccf281
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cdb.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2019 Tobias Svehagen
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _BLUETOOTH_MESH_CDB_H_
+#define _BLUETOOTH_MESH_CDB_H_
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+
+#if MYNEWT_VAL(BLE_MESH_CDB)
+#define NODE_COUNT CONFIG_BT_MESH_NODE_COUNT
+#define SUBNET_COUNT CONFIG_BT_MESH_SUBNET_COUNT
+#define APP_KEY_COUNT CONFIG_BT_MESH_APP_KEY_COUNT
+#else
+#define NODE_COUNT 0
+#define SUBNET_COUNT 0
+#define APP_KEY_COUNT 0
+#endif
+
+#include "atomic.h"
+
+enum {
+ BT_MESH_CDB_NODE_CONFIGURED,
+ BT_MESH_CDB_NODE_BLACKLISTED,
+
+ BT_MESH_CDB_NODE_FLAG_COUNT
+};
+
+struct bt_mesh_cdb_node {
+ uint8_t uuid[16];
+ uint16_t addr;
+ uint16_t net_idx;
+ uint8_t num_elem;
+ uint8_t dev_key[16];
+
+ ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT);
+};
+
+struct bt_mesh_cdb_subnet {
+ uint16_t net_idx;
+
+ bool kr_flag;
+ uint8_t kr_phase;
+
+ struct {
+ uint8_t net_key[16];
+ } keys[2];
+};
+
+struct bt_mesh_cdb_app_key {
+ uint16_t net_idx;
+ uint16_t app_idx;
+
+ struct {
+ uint8_t app_key[16];
+ } keys[2];
+};
+
+enum {
+ BT_MESH_CDB_VALID,
+ BT_MESH_CDB_SUBNET_PENDING,
+ BT_MESH_CDB_KEYS_PENDING,
+ BT_MESH_CDB_NODES_PENDING,
+ BT_MESH_CDB_IVU_IN_PROGRESS,
+
+ BT_MESH_CDB_FLAG_COUNT,
+};
+
+struct bt_mesh_cdb {
+ uint32_t iv_index;
+
+ ATOMIC_DEFINE(flags, BT_MESH_CDB_FLAG_COUNT);
+
+ struct bt_mesh_cdb_node nodes[NODE_COUNT];
+ struct bt_mesh_cdb_subnet subnets[SUBNET_COUNT];
+ struct bt_mesh_cdb_app_key app_keys[APP_KEY_COUNT];
+};
+
+extern struct bt_mesh_cdb bt_mesh_cdb;
+
+/** @brief Create the Mesh Configuration Database.
+ *
+ * Create and initialize the Mesh Configuration Database. A primary subnet,
+ * ie one with NetIdx 0, will be added and the provided key will be used as
+ * NetKey for that subnet.
+ *
+ * @param key The NetKey to be used for the primary subnet.
+ *
+ * @return 0 on success or negative error code on failure.
+ */
+int bt_mesh_cdb_create(const uint8_t key[16]);
+
+/** @brief Clear the Mesh Configuration Database.
+ *
+ * Remove all nodes, subnets and app-keys stored in the database and mark
+ * the database as invalid. The data will be cleared from persistent storage
+ * if CONFIG_BT_SETTINGS is enabled.
+ */
+void bt_mesh_cdb_clear(void);
+
+/** @brief Set and store the IV Index and IV Update flag.
+ *
+ * The IV Index stored in the CDB will be the one used during provisioning
+ * of new nodes. This function is generally only used from inside the stack.
+ *
+ * This function will store the data to persistent storage if
+ * CONFIG_BT_SETTINGS is enabled.
+ *
+ * @param iv_index The new IV Index to use.
+ * @param iv_update True if there is an ongoing IV Update procedure.
+ */
+void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update);
+
+/** @brief Allocate a node.
+ *
+ * Allocate a new node in the CDB.
+ *
+ * @param uuid UUID of the node.
+ * @param addr Address of the node's primary element. If 0, the lowest
+ * possible address available will be assigned to the node.
+ * @param num_elem Number of elements that the node has.
+ * @param net_idx NetIdx that the node was provisioned to.
+ *
+ * @return The new node or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem, uint16_t net_idx);
+
+/** @brief Delete a node.
+ *
+ * Delete a node from the CDB.
+ *
+ * @param node The node to be deleted.
+ * @param store If true, the node will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store);
+
+/** @brief Get a node by address.
+ *
+ * Try to find the node that has the provided address assigned to one of its
+ * elements.
+ *
+ * @param addr Address of the element to look for.
+ *
+ * @return The node that has an element with address addr or NULL if no such
+ * node exists.
+ */
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr);
+
+/** @brief Store node to persistent storage.
+ *
+ * @param node Node to be stored.
+ */
+void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node);
+
+enum {
+ BT_MESH_CDB_ITER_STOP = 0,
+ BT_MESH_CDB_ITER_CONTINUE,
+};
+
+/** @typedef bt_mesh_cdb_node_func_t
+ * @brief Node iterator callback.
+ *
+ * @param node Node found.
+ * @param user_data Data given.
+ *
+ * @return BT_MESH_CDB_ITER_CONTINUE to continue to iterate through the nodes
+ * or BT_MESH_CDB_ITER_STOP to stop.
+ */
+typedef uint8_t (*bt_mesh_cdb_node_func_t)(struct bt_mesh_cdb_node *node,
+ void *user_data);
+
+/** @brief Node iterator.
+ *
+ * Iterate nodes in the Mesh Configuration Database. The callback function
+ * will only be called for valid, ie allocated, nodes.
+ *
+ * @param func Callback function.
+ * @param user_data Data to pass to the callback.
+ */
+void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data);
+
+/** @brief Allocate a subnet.
+ *
+ * Allocate a new subnet in the CDB.
+ *
+ * @param net_idx NetIdx of the subnet.
+ *
+ * @return The new subnet or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx);
+
+/** @brief Delete a subnet.
+ *
+ * Delete a subnet from the CDB.
+ *
+ * @param sub The subnet to be deleted.
+ * @param store If true, the subnet will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store);
+
+/** @brief Get a subnet by NetIdx
+ *
+ * Try to find the subnet with the specified NetIdx.
+ *
+ * @param net_idx NetIdx of the subnet to look for.
+ *
+ * @return The subnet with the specified NetIdx or NULL if no such subnet
+ * exists.
+ */
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx);
+
+/** @brief Store subnet to persistent storage.
+ *
+ * @param sub Subnet to be stored.
+ */
+void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub);
+
+/** @brief Get the flags for a subnet
+ *
+ * @param sub The subnet to get flags for.
+ *
+ * @return The flags for the subnet.
+ */
+uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub);
+
+
+/** @brief Allocate an application key.
+ *
+ * Allocate a new application key in the CDB.
+ *
+ * @param net_idx NetIdx of NetKey that the application key is bound to.
+ * @param app_idx AppIdx of the application key.
+ *
+ * @return The new application key or NULL if it cannot be allocated.
+ */
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
+ uint16_t app_idx);
+
+/** @brief Delete an application key.
+ *
+ * Delete an application key from the CDB.
+ *
+ * @param key The application key to be deleted.
+ * @param store If true, the key will be cleared from persistent storage.
+ */
+void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store);
+
+/** @brief Get an application key by AppIdx
+ *
+ * Try to find the application key with the specified AppIdx.
+ *
+ * @param app_idx AppIdx of the application key to look for.
+ *
+ * @return The application key with the specified AppIdx or NULL if no such key
+ * exists.
+ */
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx);
+
+/** @brief Store application key to persistent storage.
+ *
+ * @param key Application key to be stored.
+ */
+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
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg.h
new file mode 100644
index 000000000..378f0a0aa
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg.h
@@ -0,0 +1,485 @@
+/** @file
+ * @brief Bluetooth Mesh Runtime Configuration APIs.
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _BT_MESH_CFG_H_
+#define _BT_MESH_CFG_H_
+
+#include
+#include
+#include
+
+/**
+ * @brief Bluetooth Mesh Runtime Configuration API
+ * @defgroup bt_mesh_cfg Bluetooth Mesh Runtime Configuration
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Bluetooth Mesh Feature states */
+enum bt_mesh_feat_state {
+ /** Feature is supported, but disabled. */
+ BT_MESH_FEATURE_DISABLED,
+ /** Feature is supported and enabled. */
+ BT_MESH_FEATURE_ENABLED,
+ /** Feature is not supported, and cannot be enabled. */
+ BT_MESH_FEATURE_NOT_SUPPORTED,
+};
+
+/* Legacy feature defines */
+#define BT_MESH_RELAY_DISABLED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_RELAY_ENABLED BT_MESH_FEATURE_ENABLED
+#define BT_MESH_RELAY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_BEACON_DISABLED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_BEACON_ENABLED BT_MESH_FEATURE_ENABLED
+
+#define BT_MESH_GATT_PROXY_DISABLED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_GATT_PROXY_ENABLED BT_MESH_FEATURE_ENABLED
+#define BT_MESH_GATT_PROXY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_FRIEND_DISABLED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_FRIEND_ENABLED BT_MESH_FEATURE_ENABLED
+#define BT_MESH_FRIEND_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+#define BT_MESH_NODE_IDENTITY_STOPPED BT_MESH_FEATURE_DISABLED
+#define BT_MESH_NODE_IDENTITY_RUNNING BT_MESH_FEATURE_ENABLED
+#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
+
+/** @brief Enable or disable sending of the Secure Network Beacon.
+ *
+ * @param beacon New Secure Network Beacon state.
+ */
+void bt_mesh_beacon_set(bool beacon);
+
+/** @brief Get the current Secure Network Beacon state.
+ *
+ * @returns Whether the Secure Network Beacon feature is enabled.
+ */
+bool bt_mesh_beacon_enabled(void);
+
+/** @brief Set the default TTL value.
+ *
+ * The default TTL value is used when no explicit TTL value is set. Models will
+ * use the default TTL value when @ref bt_mesh_msg_ctx::send_ttl is
+ * @ref BT_MESH_TTL_DEFAULT.
+ *
+ * @param default_ttl The new default TTL value. Valid values are 0x00 and 0x02
+ * to @ref BT_MESH_TTL_MAX.
+ *
+ * @retval 0 Successfully set the default TTL value.
+ * @retval -EINVAL Invalid TTL value.
+ */
+int bt_mesh_default_ttl_set(uint8_t default_ttl);
+
+/** @brief Get the current default TTL value.
+ *
+ * @return The current default TTL value.
+ */
+uint8_t bt_mesh_default_ttl_get(void);
+
+/** @brief Set the Network Transmit parameters.
+ *
+ * The Network Transmit parameters determine the parameters local messages are
+ * transmitted with.
+ *
+ * @see BT_MESH_TRANSMIT
+ *
+ * @param xmit New Network Transmit parameters. Use @ref BT_MESH_TRANSMIT for
+ * encoding.
+ */
+void bt_mesh_net_transmit_set(uint8_t xmit);
+
+/** @brief Get the current Network Transmit parameters.
+ *
+ * The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
+ * used to decode the Network Transmit parameters.
+ *
+ * @return The current Network Transmit parameters.
+ */
+uint8_t bt_mesh_net_transmit_get(void);
+
+/** @brief Configure the Relay feature.
+ *
+ * Enable or disable the Relay feature, and configure the parameters to
+ * transmit relayed messages with.
+ *
+ * Support for the Relay feature must be enabled through the
+ * @c CONFIG_BT_MESH_RELAY configuration option.
+ *
+ * @see BT_MESH_TRANSMIT
+ *
+ * @param relay New Relay feature state. Must be one of
+ * @ref BT_MESH_FEATURE_ENABLED and
+ * @ref BT_MESH_FEATURE_DISABLED.
+ * @param xmit New Relay retransmit parameters. Use @ref BT_MESH_TRANSMIT for
+ * encoding.
+ *
+ * @retval 0 Successfully changed the Relay configuration.
+ * @retval -ENOTSUP The Relay feature is not supported.
+ * @retval -EINVAL Invalid parameter.
+ * @retval -EALREADY Already using the given parameters.
+ */
+int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit);
+
+/** @brief Get the current Relay feature state.
+ *
+ * @returns The Relay feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_relay_get(void);
+
+/** @brief Get the current Relay Retransmit parameters.
+ *
+ * The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
+ * used to decode the Relay Retransmit parameters.
+ *
+ * @return The current Relay Retransmit parameters, or 0 if relay is not
+ * supported.
+ */
+uint8_t bt_mesh_relay_retransmit_get(void);
+
+/** @brief Enable or disable the GATT Proxy feature.
+ *
+ * Support for the GATT Proxy feature must be enabled through the
+ * @c CONFIG_BT_MESH_GATT_PROXY configuration option.
+ *
+ * @note The GATT Proxy feature only controls a Proxy node's ability to relay
+ * messages to the mesh network. A node that supports GATT Proxy will
+ * still advertise Connectable Proxy beacons, even if the feature is
+ * disabled. The Proxy feature can only be fully disabled through compile
+ * time configuration.
+ *
+ * @param gatt_proxy New GATT Proxy state. Must be one of
+ * @ref BT_MESH_FEATURE_ENABLED and
+ * @ref BT_MESH_FEATURE_DISABLED.
+ *
+ * @retval 0 Successfully changed the GATT Proxy feature state.
+ * @retval -ENOTSUP The GATT Proxy feature is not supported.
+ * @retval -EINVAL Invalid parameter.
+ * @retval -EALREADY Already in the given state.
+ */
+int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy);
+
+/** @brief Get the current GATT Proxy state.
+ *
+ * @returns The GATT Proxy feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void);
+
+/** @brief Enable or disable the Friend feature.
+ *
+ * Any active friendships will be terminated immediately if the Friend feature
+ * is disabled.
+ *
+ * Support for the Friend feature must be enabled through the
+ * @c CONFIG_BT_MESH_FRIEND configuration option.
+ *
+ * @param friendship New Friend feature state. Must be one of
+ * @ref BT_MESH_FEATURE_ENABLED and
+ * @ref BT_MESH_FEATURE_DISABLED.
+ *
+ * @retval 0 Successfully changed the Friend feature state.
+ * @retval -ENOTSUP The Friend feature is not supported.
+ * @retval -EINVAL Invalid parameter.
+ * @retval -EALREADY Already in the given state.
+ */
+int bt_mesh_friend_set(enum bt_mesh_feat_state friendship);
+
+/** @brief Get the current Friend state.
+ *
+ * @returns The Friend feature state.
+ */
+enum bt_mesh_feat_state bt_mesh_friend_get(void);
+
+/**
+ * @brief Bluetooth Mesh Subnet Configuration
+ * @defgroup bt_mesh_cfg_subnet Bluetooth Mesh Subnet Configuration
+ * @{
+ */
+
+/** @brief Add a Subnet.
+ *
+ * Adds a subnet with the given network index and network key to the list of
+ * known Subnets. All messages sent on the given Subnet will be processed by
+ * this node, and the node may send and receive Network Beacons on the given
+ * Subnet.
+ *
+ * @param net_idx Network index.
+ * @param key Root network key of the Subnet. All other keys are derived
+ * from this.
+ *
+ * @retval STATUS_SUCCESS The Subnet was successfully added.
+ * @retval STATUS_INSUFF_RESOURCES No room for this Subnet.
+ * @retval STATUS_UNSPECIFIED The Subnet couldn't be created for some reason.
+ */
+uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16]);
+
+/** @brief Update the given Subnet.
+ *
+ * Starts the Key Refresh procedure for this Subnet by adding a second set of
+ * encryption keys. The Subnet will continue sending with the old key (but
+ * receiving messages using both) until the Subnet enters Key Refresh phase 2.
+ *
+ * This allows a network configurator to replace old network and application
+ * keys for the entire network, effectively removing access for all nodes that
+ * aren't given the new keys.
+ *
+ * @param net_idx Network index.
+ * @param key New root network key of the Subnet.
+ *
+ * @retval STATUS_SUCCESS The Subnet was updated with a second key.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_IDX_ALREADY_STORED The @c key value is the same as the
+ * current key.
+ * @retval STATUS_CANNOT_UPDATE The Subnet cannot be updated for some reason.
+ */
+uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16]);
+
+/** @brief Delete a Subnet.
+ *
+ * Removes the Subnet with the given network index from the node. The node will
+ * stop sending Network Beacons with the given Subnet, and can no longer
+ * process messages on this Subnet.
+ *
+ * All Applications bound to this Subnet are also deleted.
+ *
+ * @param net_idx Network index.
+ *
+ * @retval STATUS_SUCCESS The Subnet was deleted.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_del(uint16_t net_idx);
+
+/** @brief Check whether a Subnet is known.
+ *
+ * @param net_idx Network index
+ *
+ * @return true if a Subnet with the given index exists, false otherwise.
+ */
+bool bt_mesh_subnet_exists(uint16_t net_idx);
+
+/** @brief Set the Subnet's Key Refresh phase.
+ *
+ * The Key Refresh procedure is started by updating the Subnet keys through
+ * @ref bt_mesh_subnet_update. This puts the Subnet in Key Refresh Phase 1.
+ * Once all nodes have received the new Subnet key, Key Refresh Phase 2 can be
+ * activated through this function to start transmitting with the new network
+ * key. Finally, to revoke the old key, set the Key Refresh Phase to 3. This
+ * removes the old keys from the node, and returns the Subnet back to normal
+ * single-key operation with the new key set.
+ *
+ * @param net_idx Network index.
+ * @param phase Pointer to the new Key Refresh phase. Will return the actual
+ * Key Refresh phase after updating.
+ *
+ * @retval STATUS_SUCCESS The Key Refresh phase of the Subnet was successfully
+ * changed.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_CANNOT_UPDATE The given phase change is invalid.
+ */
+uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase);
+
+/** @brief Get the Subnet's Key Refresh phase.
+ *
+ * @param net_idx Network index.
+ * @param phase Pointer to the Key Refresh variable to fill.
+ *
+ * @retval STATUS_SUCCESS Successfully populated the @c phase variable.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase);
+
+/** @brief Set the Node Identity state of the Subnet.
+ *
+ * The Node Identity state of a Subnet determines whether the Subnet advertises
+ * connectable Node Identity beacons for Proxy Clients to connect to.
+ * Once started, the Node Identity beacon runs for 60 seconds, or until it is
+ * stopped.
+ *
+ * This function serves the same purpose as @ref bt_mesh_proxy_identity_enable,
+ * but only acts on a single Subnet.
+ *
+ * GATT Proxy support must be enabled through
+ * @option{CONFIG_BT_MESH_GATT_PROXY}.
+ *
+ * @param net_idx Network index.
+ * @param node_id New Node Identity state, must be either @ref
+ * BT_MESH_FEATURE_ENABLED or @ref BT_MESH_FEATURE_DISABLED.
+ *
+ * @retval STATUS_SUCCESS Successfully set the Node Identity state of the
+ * Subnet.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_FEAT_NOT_SUPP The Node Identity feature is not supported.
+ * @retval STATUS_CANNOT_SET Couldn't set the Node Identity state.
+ */
+uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
+ enum bt_mesh_feat_state node_id);
+
+/** @brief Get the Node Identity state of the Subnet.
+ *
+ * @param net_idx Network index.
+ * @param node_id Node Identity variable to fill.
+ *
+ * @retval STATUS_SUCCESS Successfully populated the @c node_id variable.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ */
+uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
+ enum bt_mesh_feat_state *node_id);
+
+/** @brief Get a list of all known Subnet indexes.
+ *
+ * Builds a list of all known Subnet indexes in the @c net_idxs array.
+ * If the @c net_idxs array is smaller than the list of known Subnets, this
+ * function fills all available entries and returns @c -ENOMEM. In this
+ * case, the next @c max entries of the list can be read out by calling
+ * @code
+ * bt_mesh_subnets_get(list, max, max);
+ * @endcode
+ *
+ * Note that any changes to the Subnet list between calls to this function
+ * could change the order and number of entries in the list.
+ *
+ * @param net_idxs Array to fill.
+ * @param max Max number of indexes to return.
+ * @param skip Number of indexes to skip. Enables batched processing of the
+ * list.
+ *
+ * @return The number of indexes added to the @c net_idxs array, or @c -ENOMEM
+ * if the number of known Subnets exceeds the @c max parameter.
+ */
+ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip);
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Bluetooth Mesh Application Configuration
+ * @defgroup bt_mesh_cfg_app Bluetooth Mesh Application Configuration
+ * @{
+ */
+
+/** @brief Add an Application key.
+ *
+ * Adds the Application with the given index to the list of known applications.
+ * Allows the node to send and receive model messages encrypted with this
+ * Application key.
+ *
+ * Every Application is bound to a specific Subnet. The node must know the
+ * Subnet the Application is bound to before it can add the Application.
+ *
+ * @param app_idx Application index.
+ * @param net_idx Network index the Application is bound to.
+ * @param key Application key value.
+ *
+ * @retval STATUS_SUCCESS The Application was successfully added.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_INSUFF_RESOURCES There's no room for storing this
+ * Application.
+ * @retval STATUS_INVALID_BINDING This AppIdx is already bound to another
+ * Subnet.
+ * @retval STATUS_IDX_ALREADY_STORED This AppIdx is already stored with a
+ * different key value.
+ * @retval STATUS_CANNOT_SET Cannot set the Application key for some reason.
+ */
+uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t key[16]);
+
+/** @brief Update an Application key.
+ *
+ * Update an Application with a second Application key, as part of the
+ * Key Refresh procedure of the bound Subnet. The node will continue
+ * transmitting with the old application key (but receiving on both) until the
+ * Subnet enters Key Refresh phase 2. Once the Subnet enters Key Refresh phase
+ * 3, the old application key will be deleted.
+ *
+ * @note The Application key can only be updated if the bound Subnet is in Key
+ * Refresh phase 1.
+ *
+ * @param app_idx Application index.
+ * @param net_idx Network index the Application is bound to, or
+ * @ref BT_MESH_KEY_ANY to skip the binding check.
+ * @param key New key value.
+ *
+ * @retval STATUS_SUCCESS The Application key was successfully updated.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
+ * @retval STATUS_CANNOT_UPDATE The Application key cannot be updated for some
+ * reason.
+ * @retval STATUS_IDX_ALREADY_STORED This AppIdx is already updated with a
+ * different key value.
+ */
+uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t key[16]);
+
+/** @brief Delete an Application key.
+ *
+ * All models bound to this application will remove this binding.
+ * All models publishing with this application will stop publishing.
+ *
+ * @param app_idx Application index.
+ * @param net_idx Network index.
+ *
+ * @retval STATUS_SUCCESS The Application key was successfully deleted.
+ * @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
+ * @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
+ */
+uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx);
+
+/** @brief Check if an Application key is known.
+ *
+ * @param app_idx Application index.
+ *
+ * @return true if the Application is known, false otherwise.
+ */
+bool bt_mesh_app_key_exists(uint16_t app_idx);
+
+/** @brief Get a list of all known Application key indexes.
+ *
+ * Builds a list of all Application indexes for the given network index in the
+ * @c app_idxs array. If the @c app_idxs array cannot fit all bound
+ * Applications, this function fills all available entries and returns @c
+ * -ENOMEM. In this case, the next @c max entries of the list can be read out
+ * by calling
+ * @code
+ * bt_mesh_app_keys_get(net_idx, list, max, max);
+ * @endcode
+ *
+ * Note that any changes to the Application key list between calls to this
+ * function could change the order and number of entries in the list.
+ *
+ * @param net_idx Network Index to get the Applications of, or @ref
+ * BT_MESH_KEY_ANY to get all Applications.
+ * @param app_idxs Array to fill.
+ * @param max Max number of indexes to return.
+ * @param skip Number of indexes to skip. Enables batched processing of the
+ * list.
+ *
+ * @return The number of indexes added to the @c app_idxs array, or @c -ENOMEM
+ * if the number of known Applications exceeds the @c max parameter.
+ */
+ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
+ off_t skip);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* _BT_MESH_CFG_H_ */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h
index 7dc237beb..bd2f9fe5b 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h
@@ -26,7 +26,7 @@ struct bt_mesh_cfg_cli {
struct bt_mesh_model *model;
struct k_sem op_sync;
- u32_t op_pending;
+ uint32_t op_pending;
void *op_param;
};
@@ -37,45 +37,81 @@ extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb;
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_op, NULL, \
cli_data, &bt_mesh_cfg_cli_cb)
-int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
- u8_t *status, struct os_mbuf *comp);
+int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status);
-int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *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);
-int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
+int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
-int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl);
+int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
-int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl);
+int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl);
-int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status);
+int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl);
-int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
+int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
-int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status);
+int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
-int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
- u8_t *status);
+int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
-int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
- u8_t *transmit);
+int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
+ uint8_t *status);
-int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
- u8_t new_transmit, u8_t *status, u8_t *transmit);
+int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
+ uint8_t *transmit);
-int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
- const u8_t net_key[16], u8_t *status);
+int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
+ uint8_t val, uint8_t *transmit);
-int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
- u16_t key_app_idx, const u8_t app_key[16],
- u8_t *status);
+int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
+ uint8_t *transmit);
-int bt_mesh_cfg_mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u8_t *status);
+int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
+ uint8_t new_transmit, uint8_t *status, uint8_t *transmit);
-int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u16_t cid,
- u8_t *status);
+int bt_mesh_cfg_net_key_add(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_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
+ size_t *key_cnt);
+
+int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint8_t *status);
+
+int bt_mesh_cfg_app_key_add(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_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ uint8_t *status, uint16_t *keys, size_t *key_cnt);
+
+int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status);
+
+int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status);
+
+int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t mod_app_idx,
+ uint16_t mod_id, uint8_t *status);
+
+int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+ uint8_t *status);
+
+int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t mod_app_idx, uint16_t mod_id,
+ uint16_t cid, uint8_t *status);
+
+int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint8_t *status, uint16_t *apps,
+ size_t *app_cnt);
+
+int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status,
+ uint16_t *apps, size_t *app_cnt);
/** @def BT_MESH_PUB_PERIOD_100MS
*
@@ -120,109 +156,117 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
#define BT_MESH_PUB_PERIOD_10MIN(steps) (((steps) & BIT_MASK(6)) | (3 << 6))
struct bt_mesh_cfg_mod_pub {
- u16_t addr;
- u16_t app_idx;
+ uint16_t addr;
+ uint16_t app_idx;
bool cred_flag;
- u8_t ttl;
- u8_t period;
- u8_t transmit;
+ uint8_t ttl;
+ uint8_t period;
+ uint8_t transmit;
};
-int bt_mesh_cfg_mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
- u8_t *status);
+int bt_mesh_cfg_mod_pub_get(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);
-int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
+int bt_mesh_cfg_mod_pub_get_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);
-int bt_mesh_cfg_mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
- u8_t *status);
+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);
-int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *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);
-int bt_mesh_cfg_mod_sub_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status);
+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);
-int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid,
- u8_t *status);
+int bt_mesh_cfg_mod_sub_add_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);
-int bt_mesh_cfg_mod_sub_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status);
+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);
-int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid,
- u8_t *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);
-int bt_mesh_cfg_mod_sub_overwrite(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *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);
-int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
- u16_t elem_addr, u16_t sub_addr,
- u16_t mod_id, u16_t cid, u8_t *status);
+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);
-int bt_mesh_cfg_mod_sub_va_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t cid, u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t cid, uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t cid, u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t cid, uint16_t *virt_addr, uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_overwrite(u16_t net_idx, u16_t addr,
- u16_t elem_addr, const u8_t label[16],
- u16_t mod_id, u16_t *virt_addr,
- u8_t *status);
+int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, const uint8_t label[16],
+ uint16_t mod_id, uint16_t *virt_addr,
+ uint8_t *status);
-int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
- u16_t elem_addr, const u8_t label[16],
- u16_t mod_id, u16_t cid,
- u16_t *virt_addr, u8_t *status);
+int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, const uint8_t label[16],
+ uint16_t mod_id, uint16_t cid,
+ uint16_t *virt_addr, uint8_t *status);
+
+int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint8_t *status, uint16_t *subs,
+ size_t *sub_cnt);
+
+int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status,
+ uint16_t *subs, size_t *sub_cnt);
struct bt_mesh_cfg_hb_sub {
- u16_t src;
- u16_t dst;
- u8_t period;
- u8_t count;
- u8_t min;
- u8_t max;
+ uint16_t src;
+ uint16_t dst;
+ uint8_t period;
+ uint8_t count;
+ uint8_t min;
+ uint8_t max;
};
-int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
+int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
-int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
+int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
struct bt_mesh_cfg_hb_pub {
- u16_t dst;
- u8_t count;
- u8_t period;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx;
+ uint16_t dst;
+ uint8_t count;
+ uint8_t period;
+ uint8_t ttl;
+ uint16_t feat;
+ uint16_t net_idx;
};
-int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
- const struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
+int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
+ const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
-int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
+int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
-s32_t bt_mesh_cfg_cli_timeout_get(void);
-void bt_mesh_cfg_cli_timeout_set(s32_t timeout);
+int32_t bt_mesh_cfg_cli_timeout_get(void);
+void bt_mesh_cfg_cli_timeout_set(int32_t timeout);
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h
index 14d8a2956..5bf3f4399 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h
@@ -21,51 +21,13 @@
extern "C" {
#endif
-/** Mesh Configuration Server Model Context */
-struct bt_mesh_cfg_srv {
- struct bt_mesh_model *model;
-
- u8_t net_transmit; /* Network Transmit state */
- u8_t relay; /* Relay Mode state */
- u8_t relay_retransmit; /* Relay Retransmit state */
- u8_t beacon; /* Secure Network Beacon state */
- u8_t gatt_proxy; /* GATT Proxy state */
- u8_t frnd; /* Friend state */
- u8_t default_ttl; /* Default TTL */
-
- /* Heartbeat Publication */
- struct bt_mesh_hb_pub {
- struct k_delayed_work timer;
-
- u16_t dst;
- u16_t count;
- u8_t period;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx;
- } hb_pub;
-
- /* Heartbeat Subscription */
- struct bt_mesh_hb_sub {
- s64_t expiry;
-
- u16_t src;
- u16_t dst;
- u16_t count;
- u8_t min_hops;
- u8_t max_hops;
-
- /* Optional subscription tracking function */
- void (*func)(u8_t hops, u16_t feat);
- } hb_sub;
-};
extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[];
extern const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb;
-#define BT_MESH_MODEL_CFG_SRV(srv_data) \
+#define BT_MESH_MODEL_CFG_SRV \
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \
- srv_data, &bt_mesh_cfg_srv_cb)
+ NULL, &bt_mesh_cfg_srv_cb)
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h
index f50b6ece8..d27e7ebbe 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/glue.h
@@ -62,15 +62,6 @@
extern "C" {
#endif
-#define u8_t uint8_t
-#define s8_t int8_t
-#define u16_t uint16_t
-#define s16_t int16_t
-#define u32_t uint32_t
-#define u64_t uint64_t
-#define s64_t int64_t
-#define s32_t int32_t
-
/** @brief Helper to declare elements of bt_data arrays
*
* This macro is mainly for creating an array of struct bt_data
@@ -84,7 +75,7 @@ extern "C" {
{ \
.type = (_type), \
.data_len = (_data_len), \
- .data = (const u8_t *)(_data), \
+ .data = (const uint8_t *)(_data), \
}
/** @brief Helper to declare elements of bt_data arrays
@@ -96,8 +87,8 @@ extern "C" {
* @param _bytes Variable number of single-byte parameters
*/
#define BT_DATA_BYTES(_type, _bytes...) \
- BT_DATA(_type, ((u8_t []) { _bytes }), \
- sizeof((u8_t []) { _bytes }))
+ BT_DATA(_type, ((uint8_t []) { _bytes }), \
+ sizeof((uint8_t []) { _bytes }))
/* EIR/AD data type definitions */
#define BT_DATA_FLAGS 0x01 /* AD flags */
@@ -130,9 +121,13 @@ extern "C" {
#define sys_put_be16(a,b) put_be16(b, a)
#define sys_put_le16(a,b) put_le16(b, a)
+#define sys_put_le24(a,b) put_le24(b, a)
+#define sys_put_be24(a,b) put_be24(b, a)
#define sys_put_be32(a,b) put_be32(b, a)
#define sys_get_be16(a) get_be16(a)
+#define sys_get_be24(a) get_be24(a)
#define sys_get_le16(a) get_le16(a)
+#define sys_get_le24(a) get_le24(a)
#define sys_get_be32(a) get_be32(a)
#define sys_cpu_to_be16(a) htobe16(a)
#define sys_cpu_to_be32(a) htobe32(a)
@@ -207,9 +202,9 @@ typedef ble_addr_t bt_addr_le_t;
struct net_buf_simple_state {
/** Offset of the data pointer from the beginning of the storage */
- u16_t offset;
+ uint16_t offset;
/** Length of data */
- u16_t len;
+ uint16_t len;
};
static inline struct os_mbuf * NET_BUF_SIMPLE(uint16_t size)
@@ -249,6 +244,14 @@ static inline void net_buf_simple_init(struct os_mbuf *buf,
buf->om_len = 0;
}
+#define net_buf_simple_init_with_data(buf, data, size) \
+ os_mbuf_copyinto(buf, 0, data, size);
+
+static inline void net_buf_simple_reset(struct os_mbuf *om)
+{
+ net_buf_simple_init(om, 0);
+}
+
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);
@@ -259,18 +262,20 @@ uint32_t net_buf_simple_pull_le32(struct os_mbuf *om);
uint8_t net_buf_simple_pull_u8(struct os_mbuf *om);
void net_buf_simple_add_le16(struct os_mbuf *om, uint16_t val);
void net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val);
+void net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val);
void net_buf_simple_add_u8(struct os_mbuf *om, uint8_t val);
void net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val);
void net_buf_simple_add_le32(struct os_mbuf *om, uint32_t val);
void net_buf_add_zeros(struct os_mbuf *om, uint8_t len);
void net_buf_simple_push_le16(struct os_mbuf *om, uint16_t val);
void net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val);
+void net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val);
void net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val);
void *net_buf_simple_pull(struct os_mbuf *om, uint8_t len);
void *net_buf_simple_pull_mem(struct os_mbuf *om, uint8_t len);
void *net_buf_simple_add(struct os_mbuf *om, uint8_t len);
bool k_fifo_is_empty(struct ble_npl_eventq *q);
-void *net_buf_get(struct ble_npl_eventq *fifo,s32_t t);
+void *net_buf_get(struct ble_npl_eventq *fifo,int32_t t);
uint8_t *net_buf_simple_push(struct os_mbuf *om, uint8_t len);
void net_buf_reserve(struct os_mbuf *om, size_t reserve);
@@ -282,7 +287,7 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
#define net_buf_clone(a, b) os_mbuf_dup(a)
#define net_buf_add_be32(a, b) net_buf_simple_add_be32(a, b)
#define net_buf_add_be16(a, b) net_buf_simple_add_be16(a, b)
-#define net_buf_pull(a, b) net_buf_simple_pull(a, b)
+#define net_buf_pull(a, b) net_buf_simple_pull_mem(a, b)
#define net_buf_pull_mem(a, b) net_buf_simple_pull_mem(a, b)
#define net_buf_pull_u8(a) net_buf_simple_pull_u8(a)
#define net_buf_pull_be16(a) net_buf_simple_pull_be16(a)
@@ -290,14 +295,22 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
#define BT_GATT_CCC_NOTIFY BLE_GATT_CHR_PROP_NOTIFY
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
/** Description of different data types that can be encoded into
* advertising data. Used to form arrays that are passed to the
* bt_le_adv_start() function.
*/
struct bt_data {
- u8_t type;
- u8_t data_len;
- const u8_t *data;
+ uint8_t type;
+ uint8_t data_len;
+ const uint8_t *data;
};
struct bt_pub_key_cb {
@@ -309,18 +322,24 @@ struct bt_pub_key_cb {
*
* @param key The local public key, or NULL in case of no key.
*/
- void (*func)(const u8_t key[64]);
+ void (*func)(const uint8_t key[64]);
struct bt_pub_key_cb *_next;
};
-typedef void (*bt_dh_key_cb_t)(const u8_t key[32]);
-int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb);
+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);
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);
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);
+int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
+ size_t len, const uint8_t *aad, size_t aad_len,
+ uint8_t *plaintext, size_t mic_size);
+int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
+ size_t len, const uint8_t *aad, size_t aad_len,
+ 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,
const struct bt_data *ad, size_t ad_len,
@@ -334,9 +353,10 @@ struct k_delayed_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);
int64_t k_uptime_get(void);
-u32_t k_uptime_get_32(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);
@@ -366,18 +386,18 @@ static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
src += length - 1;
for (; length > 0; length--) {
- *((u8_t *)dst++) = *((u8_t *)src--);
+ *((uint8_t *)dst++) = *((uint8_t *)src--);
}
}
#define popcount(x) __builtin_popcount(x)
-static inline unsigned int find_lsb_set(u32_t op)
+static inline unsigned int find_lsb_set(uint32_t op)
{
return __builtin_ffs(op);
}
-static inline unsigned int find_msb_set(u32_t op)
+static inline unsigned int find_msb_set(uint32_t op)
{
if (!op)
return 0;
@@ -385,43 +405,61 @@ static inline unsigned int find_msb_set(u32_t op)
return 32 - __builtin_clz(op);
}
-#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND
-#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
-#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
-#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
-#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
-#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
-#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
-#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
-#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
-#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
-#define CONFIG_BT_TESTING BLE_MESH_TESTING
-#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
-#define CONFIG_SETTINGS BLE_MESH_SETTINGS
-#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
+#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND
+#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
+#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
+#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
+#define CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR BLE_MESH_LPN_SUB_ALL_NODES_ADDR
+#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
+#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
+#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
+#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT
+#define CONFIG_BT_MESH_PROV BLE_MESH_PROV
+#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY
+#define CONFIG_BT_TESTING BLE_MESH_TESTING
+#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
+#define CONFIG_SETTINGS BLE_MESH_SETTINGS
+#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
/* Above flags are used with IS_ENABLED macro */
#define IS_ENABLED(config) MYNEWT_VAL(config)
-#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_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)
-#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT)
-#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT)
-#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT)
-#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS)
-#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE)
-#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT)
-#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_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
-#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
-#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
-#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
-#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_NODE_COUNT)
+#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_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)
+#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT)
+#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT)
+#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT)
+#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS)
+#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE)
+#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT)
+#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_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)
+#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
+#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_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)
+#define CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_COUNT)
+#define CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_INTERVAL)
+#define CONFIG_BT_MESH_RELAY_ENABLED MYNEWT_VAL(BLE_MESH_RELAY_ENABLED)
+#define CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_INTERVAL)
+#define CONFIG_BT_MESH_BEACON_ENABLED MYNEWT_VAL(BLE_MESH_BEACON_ENABLED)
+#define CONFIG_BT_MESH_FRIEND_ENABLED MYNEWT_VAL(BLE_MESH_FRIEND_ENABLED)
+#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 printk console_printf
@@ -437,7 +475,7 @@ static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count,
ble_npl_sem_init(sem, initial_count);
}
-static inline int k_sem_take(struct k_sem *sem, s32_t timeout)
+static inline int k_sem_take(struct k_sem *sem, int32_t timeout)
{
uint32_t ticks;
@@ -459,8 +497,8 @@ static inline void k_sem_give(struct k_sem *sem)
static inline int net_buf_id(struct os_mbuf *buf)
{
struct os_mbuf_pool *pool = buf->om_omp;
- u8_t *pool_start = (u8_t *)pool->omp_pool->mp_membuf_addr;
- u8_t *buf_ptr = (u8_t *)buf;
+ uint8_t *pool_start = (uint8_t *)pool->omp_pool->mp_membuf_addr;
+ uint8_t *buf_ptr = (uint8_t *)buf;
return (buf_ptr - pool_start) / BUF_SIZE(pool);
}
@@ -506,6 +544,46 @@ settings_load(void)
#define BUILD_ASSERT(cond) _Static_assert(cond, "")
+
+/* Memory slabs/blocks */
+
+/** Memory slab structure */
+struct k_mem_slab {
+ /**
+ * _wait_q_t is not required now, as we don't implement zephyr timeouts -
+ * if slab couldn't be allocated, we simply return error
+ */
+ uint32_t num_blocks; /** number of memory blocks available for allocation */
+ size_t block_size; /** size of single block */
+ /**
+ * buffer for blocks - must be alligned to N-byte, where N is a power of 2.
+ * Minimal size of buffer is num_blocks * block_size
+ */
+ char *buffer;
+ char *free_list; /** list of free memory blocks */
+ uint32_t num_used; /** count of used memory blocks */
+};
+
+struct k_mem_block_id {
+ uint32_t pool : 8;
+ uint32_t level : 4;
+ uint32_t block : 20;
+};
+
+struct k_mem_block {
+ void *data;
+ struct k_mem_block_id id;
+};
+
+extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem);
+extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem);
+static inline uint32_t k_mem_slab_num_free_get(struct k_mem_slab *slab)
+{
+ return slab->num_blocks - slab->num_used;
+}
+
+int create_free_list(struct k_mem_slab *slab);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_cli.h
index 8ab8d6d5b..e9efe4b1f 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_cli.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_cli.h
@@ -25,12 +25,12 @@ extern "C" {
struct bt_mesh_health_cli {
struct bt_mesh_model *model;
- void (*current_status)(struct bt_mesh_health_cli *cli, u16_t addr,
- u8_t test_id, u16_t cid, u8_t *faults,
+ void (*current_status)(struct bt_mesh_health_cli *cli, uint16_t addr,
+ uint8_t test_id, uint16_t cid, uint8_t *faults,
size_t fault_count);
struct k_sem op_sync;
- u32_t op_pending;
+ uint32_t op_pending;
void *op_param;
};
@@ -43,32 +43,30 @@ extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb;
int bt_mesh_health_cli_set(struct bt_mesh_model *model);
-int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t *test_id, u8_t *faults,
- size_t *fault_count);
+int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults,
+ size_t *fault_count);
-int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t *test_id, u8_t *faults,
- size_t *fault_count);
+int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults,
+ size_t *fault_count);
-int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t test_id, u8_t *faults,
- size_t *fault_count);
+int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t test_id, uint8_t *faults,
+ size_t *fault_count);
-int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *divisor);
+int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor);
-int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t divisor, u8_t *updated_divisor);
+int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
+ uint8_t *updated_divisor);
-int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *attention);
+int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention);
-int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t attention, u8_t *updated_attention);
+int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
+ uint8_t *updated_attention);
-s32_t bt_mesh_health_cli_timeout_get(void);
-void bt_mesh_health_cli_timeout_set(s32_t timeout);
+int32_t bt_mesh_health_cli_timeout_get(void);
+void bt_mesh_health_cli_timeout_set(int32_t timeout);
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_srv.h
index 83982376f..ad79e368d 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_srv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/health_srv.h
@@ -23,21 +23,21 @@ extern "C" {
struct bt_mesh_health_srv_cb {
/* Fetch current faults */
- int (*fault_get_cur)(struct bt_mesh_model *model, u8_t *test_id,
- u16_t *company_id, u8_t *faults,
- u8_t *fault_count);
+ int (*fault_get_cur)(struct bt_mesh_model *model, uint8_t *test_id,
+ uint16_t *company_id, uint8_t *faults,
+ uint8_t *fault_count);
/* Fetch registered faults */
- int (*fault_get_reg)(struct bt_mesh_model *model, u16_t company_id,
- u8_t *test_id, u8_t *faults,
- u8_t *fault_count);
+ int (*fault_get_reg)(struct bt_mesh_model *model, uint16_t company_id,
+ uint8_t *test_id, uint8_t *faults,
+ uint8_t *fault_count);
/* Clear registered faults */
- int (*fault_clear)(struct bt_mesh_model *model, u16_t company_id);
+ int (*fault_clear)(struct bt_mesh_model *model, uint16_t company_id);
/* Run a specific test */
- int (*fault_test)(struct bt_mesh_model *model, u8_t test_id,
- u16_t company_id);
+ int (*fault_test)(struct bt_mesh_model *model, uint8_t test_id,
+ uint16_t company_id);
/* Attention on */
void (*attn_on)(struct bt_mesh_model *model);
@@ -52,7 +52,7 @@ struct bt_mesh_health_srv_cb {
*
* @param max_faults Maximum number of faults the element can have.
*
- * @return a New net_buf_simple of the needed size.
+ * @return a New os_mbuf of the needed size.
*/
#define BT_MESH_HEALTH_FAULT_MSG(max_faults) \
NET_BUF_SIMPLE(1 + 3 + (max_faults))
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/heartbeat.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/heartbeat.h
new file mode 100644
index 000000000..b9990f6fd
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/heartbeat.h
@@ -0,0 +1,123 @@
+/** @file
+ * @brief Bluetooth Mesh Heartbeat API.
+ */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef _BLUETOOTH_MESH_HEARTBEAT_H_
+#define _BLUETOOTH_MESH_HEARTBEAT_H_
+
+/**
+ * @brief Bluetooth Mesh
+ * @defgroup bt_mesh_heartbeat Bluetooth Mesh Heartbeat
+ * @ingroup bt_mesh
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Heartbeat Publication parameters */
+struct bt_mesh_hb_pub {
+ /** Destination address. */
+ uint16_t dst;
+ /** Remaining publish count. */
+ uint16_t count;
+ /** Time To Live value. */
+ uint8_t ttl;
+ /**
+ * Bitmap of features that trigger a Heartbeat publication if
+ * they change. Legal values are @ref BT_MESH_FEAT_RELAY,
+ * @ref BT_MESH_FEAT_PROXY, @ref BT_MESH_FEAT_FRIEND and
+ * @ref BT_MESH_FEAT_LOW_POWER.
+ */
+ uint16_t feat;
+ /** Network index used for publishing. */
+ uint16_t net_idx;
+ /** Publication period in seconds. */
+ uint32_t period;
+};
+
+/** Heartbeat Subscription parameters. */
+struct bt_mesh_hb_sub {
+ /** Subscription period in seconds. */
+ uint32_t period;
+ /** Remaining subscription time in seconds. */
+ uint32_t remaining;
+ /** Source address to receive Heartbeats from. */
+ uint16_t src;
+ /** Destination address to received Heartbeats on. */
+ uint16_t dst;
+ /** The number of received Heartbeat messages so far. */
+ uint16_t count;
+ /**
+ * Minimum hops in received messages, ie the shortest registered
+ * path from the publishing node to the subscribing node. A
+ * Heartbeat received from an immediate neighbor has hop
+ * count = 1.
+ */
+ uint8_t min_hops;
+ /**
+ * Maximum hops in received messages, ie the longest registered
+ * path from the publishing node to the subscribing node. A
+ * Heartbeat received from an immediate neighbor has hop
+ * count = 1.
+ */
+ uint8_t max_hops;
+};
+
+/** Heartbeat callback structure */
+struct bt_mesh_hb_cb {
+ /** @brief Receive callback for heartbeats.
+ *
+ * Gets called on every received Heartbeat that matches the current
+ * Heartbeat subscription parameters.
+ *
+ * @param sub Current Heartbeat subscription parameters.
+ * @param hops The number of hops the Heartbeat was received
+ * with.
+ * @param feat The feature set of the publishing node. The
+ * value is a bitmap of @ref BT_MESH_FEAT_RELAY,
+ * @ref BT_MESH_FEAT_PROXY,
+ * @ref BT_MESH_FEAT_FRIEND and
+ * @ref BT_MESH_FEAT_LOW_POWER.
+ */
+ void (*recv)(const struct bt_mesh_hb_sub *sub, uint8_t hops,
+ uint16_t feat);
+
+ /** @brief Subscription end callback for heartbeats.
+ *
+ * Gets called when the subscription period ends, providing a summary
+ * of the received heartbeat messages.
+ *
+ * @param sub Current Heartbeat subscription parameters.
+ */
+ void (*sub_end)(const struct bt_mesh_hb_sub *sub);
+};
+
+/** @brief Get the current Heartbeat publication parameters.
+ *
+ * @param get Heartbeat publication parameters return buffer.
+ */
+void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get);
+
+/** @brief Get the current Heartbeat subscription parameters.
+ *
+ * @param get Heartbeat subscription parameters return buffer.
+ */
+void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get);
+
+extern struct bt_mesh_hb_cb hb_cb;
+
+#ifdef __cplusplus
+}
+#endif
+/**
+ * @}
+ */
+
+#endif /* _BLUETOOTH_MESH_HEARTBEAT_H_ */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/main.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/main.h
index 4a5bedba1..2bcb05c83 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/main.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/main.h
@@ -59,10 +59,37 @@ typedef enum {
BT_MESH_PROV_OOB_ON_DEV = BIT(15),
} bt_mesh_prov_oob_info_t;
+/** Device Capabilities. */
+struct bt_mesh_dev_capabilities {
+ /** Number of elements supported by the device */
+ uint8_t elem_count;
+
+ /** Supported algorithms and other capabilities */
+ uint16_t algorithms;
+
+ /** Supported public key types */
+ uint8_t pub_key_type;
+
+ /** Supported static OOB Types */
+ uint8_t static_oob;
+
+ /** Supported Output OOB Actions */
+ bt_mesh_output_action_t output_actions;
+
+ /** Supported Input OOB Actions */
+ bt_mesh_input_action_t input_actions;
+
+ /** Maximum size of Output OOB supported */
+ uint8_t output_size;
+
+ /** Maximum size in octets of Input OOB supported */
+ uint8_t input_size;
+};
+
/** Provisioning properties & capabilities. */
struct bt_mesh_prov {
/** The UUID that's used when advertising as unprovisioned */
- const u8_t *uuid;
+ const uint8_t *uuid;
/** Optional URI. This will be advertised separately from the
* unprovisioned beacon, however the unprovisioned beacon will
@@ -75,19 +102,34 @@ struct bt_mesh_prov {
bt_mesh_prov_oob_info_t oob_info;
/** Static OOB value */
- const u8_t *static_val;
+ const uint8_t *static_val;
/** Static OOB value length */
- u8_t static_val_len;
+ uint8_t static_val_len;
/** Maximum size of Output OOB supported */
- u8_t output_size;
+ uint8_t output_size;
/** Supported Output OOB Actions */
- u16_t output_actions;
+ uint16_t output_actions;
/* Maximum size of Input OOB supported */
- u8_t input_size;
+ uint8_t input_size;
/** Supported Input OOB Actions */
- u16_t input_actions;
+ uint16_t input_actions;
+
+ /** @brief Provisioning Capabilities.
+ *
+ * This callback notifies the application that the provisioning capabilities
+ * of the unprovisioned device has been received.
+ *
+ * The application can consequently call bt_mesh_auth_method_set_<*> to
+ * select suitable provisioning oob authentication method.
+ *
+ * When this callback returns, the provisioner will start authentication with
+ * the chosen method.
+ *
+ * @param cap capabilities supported by device.
+ */
+ void (*capabilities)(const struct bt_mesh_dev_capabilities *cap);
/** @brief Output of a number is requested.
*
@@ -99,7 +141,7 @@ struct bt_mesh_prov {
*
* @return Zero on success or negative error code otherwise
*/
- int (*output_number)(bt_mesh_output_action_t act, u32_t num);
+ int (*output_number)(bt_mesh_output_action_t act, uint32_t num);
/** @brief Output of a string is requested.
*
@@ -126,7 +168,7 @@ struct bt_mesh_prov {
*
* @return Zero on success or negative error code otherwise
*/
- int (*input)(bt_mesh_input_action_t act, u8_t size);
+ int (*input)(bt_mesh_input_action_t act, uint8_t size);
/** @brief The other device finished their OOB input.
*
@@ -146,9 +188,9 @@ struct bt_mesh_prov {
* @param uri_hash Pointer to URI Hash value. NULL if no hash was
* present in the beacon.
*/
- void (*unprovisioned_beacon)(u8_t uuid[16],
+ void (*unprovisioned_beacon)(uint8_t uuid[16],
bt_mesh_prov_oob_info_t oob_info,
- u32_t *uri_hash);
+ uint32_t *uri_hash);
/** @brief Provisioning link has been opened.
*
@@ -177,7 +219,7 @@ struct bt_mesh_prov {
* @param net_idx NetKeyIndex given during provisioning.
* @param addr Primary element address.
*/
- void (*complete)(u16_t net_idx, u16_t addr);
+ void (*complete)(uint16_t net_idx, uint16_t addr);
/** @brief A new node has been added to the provisioning database.
*
@@ -186,10 +228,12 @@ struct bt_mesh_prov {
* the specified NetKeyIndex and primary element address.
*
* @param net_idx NetKeyIndex given during provisioning.
+ * @param uuid UUID of the added node
* @param addr Primary element address.
* @param num_elem Number of elements that this node has.
*/
- void (*node_added)(u16_t net_idx, u16_t addr, u8_t num_elem);
+ void (*node_added)(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem);
/** @brief Node has been reset.
*
@@ -222,7 +266,90 @@ int bt_mesh_input_string(const char *str);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_mesh_input_number(u32_t num);
+int bt_mesh_input_number(uint32_t num);
+
+/** @brief Provide Device public key.
+ *
+ * @param public_key Device public key.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]);
+
+/** @brief Use Input OOB authentication.
+ *
+ * Provisioner only.
+ *
+ * Instruct the unprovisioned device to use the specified Input OOB
+ * authentication action. When using @ref BT_MESH_PUSH, @ref BT_MESH_TWIST or
+ * @ref BT_MESH_ENTER_NUMBER, the @ref bt_mesh_prov::output_number callback is
+ * called with a random number that has to be entered on the unprovisioned
+ * device.
+ *
+ * When using @ref BT_MESH_ENTER_STRING, the @ref bt_mesh_prov::output_string
+ * callback is called with a random string that has to be entered on the
+ * unprovisioned device.
+ *
+ * @param action Authentication action used by the unprovisioned device.
+ * @param size Authentication size.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size);
+
+/** @brief Use Output OOB authentication.
+ *
+ * Provisioner only.
+ *
+ * Instruct the unprovisioned device to use the specified Output OOB
+ * authentication action. The @ref bt_mesh_prov::input callback will
+ * be called.
+ *
+ * When using @ref BT_MESH_BLINK, @ref BT_MESH_BEEP, @ref BT_MESH_VIBRATE
+ * or @ref BT_MESH_DISPLAY_NUMBER, and the application has to call
+ * @ref bt_mesh_input_number with the random number indicated by
+ * the unprovisioned device.
+ *
+ * When using @ref BT_MESH_DISPLAY_STRING, the application has to call
+ * @ref bt_mesh_input_string with the random string displayed by the
+ * unprovisioned device.
+ *
+ * @param action Authentication action used by the unprovisioned device.
+ * @param size Authentication size.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size);
+
+/** @brief Use static OOB authentication.
+ *
+ * Provisioner only.
+ *
+ * Instruct the unprovisioned device to use static OOB authentication, and use
+ * the given static authentication value when provisioning.
+ *
+ * @param static_val Static OOB value.
+ * @param size Static OOB value size.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size);
+
+/** @brief Don't use OOB authentication.
+ *
+ * Provisioner only.
+ *
+ * Don't use any authentication when provisioning new devices. This is the
+ * default behavior.
+ *
+ * @warning Not using any authentication exposes the mesh network to
+ * impersonation attacks, where attackers can pretend to be the
+ * unprovisioned device to gain access to the network. Authentication
+ * is strongly encouraged.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_auth_method_set_none(void);
/** @brief Enable specific provisioning bearers
*
@@ -258,25 +385,6 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
/* Primary Network Key index */
#define BT_MESH_NET_PRIMARY 0x000
-#define BT_MESH_RELAY_DISABLED 0x00
-#define BT_MESH_RELAY_ENABLED 0x01
-#define BT_MESH_RELAY_NOT_SUPPORTED 0x02
-
-#define BT_MESH_BEACON_DISABLED 0x00
-#define BT_MESH_BEACON_ENABLED 0x01
-
-#define BT_MESH_GATT_PROXY_DISABLED 0x00
-#define BT_MESH_GATT_PROXY_ENABLED 0x01
-#define BT_MESH_GATT_PROXY_NOT_SUPPORTED 0x02
-
-#define BT_MESH_FRIEND_DISABLED 0x00
-#define BT_MESH_FRIEND_ENABLED 0x01
-#define BT_MESH_FRIEND_NOT_SUPPORTED 0x02
-
-#define BT_MESH_NODE_IDENTITY_STOPPED 0x00
-#define BT_MESH_NODE_IDENTITY_RUNNING 0x01
-#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED 0x02
-
/* Features */
#define BT_MESH_FEAT_RELAY BIT(0)
#define BT_MESH_FEAT_PROXY BIT(1)
@@ -299,7 +407,7 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_mesh_init(u8_t own_addr_type,
+int bt_mesh_init(uint8_t own_addr_type,
const struct bt_mesh_prov *prov,
const struct bt_mesh_comp *comp);
@@ -351,9 +459,9 @@ int bt_mesh_resume(void);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
- u8_t flags, u32_t iv_index, u16_t addr,
- const u8_t dev_key[16]);
+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]);
/** @brief Provision a Mesh Node using PB-ADV
*
@@ -365,8 +473,8 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration);
+int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration);
/** @brief Check if the local node has been provisioned.
*
@@ -428,7 +536,17 @@ int bt_mesh_lpn_poll(void);
*
* @param cb Function to call when the Friendship status changes.
*/
-void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established));
+void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established));
+
+/** @brief Terminate Friendship.
+ *
+ * Terminated Friendship for given LPN.
+ *
+ * @param lpn_addr Low Power Node address.
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_friend_terminate(uint16_t lpn_addr);
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h
index 77b2871fc..4fce128b4 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/mesh.h
@@ -17,10 +17,15 @@
#include "glue.h"
#include "access.h"
#include "main.h"
+#include "cfg.h"
#include "cfg_srv.h"
#include "health_srv.h"
#include "cfg_cli.h"
#include "health_cli.h"
#include "proxy.h"
+#include "cdb.h"
+#include "cfg.h"
+#include "heartbeat.h"
+#include "../../src/app_keys.h"
#endif /* __BT_MESH_H */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_cli.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_cli.h
index f2e77a47f..87e2dd2be 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_cli.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_cli.h
@@ -15,7 +15,7 @@ struct bt_mesh_gen_model_cli {
struct bt_mesh_model *model;
struct k_sem op_sync;
- u32_t op_pending;
+ uint32_t op_pending;
void *op_param;
};
@@ -33,14 +33,14 @@ extern const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb;
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_LEVEL_CLI, gen_level_cli_op, pub,\
cli_data, &bt_mesh_gen_level_cli_cb)
-int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *state);
-int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t val, u8_t *state);
-int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- s16_t *level);
-int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- s16_t val, s16_t *state);
+int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t *state);
+int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t val, uint8_t *state);
+int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t *level);
+int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t val, int16_t *state);
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_srv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_srv.h
index e498ad346..a23296b83 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_srv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/model_srv.h
@@ -14,8 +14,8 @@ extern "C" {
struct bt_mesh_gen_onoff_srv {
struct bt_mesh_model *model;
- int (*get)(struct bt_mesh_model *model, u8_t *state);
- int (*set)(struct bt_mesh_model *model, u8_t state);
+ int (*get)(struct bt_mesh_model *model, uint8_t *state);
+ int (*set)(struct bt_mesh_model *model, uint8_t state);
};
extern const struct bt_mesh_model_op gen_onoff_srv_op[];
@@ -28,8 +28,8 @@ extern const struct bt_mesh_model_cb gen_onoff_srv_cb;
struct bt_mesh_gen_level_srv {
struct bt_mesh_model *model;
- int (*get)(struct bt_mesh_model *model, s16_t *level);
- int (*set)(struct bt_mesh_model *model, s16_t level);
+ int (*get)(struct bt_mesh_model *model, int16_t *level);
+ int (*set)(struct bt_mesh_model *model, int16_t level);
};
extern const struct bt_mesh_model_op gen_level_srv_op[];
@@ -42,8 +42,8 @@ extern const struct bt_mesh_model_cb gen_level_srv_cb;
struct bt_mesh_light_lightness_srv {
struct bt_mesh_model *model;
- int (*get)(struct bt_mesh_model *model, s16_t *level);
- int (*set)(struct bt_mesh_model *model, s16_t level);
+ int (*get)(struct bt_mesh_model *model, int16_t *level);
+ int (*set)(struct bt_mesh_model *model, int16_t level);
};
extern const struct bt_mesh_model_op light_lightness_srv_op[];
@@ -53,12 +53,12 @@ extern const struct bt_mesh_model_cb light_lightness_srv_cb;
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, \
light_lightness_srv_op, pub, srv, &light_lightness_srv_cb)
-void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
- int (*set)(struct bt_mesh_model *model, u8_t state));
-void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
- int (*set)(struct bt_mesh_model *model, s16_t level));
-void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
- int (*set)(struct bt_mesh_model *model, s16_t level));
+void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state),
+ int (*set)(struct bt_mesh_model *model, uint8_t state));
+void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level));
+void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level));
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/testing.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/testing.h
index 4c2b2a619..580aafe41 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/testing.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/include/mesh/testing.h
@@ -33,13 +33,13 @@ extern "C" {
* Allows access to Bluetooth stack internals, not exposed by public API.
*/
struct bt_test_cb {
- void (*mesh_net_recv)(u8_t ttl, u8_t ctl, u16_t src, u16_t dst,
+ void (*mesh_net_recv)(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
const void *payload, size_t payload_len);
- void (*mesh_model_bound)(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx);
- void (*mesh_model_unbound)(u16_t addr, struct bt_mesh_model *model,
- u16_t key_idx);
- void (*mesh_prov_invalid_bearer)(u8_t opcode);
+ void (*mesh_model_bound)(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx);
+ void (*mesh_model_unbound)(uint16_t addr, struct bt_mesh_model *model,
+ uint16_t key_idx);
+ void (*mesh_prov_invalid_bearer)(uint8_t opcode);
void (*mesh_trans_incomp_timer_exp)(void);
sys_snode_t node;
@@ -66,7 +66,7 @@ void bt_test_cb_unregister(struct bt_test_cb *cb);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_test_mesh_lpn_group_add(u16_t group);
+int bt_test_mesh_lpn_group_add(uint16_t group);
/** Send Friend Subscription List Remove message.
*
@@ -79,7 +79,7 @@ int bt_test_mesh_lpn_group_add(u16_t group);
*
* @return Zero on success or (negative) error code otherwise.
*/
-int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count);
+int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count);
/** Clear replay protection list cache.
*
@@ -87,12 +87,12 @@ int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count);
*/
int bt_test_mesh_rpl_clear(void);
-u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx);
-u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store);
+uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx);
+uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store);
int cmd_mesh_init(int argc, char *argv[]);
int bt_test_shell_init(void);
-int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, u16_t key_idx, u16_t id);
+int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, uint16_t key_idx, uint16_t id);
/**
* @}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c
index 37580b400..306ff8c2f 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.c
@@ -28,7 +28,7 @@
#endif
static const struct bt_mesh_comp *dev_comp;
-static u16_t dev_primary_addr;
+static uint16_t dev_primary_addr;
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
struct bt_mesh_elem *elem,
@@ -55,7 +55,7 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
}
}
-s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
+int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
{
int period;
@@ -91,10 +91,10 @@ s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod)
}
}
-static s32_t next_period(struct bt_mesh_model *mod)
+static int32_t next_period(struct bt_mesh_model *mod)
{
struct bt_mesh_model_pub *pub = mod->pub;
- u32_t elapsed, period;
+ uint32_t elapsed, period;
period = bt_mesh_model_pub_period_get(mod);
if (!period) {
@@ -117,7 +117,7 @@ static s32_t next_period(struct bt_mesh_model *mod)
static void publish_sent(int err, void *user_data)
{
struct bt_mesh_model *mod = user_data;
- s32_t delay;
+ int32_t delay;
BT_DBG("err %d", err);
@@ -133,7 +133,7 @@ static void publish_sent(int err, void *user_data)
}
}
-static void publish_start(u16_t duration, int err, void *user_data)
+static void publish_start(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_model *mod = user_data;
struct bt_mesh_model_pub *pub = mod->pub;
@@ -158,30 +158,18 @@ static int publish_retransmit(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;
- struct bt_mesh_app_key *key;
struct bt_mesh_msg_ctx ctx = {
.addr = pub->addr,
.send_ttl = pub->ttl,
+ .app_idx = pub->key,
};
struct bt_mesh_net_tx tx = {
.ctx = &ctx,
.src = bt_mesh_model_elem(mod)->addr,
- .xmit = bt_mesh_net_transmit_get(),
.friend_cred = pub->cred,
};
int err;
- key = bt_mesh_app_key_find(pub->key);
- if (!key) {
- err = -EADDRNOTAVAIL;
- goto done;
- }
-
- tx.sub = bt_mesh_subnet_get(key->net_idx);
-
- ctx.net_idx = key->net_idx;
- ctx.app_idx = key->app_idx;
-
net_buf_simple_init(sdu, 0);
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
@@ -189,15 +177,22 @@ static int publish_retransmit(struct bt_mesh_model *mod)
err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod);
-done:
os_mbuf_free_chain(sdu);
return err;
}
+static void publish_retransmit_end(int err, 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);
+}
+
static void mod_publish(struct ble_npl_event *work)
{
struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work);
- s32_t period_ms;
+ int32_t period_ms;
int err;
BT_DBG("");
@@ -229,7 +224,10 @@ static void mod_publish(struct ble_npl_event *work)
err = pub->update(pub->mod);
if (err) {
- BT_ERR("Failed to update publication message");
+ /* 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;
}
@@ -244,7 +242,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod)
return &dev_comp->elem[mod->elem_idx];
}
-struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx)
+struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx)
{
struct bt_mesh_elem *elem;
@@ -276,6 +274,11 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
int i;
+ int *err = user_data;
+
+ if (*err) {
+ return;
+ }
if (mod->pub) {
mod->pub->mod = mod;
@@ -295,12 +298,14 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
}
if (mod->cb && mod->cb->init) {
- mod->cb->init(mod);
+ *err = mod->cb->init(mod);
}
}
int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
{
+ int err;
+
/* There must be at least one element */
if (!comp->elem_count) {
return -EINVAL;
@@ -308,12 +313,13 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp)
dev_comp = comp;
- bt_mesh_model_foreach(mod_init, NULL);
+ err = 0;
+ bt_mesh_model_foreach(mod_init, &err);
- return 0;
+ return err;
}
-void bt_mesh_comp_provision(u16_t addr)
+void bt_mesh_comp_provision(uint16_t addr)
{
int i;
@@ -336,16 +342,14 @@ void bt_mesh_comp_unprovision(void)
BT_DBG("");
dev_primary_addr = BT_MESH_ADDR_UNASSIGNED;
-
- bt_mesh_model_foreach(mod_init, NULL);
}
-u16_t bt_mesh_primary_addr(void)
+uint16_t bt_mesh_primary_addr(void)
{
return dev_primary_addr;
}
-static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
+static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr)
{
int i;
@@ -359,13 +363,13 @@ static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr)
}
struct find_group_visitor_ctx {
- u16_t *entry;
+ uint16_t *entry;
struct bt_mesh_model *mod;
- u16_t addr;
+ uint16_t addr;
};
static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *user_data)
+ uint32_t depth, void *user_data)
{
struct find_group_visitor_ctx *ctx = user_data;
@@ -382,7 +386,7 @@ static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod,
return BT_MESH_WALK_CONTINUE;
}
-u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
+uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr)
{
struct find_group_visitor_ctx ctx = {
.mod = *mod,
@@ -398,10 +402,10 @@ u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr)
}
static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
- u16_t group_addr)
+ uint16_t group_addr)
{
struct bt_mesh_model *model;
- u16_t *match;
+ uint16_t *match;
int i;
for (i = 0; i < elem->model_count; i++) {
@@ -425,9 +429,9 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem,
return NULL;
}
-struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
+struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr)
{
- u16_t index;
+ uint16_t index;
if (BT_MESH_ADDR_IS_UNICAST(addr)) {
index = (addr - dev_comp->elem[0].addr);
@@ -449,12 +453,12 @@ struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr)
return NULL;
}
-u8_t bt_mesh_elem_count(void)
+uint8_t bt_mesh_elem_count(void)
{
return dev_comp->elem_count;
}
-static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
+static bool model_has_key(struct bt_mesh_model *mod, uint16_t key)
{
int i;
@@ -469,22 +473,26 @@ static bool model_has_key(struct bt_mesh_model *mod, u16_t key)
return false;
}
-static bool model_has_dst(struct bt_mesh_model *mod, u16_t dst)
+static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst)
{
if (BT_MESH_ADDR_IS_UNICAST(dst)) {
return (dev_comp->elem[mod->elem_idx].addr == dst);
} else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst)) {
- return bt_mesh_model_find_group(&mod, dst);
+ return !!bt_mesh_model_find_group(&mod, dst);
}
- return (mod->elem_idx == 0 && bt_mesh_fixed_group_match(dst));
+ /* If a message with a fixed group address is sent to the access layer,
+ * the lower layers have already confirmed that we are subscribing to
+ * it. All models on the primary element should receive the message.
+ */
+ return mod->elem_idx == 0;
}
static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
- u8_t model_count, u32_t opcode,
+ uint8_t model_count, uint32_t opcode,
struct bt_mesh_model **model)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < model_count; i++) {
const struct bt_mesh_model_op *op;
@@ -502,7 +510,7 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models,
return NULL;
}
-static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
+static int get_opcode(struct os_mbuf *buf, uint32_t *opcode)
{
switch (buf->om_data[0] >> 6) {
case 0x00:
@@ -529,6 +537,10 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
}
*opcode = net_buf_simple_pull_u8(buf) << 16;
+ /* 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.
+ */
*opcode |= net_buf_simple_pull_le16(buf);
return 0;
}
@@ -536,29 +548,12 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode)
CODE_UNREACHABLE;
}
-bool bt_mesh_fixed_group_match(u16_t addr)
-{
- /* Check for fixed group addresses */
- switch (addr) {
- case BT_MESH_ADDR_ALL_NODES:
- return true;
- case BT_MESH_ADDR_PROXIES:
- return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
- case BT_MESH_ADDR_FRIENDS:
- return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED);
- case BT_MESH_ADDR_RELAYS:
- return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
- default:
- return false;
- }
-}
-
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_model *models, *model;
const struct bt_mesh_model_op *op;
- u32_t opcode;
- u8_t count;
+ uint32_t opcode;
+ uint8_t count;
int i;
BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
@@ -617,7 +612,7 @@ 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, u32_t opcode)
+void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode)
{
net_buf_simple_init(msg, 0);
@@ -630,6 +625,10 @@ void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t 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:
@@ -676,11 +675,8 @@ int bt_mesh_model_send(struct bt_mesh_model *model,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
struct bt_mesh_net_tx tx = {
- .sub = bt_mesh_subnet_get(ctx->net_idx),
.ctx = ctx,
.src = bt_mesh_model_elem(model)->addr,
- .xmit = bt_mesh_net_transmit_get(),
- .friend_cred = 0,
};
return model_send(model, &tx, false, msg, cb, cb_data);
@@ -690,13 +686,15 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_model_pub *pub = model->pub;
- struct bt_mesh_app_key *key;
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,
- .xmit = bt_mesh_net_transmit_get(),
};
int err;
@@ -712,12 +710,6 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
goto done;
}
- key = bt_mesh_app_key_find(pub->key);
- if (!key) {
- err = -EADDRNOTAVAIL;
- goto done;
- }
-
if (pub->msg->om_len + 4 > BT_MESH_TX_SDU_MAX) {
BT_ERR("Message does not fit maximum SDU size");
err = -EMSGSIZE;
@@ -732,13 +724,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
net_buf_simple_init(sdu, 0);
net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len);
- ctx.addr = pub->addr;
- ctx.send_ttl = pub->ttl;
- ctx.net_idx = key->net_idx;
- ctx.app_idx = key->app_idx;
-
tx.friend_cred = pub->cred;
- tx.sub = bt_mesh_subnet_get(ctx.net_idx),
pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit);
@@ -747,10 +733,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
if (err) {
- /* Don't try retransmissions for this publish attempt */
- pub->count = 0;
- /* Make sure the publish timer gets reset */
- publish_sent(err, model);
+ publish_retransmit_end(err, pub);
}
done:
@@ -759,9 +742,9 @@ done:
}
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
- u16_t company, u16_t id)
+ uint16_t company, uint16_t id)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < elem->vnd_model_count; i++) {
if (elem->vnd_models[i].vnd.company == company &&
@@ -774,9 +757,9 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
}
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
- u16_t id)
+ uint16_t id)
{
- u8_t i;
+ uint8_t i;
for (i = 0; i < elem->model_count; i++) {
if (elem->models[i].id == id) {
@@ -804,29 +787,38 @@ 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,
- u32_t depth,
+ uint32_t depth,
void *user_data),
void *user_data)
{
struct bt_mesh_model *m = root;
- u32_t depth = 0;
+ 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 (cb(m, depth, user_data) == BT_MESH_WALK_STOP) {
+ if (!skip &&
+ cb(m, (uint32_t)depth, user_data) == BT_MESH_WALK_STOP) {
return;
}
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
- if (m->extends) {
+ if (!skip && m->extends) {
m = m->extends;
depth++;
} else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) {
- m = m->next->next;
+ m = m->next;
depth--;
+ skip = true;
} else {
m = m->next;
+ skip = false;
}
#endif
- } while (m && m != root);
+ } while (m && depth > 0);
}
#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h
index 03081b9ad..6d2e31e88 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/access.h
@@ -16,8 +16,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_DATA_PRESENT = BIT(3),
- BT_MESH_MOD_NEXT_IS_PARENT = BIT(4),
+ BT_MESH_MOD_NEXT_IS_PARENT = BIT(3),
};
/* Tree walk return codes */
@@ -26,23 +25,21 @@ enum bt_mesh_walk {
BT_MESH_WALK_CONTINUE,
};
-void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count);
+void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count);
-u8_t bt_mesh_elem_count(void);
+uint8_t bt_mesh_elem_count(void);
/* Find local element based on unicast or group address */
-struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr);
+struct bt_mesh_elem *bt_mesh_elem_find(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,
- u32_t depth,
+ uint32_t depth,
void *user_data),
void *user_data);
-u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr);
-
-bool bt_mesh_fixed_group_match(u16_t addr);
+uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr);
void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
struct bt_mesh_elem *elem,
@@ -50,16 +47,16 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod,
void *user_data),
void *user_data);
-s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
+int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod);
-void bt_mesh_comp_provision(u16_t addr);
+void bt_mesh_comp_provision(uint16_t addr);
void bt_mesh_comp_unprovision(void);
-u16_t bt_mesh_primary_addr(void);
+uint16_t bt_mesh_primary_addr(void);
const struct bt_mesh_comp *bt_mesh_comp_get(void);
-struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx);
+struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx);
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c
index b9d290176..95960ddb2 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.c
@@ -40,21 +40,20 @@
#define ADV_INT_DEFAULT_MS 100
#define ADV_INT_FAST_MS 20
-static s32_t adv_int_min = ADV_INT_DEFAULT_MS;
+static int32_t adv_int_min = ADV_INT_DEFAULT_MS;
/* TinyCrypt PRNG consumes a lot of stack space, so we need to have
* an increased call stack whenever it's used.
*/
#if MYNEWT
-#define ADV_STACK_SIZE 768
-OS_TASK_STACK_DEFINE(g_blemesh_stack, ADV_STACK_SIZE);
+OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE));
struct os_task adv_task;
#else
static TaskHandle_t adv_task_h;
#endif
static struct ble_npl_eventq adv_queue;
-extern u8_t g_mesh_addr_type;
+extern uint8_t g_mesh_addr_type;
static int adv_initialized = false;
static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE(
@@ -64,14 +63,6 @@ static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE(
struct os_mbuf_pool adv_os_mbuf_pool;
static struct os_mempool adv_buf_mempool;
-static const u8_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,
-};
-
-
static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT];
static struct bt_mesh_adv *adv_alloc(int id)
@@ -79,7 +70,7 @@ static struct bt_mesh_adv *adv_alloc(int id)
return &adv_pool[id];
}
-static inline void adv_send_start(u16_t duration, int err,
+static inline void adv_send_start(uint16_t duration, int err,
const struct bt_mesh_send_cb *cb,
void *cb_data)
{
@@ -98,10 +89,17 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb,
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 };
- u16_t duration, adv_int;
+ uint16_t duration, adv_int;
struct bt_data ad;
int err;
@@ -158,7 +156,7 @@ mesh_adv_thread(void *args)
static struct ble_npl_event *ev;
struct os_mbuf *buf;
#if (MYNEWT_VAL(BLE_MESH_PROXY))
- s32_t timeout;
+ int32_t timeout;
#endif
BT_DBG("started");
@@ -212,7 +210,7 @@ void bt_mesh_adv_update(void)
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,
- u8_t xmit, s32_t timeout)
+ uint8_t xmit, int32_t timeout)
{
struct bt_mesh_adv *adv;
struct os_mbuf *buf;
@@ -241,8 +239,8 @@ struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool,
return buf;
}
-struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
- s32_t timeout)
+struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
+ int32_t timeout)
{
return bt_mesh_adv_create_from_pool(&adv_os_mbuf_pool, adv_alloc, type,
xmit, timeout);
@@ -261,8 +259,8 @@ void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb,
net_buf_put(&adv_queue, net_buf_ref(buf));
}
-static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
- u8_t adv_type, struct os_mbuf *buf)
+static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi,
+ uint8_t adv_type, struct os_mbuf *buf)
{
if (adv_type != BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
return;
@@ -274,7 +272,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
while (buf->om_len > 1) {
struct net_buf_simple_state state;
- u8_t len, type;
+ uint8_t len, type;
len = net_buf_simple_pull_u8(buf);
/* Check for early termination */
@@ -308,7 +306,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi,
}
net_buf_simple_restore(buf, &state);
- net_buf_simple_pull(buf, len);
+ net_buf_simple_pull_mem(buf, len);
}
}
@@ -337,7 +335,7 @@ void bt_mesh_adv_init(void)
#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, ADV_STACK_SIZE);
+ g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE));
#elif ESP_PLATFORM
xTaskCreatePinnedToCore(mesh_adv_thread, "mesh_adv", 2768,
NULL, (configMAX_PRIORITIES - 5), &adv_task_h, NIMBLE_CORE);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h
index 40e65e5f4..fe74438c3 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/adv.h
@@ -31,23 +31,18 @@ enum bt_mesh_adv_type
BT_MESH_ADV_URI,
};
-typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, u16_t duration,
+typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration,
int err, void *user_data);
struct bt_mesh_adv {
const struct bt_mesh_send_cb *cb;
void *cb_data;
- u8_t type:2,
+ uint8_t type:2,
busy:1;
- u8_t xmit;
+ uint8_t xmit;
- /* For transport layer segment sending */
- struct {
- u8_t attempts;
- } seg;
-
- u8_t flags;
+ uint8_t flags;
int ref_cnt;
struct ble_npl_event ev;
@@ -56,13 +51,13 @@ struct bt_mesh_adv {
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
/* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */
-struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit,
- s32_t timeout);
+struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit,
+ int32_t timeout);
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,
- u8_t xmit, s32_t timeout);
+ uint8_t xmit, int32_t timeout);
void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb,
void *cb_data);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/aes-ccm.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/aes-ccm.c
new file mode 100644
index 000000000..2bc7e1ac7
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/aes-ccm.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_MESH)
+
+#include "crypto.h"
+#define MESH_LOG_MODULE BLE_MESH_LOG
+
+static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
+{
+ dst[0] = a[0] ^ b[0];
+ dst[1] = a[1] ^ b[1];
+ dst[2] = a[2] ^ b[2];
+ dst[3] = a[3] ^ b[3];
+ dst[4] = a[4] ^ b[4];
+ dst[5] = a[5] ^ b[5];
+ dst[6] = a[6] ^ b[6];
+ dst[7] = a[7] ^ b[7];
+ dst[8] = a[8] ^ b[8];
+ dst[9] = a[9] ^ b[9];
+ dst[10] = a[10] ^ b[10];
+ dst[11] = a[11] ^ b[11];
+ dst[12] = a[12] ^ b[12];
+ dst[13] = a[13] ^ b[13];
+ dst[14] = a[14] ^ b[14];
+ dst[15] = a[15] ^ b[15];
+}
+
+/* pmsg is assumed to have the nonce already present in bytes 1-13 */
+static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
+ size_t mic_size, uint8_t msg_len, uint8_t b[16],
+ uint8_t X0[16])
+{
+ int i, j, err;
+
+ /* X_0 = e(AppKey, flags || nonce || length) */
+ b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;
+
+ sys_put_be16(msg_len, b + 14);
+
+ err = bt_encrypt_be(key, b, X0);
+ if (err) {
+ return err;
+ }
+
+ /* If AAD is being used to authenticate, include it here */
+ if (aad_len) {
+ sys_put_be16(aad_len, b);
+
+ for (i = 0; i < sizeof(uint16_t); i++) {
+ b[i] = X0[i] ^ b[i];
+ }
+
+ j = 0;
+ aad_len += sizeof(uint16_t);
+ while (aad_len > 16) {
+ do {
+ b[i] = X0[i] ^ aad[j];
+ i++, j++;
+ } while (i < 16);
+
+ aad_len -= 16;
+ i = 0;
+
+ err = bt_encrypt_be(key, b, X0);
+ if (err) {
+ return err;
+ }
+ }
+
+ for (; i < aad_len; i++, j++) {
+ b[i] = X0[i] ^ aad[j];
+ }
+
+ for (i = aad_len; i < 16; i++) {
+ b[i] = X0[i];
+ }
+
+ err = bt_encrypt_be(key, b, X0);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int ccm_auth(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t *cleartext_msg, size_t msg_len, const uint8_t *aad,
+ size_t aad_len, uint8_t *mic, size_t mic_size)
+{
+ uint8_t b[16], Xn[16], s0[16];
+ uint16_t blk_cnt, last_blk;
+ int err, j, i;
+
+ last_blk = msg_len % 16;
+ blk_cnt = (msg_len + 15) / 16;
+ if (!last_blk) {
+ last_blk = 16U;
+ }
+
+ b[0] = 0x01;
+ memcpy(b + 1, nonce, 13);
+
+ /* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
+ sys_put_be16(0x0000, &b[14]);
+
+ err = bt_encrypt_be(key, b, s0);
+ if (err) {
+ return err;
+ }
+
+ ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);
+
+ for (j = 0; j < blk_cnt; j++) {
+ /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
+ if (j + 1 == blk_cnt) {
+ for (i = 0; i < last_blk; i++) {
+ b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
+ }
+
+ memcpy(&b[i], &Xn[i], 16 - i);
+ } else {
+ xor16(b, Xn, &cleartext_msg[j * 16]);
+ }
+
+ err = bt_encrypt_be(key, b, Xn);
+ if (err) {
+ return err;
+ }
+ }
+
+ /* MIC = C_mic ^ X_1 */
+ for (i = 0; i < mic_size; i++) {
+ mic[i] = s0[i] ^ Xn[i];
+ }
+
+ return 0;
+}
+
+static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
+ const uint8_t *in_msg, uint8_t *out_msg, size_t msg_len)
+{
+ uint8_t a_i[16], s_i[16];
+ uint16_t last_blk, blk_cnt;
+ size_t i, j;
+ int err;
+
+ last_blk = msg_len % 16;
+ blk_cnt = (msg_len + 15) / 16;
+ if (!last_blk) {
+ last_blk = 16U;
+ }
+
+ a_i[0] = 0x01;
+ memcpy(&a_i[1], nonce, 13);
+
+ for (j = 0; j < blk_cnt; j++) {
+ /* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
+ sys_put_be16(j + 1, &a_i[14]);
+
+ err = bt_encrypt_be(key, a_i, s_i);
+ if (err) {
+ return err;
+ }
+
+ /* Encrypted = Payload[0-15] ^ C_1 */
+ if (j < blk_cnt - 1) {
+ xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
+ } else {
+ for (i = 0; i < last_blk; i++) {
+ out_msg[(j * 16) + i] =
+ in_msg[(j * 16) + i] ^ s_i[i];
+ }
+ }
+ }
+ return 0;
+}
+
+int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_msg,
+ size_t msg_len, const uint8_t *aad, size_t aad_len,
+ uint8_t *out_msg, size_t mic_size)
+{
+ uint8_t mic[16];
+
+ if (aad_len >= 0xff00 || mic_size > sizeof(mic)) {
+ return -EINVAL;
+ }
+
+ ccm_crypt(key, nonce, enc_msg, out_msg, msg_len);
+
+ ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
+
+ if (memcmp(mic, enc_msg + msg_len, mic_size)) {
+ return -EBADMSG;
+ }
+
+ return 0;
+}
+
+int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *msg,
+ size_t msg_len, const uint8_t *aad, size_t aad_len,
+ uint8_t *out_msg, size_t mic_size)
+{
+ uint8_t *mic = out_msg + msg_len;
+
+ BT_DBG("key %s", bt_hex(key, 16));
+ BT_DBG("nonce %s", bt_hex(nonce, 13));
+ BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
+ BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
+
+ /* Unsupported AAD size */
+ if (aad_len >= 0xff00 || mic_size > 16) {
+ return -EINVAL;
+ }
+
+ ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size);
+
+ ccm_crypt(key, nonce, msg, out_msg, msg_len);
+
+ return 0;
+}
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/app_keys.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/app_keys.c
new file mode 100644
index 000000000..e64b9be98
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/app_keys.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_MESH)
+
+#include
+#include
+#include "../include/mesh/mesh.h"
+#include "mesh_priv.h"
+#include "net.h"
+#include "app_keys.h"
+#include "rpl.h"
+#include "settings.h"
+#include "crypto.h"
+#include "adv.h"
+#include "proxy.h"
+#include "friend.h"
+#include "foundation.h"
+#include "access.h"
+#include "subnet.h"
+
+#define MESH_LOG_MODULE BLE_MESH_LOG
+#include "nimble/porting/nimble/include/log/log.h"
+
+static struct bt_mesh_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)
+{
+ 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);
+ }
+ }
+}
+
+struct bt_mesh_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 struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx)
+{
+ struct bt_mesh_app_key *app = NULL;
+
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ /* Check for already existing app_key */
+ if (apps[i].app_idx == app_idx) {
+ return &apps[i];
+ }
+
+ if (!app && apps[i].app_idx == BT_MESH_KEY_UNUSED) {
+ app = &apps[i];
+ }
+ }
+
+ return app;
+}
+
+static void app_key_del(struct bt_mesh_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);
+ }
+
+ app_key_evt(app, BT_MESH_KEY_DELETED);
+
+ app->net_idx = BT_MESH_KEY_UNUSED;
+ app->app_idx = BT_MESH_KEY_UNUSED;
+ (void)memset(app->keys, 0, sizeof(app->keys));
+}
+
+static void app_key_revoke(struct bt_mesh_app_key *app)
+{
+ if (!app->updated) {
+ return;
+ }
+
+ memcpy(&app->keys[0], &app->keys[1], sizeof(app->keys[0]));
+ memset(&app->keys[1], 0, sizeof(app->keys[1]));
+ app->updated = false;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_app_key(app->app_idx);
+ }
+
+ app_key_evt(app, BT_MESH_KEY_REVOKED);
+}
+
+
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ if (evt == BT_MESH_KEY_UPDATED || evt == BT_MESH_KEY_ADDED) {
+ return;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ struct bt_mesh_app_key *app = &apps[i];
+
+ if (app->app_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (app->net_idx != sub->net_idx) {
+ continue;
+ }
+
+ if (evt == BT_MESH_KEY_DELETED) {
+ app_key_del(app);
+ } else if (evt == BT_MESH_KEY_REVOKED) {
+ app_key_revoke(app);
+ } else if (evt == BT_MESH_KEY_SWAPPED && app->updated) {
+ app_key_evt(app, BT_MESH_KEY_SWAPPED);
+ }
+ }
+}
+
+
+uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
+ const uint8_t key[16])
+{
+ if (!bt_mesh_subnet_cb_list[0]) {
+ bt_mesh_subnet_cb_list[0] = subnet_evt;
+ }
+
+ struct bt_mesh_app_key *app;
+
+ BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
+ bt_hex(key, 16));
+
+ if (!bt_mesh_subnet_get(net_idx)) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ app = app_key_alloc(app_idx);
+ if (!app) {
+ return STATUS_INSUFF_RESOURCES;
+ }
+
+ if (app->app_idx == app_idx) {
+ if (app->net_idx != net_idx) {
+ return STATUS_INVALID_BINDING;
+ }
+
+ if (memcmp(key, app->keys[0].val, 16)) {
+ return STATUS_IDX_ALREADY_STORED;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ if (bt_mesh_app_id(key, &app->keys[0].id)) {
+ return STATUS_CANNOT_SET;
+ }
+
+ BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
+
+ app->net_idx = net_idx;
+ app->app_idx = app_idx;
+ app->updated = false;
+ memcpy(app->keys[0].val, key, 16);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing AppKey persistently");
+ bt_mesh_store_app_key(app->app_idx);
+ }
+
+ app_key_evt(app, BT_MESH_KEY_ADDED);
+
+ 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 bt_mesh_subnet *sub;
+
+ BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx,
+ bt_hex(key, 16));
+
+ app = app_get(app_idx);
+ if (!app) {
+ return STATUS_INVALID_APPKEY;
+ }
+
+ if (net_idx != BT_MESH_KEY_UNUSED && app->net_idx != net_idx) {
+ return STATUS_INVALID_BINDING;
+ }
+
+ sub = bt_mesh_subnet_get(app->net_idx);
+ if (!sub) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ /* The AppKey Update message shall generate an error when node
+ * is in normal operation, Phase 2, or Phase 3 or in Phase 1
+ * when the AppKey Update message on a valid AppKeyIndex when
+ * the AppKey value is different.
+ */
+ if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
+ return STATUS_CANNOT_UPDATE;
+ }
+
+ if (app->updated) {
+ if (memcmp(app->keys[1].val, key, 16)) {
+ return STATUS_IDX_ALREADY_STORED;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ if (bt_mesh_app_id(key, &app->keys[1].id)) {
+ return STATUS_CANNOT_UPDATE;
+ }
+
+ BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, app->keys[1].id);
+
+ app->updated = true;
+ memcpy(app->keys[1].val, key, 16);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing AppKey persistently");
+ bt_mesh_store_app_key(app->app_idx);
+ }
+
+ app_key_evt(app, BT_MESH_KEY_UPDATED);
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx)
+{
+ struct bt_mesh_app_key *app;
+
+ BT_DBG("AppIdx 0x%03x", app_idx);
+
+ if (net_idx != BT_MESH_KEY_UNUSED && !bt_mesh_subnet_get(net_idx)) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ app = app_get(app_idx);
+ if (!app) {
+ /* This could be a retry of a previous attempt that had its
+ * response lost, so pretend that it was a success.
+ */
+ return STATUS_SUCCESS;
+ }
+
+ if (net_idx != BT_MESH_KEY_UNUSED && net_idx != app->net_idx) {
+ return STATUS_INVALID_BINDING;
+ }
+
+ app_key_del(app);
+
+ return STATUS_SUCCESS;
+}
+
+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;
+
+ app = app_key_alloc(app_idx);
+ if (!app) {
+ return -ENOMEM;
+ }
+
+ if (app->app_idx == app_idx) {
+ return 0;
+ }
+
+ BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id);
+
+ memcpy(app->keys[0].val, old_key, 16);
+ if (bt_mesh_app_id(old_key, &app->keys[0].id)) {
+ return -EIO;
+ }
+
+ if (new_key) {
+ memcpy(app->keys[1].val, new_key, 16);
+ if (bt_mesh_app_id(new_key, &app->keys[1].id)) {
+ return -EIO;
+ }
+ }
+
+ app->net_idx = net_idx;
+ app->app_idx = app_idx;
+ app->updated = !!new_key;
+
+ return 0;
+}
+
+bool bt_mesh_app_key_exists(uint16_t app_idx)
+{
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ if (apps[i].app_idx == app_idx) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
+ off_t skip)
+{
+ size_t count = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ struct bt_mesh_app_key *app = &apps[i];
+
+ if (app->app_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (net_idx != BT_MESH_KEY_ANY && app->net_idx != net_idx) {
+ continue;
+ }
+
+ if (skip) {
+ skip--;
+ continue;
+ }
+
+ if (count >= max) {
+ return -ENOMEM;
+ }
+
+ app_idxs[count++] = app->app_idx;
+ }
+
+ return count;
+}
+
+int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
+ struct bt_mesh_subnet **sub,
+ const uint8_t **app_key, uint8_t *aid)
+{
+ struct bt_mesh_app_key *app = NULL;
+
+ if (BT_MESH_IS_DEV_KEY(ctx->app_idx)) {
+ /* With device keys, the application has to decide which subnet
+ * to send on.
+ */
+ *sub = bt_mesh_subnet_get(ctx->net_idx);
+ if (!*sub) {
+ BT_WARN("Unknown NetKey 0x%03x", ctx->net_idx);
+ return -EINVAL;
+ }
+
+ if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE &&
+ !bt_mesh_elem_find(ctx->addr)) {
+ struct bt_mesh_cdb_node *node;
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ BT_WARN("No DevKey for 0x%04x", ctx->addr);
+ return -EINVAL;
+ }
+
+ node = bt_mesh_cdb_node_get(ctx->addr);
+ if (!node) {
+ BT_WARN("No DevKey for 0x%04x", ctx->addr);
+ return -EINVAL;
+ }
+
+ *app_key = node->dev_key;
+ } else {
+ *app_key = bt_mesh.dev_key;
+ }
+
+ *aid = 0;
+ return 0;
+ }
+
+ app = app_get(ctx->app_idx);
+ if (!app) {
+ BT_WARN("Unknown AppKey 0x%03x", ctx->app_idx);
+ return -EINVAL;
+ }
+
+ *sub = bt_mesh_subnet_get(app->net_idx);
+ if (!*sub) {
+ BT_WARN("Unknown NetKey 0x%03x", app->net_idx);
+ return -EINVAL;
+ }
+
+ if ((*sub)->kr_phase == BT_MESH_KR_PHASE_2 && app->updated) {
+ *aid = app->keys[1].id;
+ *app_key = app->keys[1].val;
+ } else {
+ *aid = app->keys[0].id;
+ *app_key = app->keys[0].val;
+ }
+
+ return 0;
+}
+
+uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
+ struct bt_mesh_net_rx *rx,
+ int (*cb)(struct bt_mesh_net_rx *rx,
+ const uint8_t key[16], void *cb_data),
+ void *cb_data)
+{
+ int err, i;
+
+ if (dev_key) {
+ /* Attempt remote dev key first, as that is only available for
+ * provisioner devices, which normally don't interact with nodes
+ * that know their local dev key.
+ */
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB) &&
+ rx->net_if != BT_MESH_NET_IF_LOCAL) {
+ struct bt_mesh_cdb_node *node;
+
+ node = bt_mesh_cdb_node_get(rx->ctx.addr);
+ if (node && !cb(rx, node->dev_key, cb_data)) {
+ return BT_MESH_KEY_DEV_REMOTE;
+ }
+ }
+
+ /** Bluetooth Mesh Specification v1.0.1, section 3.4.3:
+ * The Device key is only valid for unicast addresses.
+ */
+ if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
+ err = cb(rx, bt_mesh.dev_key, cb_data);
+ if (!err) {
+ return BT_MESH_KEY_DEV_LOCAL;
+ }
+ }
+
+ return BT_MESH_KEY_UNUSED;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(apps); i++) {
+ const struct bt_mesh_app_key *app = &apps[i];
+ const struct bt_mesh_app_cred *cred;
+
+ if (app->app_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (app->net_idx != rx->sub->net_idx) {
+ continue;
+ }
+
+ if (rx->new_key && app->updated) {
+ cred = &app->keys[1];
+ } else {
+ cred = &app->keys[0];
+ }
+
+ if (cred->id != aid) {
+ continue;
+ }
+
+ err = cb(rx, cred->val, cb_data);
+ if (err) {
+ continue;
+ }
+
+ return app->app_idx;
+ }
+
+ return BT_MESH_KEY_UNUSED;
+}
+
+
+void bt_mesh_app_keys_reset(void)
+{
+ for (int i = 0; i < ARRAY_SIZE(apps); i++) {
+ struct bt_mesh_app_key *app = &apps[i];
+
+ if (app->app_idx != BT_MESH_KEY_UNUSED) {
+ app_key_del(app);
+ }
+ }
+}
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/app_keys.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/app_keys.h
new file mode 100644
index 000000000..2a4e51f53
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/app_keys.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _BT_MESH_APP_KEYS_H_
+#define _BT_MESH_APP_KEYS_H_
+
+#include "../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.
+ * @param net_idx NetIndex the application is bound to.
+ * @param old_key Current application key.
+ * @param new_key Updated application key, or NULL if not known.
+ *
+ * @return 0 on success, or (negative) error code on failure.
+ */
+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]);
+
+/** @brief Resolve the message encryption keys, given a message context.
+ *
+ * Will use the @c ctx::app_idx and @c ctx::net_idx fields to find a pair of
+ * message encryption keys. If @c ctx::app_idx represents a device key, the
+ * @c ctx::net_idx will be used to determine the net key. Otherwise, the
+ * @c ctx::net_idx parameter will be ignored.
+ *
+ * @param ctx Message context.
+ * @param sub Subnet return parameter.
+ * @param app_key Application return parameter.
+ * @param aid Application ID return parameter.
+ *
+ * @return 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx,
+ struct bt_mesh_subnet **sub,
+ const uint8_t **app_key, uint8_t *aid);
+
+/** @brief Iterate through all matching application keys and call @c cb on each.
+ *
+ * @param dev_key Whether to return device keys.
+ * @param aid 7 bit application ID to match.
+ * @param rx RX structure to match against.
+ * @param cb Callback to call for every valid app key.
+ * @param cb_data Callback data to pass to the callback.
+ *
+ * @return The AppIdx that yielded a 0-return from the callback.
+ */
+uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid,
+ struct bt_mesh_net_rx *rx,
+ int (*cb)(struct bt_mesh_net_rx *rx,
+ 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);
+
+#endif /* _BT_MESH_APP_KEYS_H_ */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c
index 89ee1a086..b7115c606 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.c
@@ -23,8 +23,8 @@
#include "crypto.h"
#include "beacon.h"
#include "foundation.h"
+#include "atomic.h"
-#define UNPROVISIONED_INTERVAL (K_SECONDS(5))
#define PROVISIONED_INTERVAL (K_SECONDS(10))
#define BEACON_TYPE_UNPROVISIONED 0x00
@@ -38,26 +38,12 @@
static struct k_delayed_work beacon_timer;
-static struct bt_mesh_subnet *cache_check(u8_t data[21])
+static int cache_check(struct bt_mesh_subnet *sub, void *beacon_data)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (!memcmp(sub->beacon_cache, data, 21)) {
- return sub;
- }
- }
-
- return NULL;
+ return !memcmp(sub->beacon_cache, beacon_data, 21);
}
-static void cache_add(u8_t data[21], struct bt_mesh_subnet *sub)
+static void cache_add(uint8_t data[21], struct bt_mesh_subnet *sub)
{
memcpy(sub->beacon_cache, data, 21);
}
@@ -74,16 +60,12 @@ static void beacon_complete(int err, void *user_data)
void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
struct os_mbuf *buf)
{
- u8_t flags = bt_mesh_net_flags(sub);
+ uint8_t flags = bt_mesh_net_flags(sub);
struct bt_mesh_subnet_keys *keys;
net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE);
- if (sub->kr_flag) {
- keys = &sub->keys[1];
- } else {
- keys = &sub->keys[0];
- }
+ keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)];
net_buf_simple_add_u8(buf, flags);
@@ -105,53 +87,43 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
#define BEACON_THRESHOLD(sub) (K_SECONDS(10 * ((sub)->beacons_last + 1)) - \
K_SECONDS(5))
-static int secure_beacon_send(void)
+static int secure_beacon_send(struct bt_mesh_subnet *sub, void *cb_data)
{
static const struct bt_mesh_send_cb send_cb = {
.end = beacon_complete,
};
- u32_t now = k_uptime_get_32();
- int i;
+ uint32_t now = k_uptime_get_32();
+ struct os_mbuf *buf;
+ uint32_t time_diff;
BT_DBG("");
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
- struct os_mbuf *buf;
- u32_t time_diff;
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- time_diff = now - sub->beacon_sent;
- if (time_diff < K_SECONDS(600) &&
- time_diff < BEACON_THRESHOLD(sub)) {
- continue;
- }
-
- buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT,
- K_NO_WAIT);
- if (!buf) {
- BT_ERR("Unable to allocate beacon buffer");
- return -ENOBUFS;
- }
-
- bt_mesh_beacon_create(sub, buf);
-
- bt_mesh_adv_send(buf, &send_cb, sub);
- net_buf_unref(buf);
+ time_diff = now - sub->beacon_sent;
+ if (time_diff < (600 * MSEC_PER_SEC) &&
+ time_diff < BEACON_THRESHOLD(sub)) {
+ return 0;
}
+ buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT, K_NO_WAIT);
+ if (!buf) {
+ BT_ERR("Unable to allocate beacon buffer");
+ return -ENOMEM;
+ }
+
+ bt_mesh_beacon_create(sub, buf);
+
+ bt_mesh_adv_send(buf, &send_cb, sub);
+ net_buf_unref(buf);
+
return 0;
}
static int unprovisioned_beacon_send(void)
{
const struct bt_mesh_prov *prov;
- u8_t uri_hash[16] = { 0 };
+ uint8_t uri_hash[16] = { 0 };
struct os_mbuf *buf;
- u16_t oob_info;
+ uint16_t oob_info;
BT_DBG("unprovisioned_beacon_send");
@@ -204,12 +176,11 @@ static int unprovisioned_beacon_send(void)
static void unprovisioned_beacon_recv(struct os_mbuf *buf)
{
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
const struct bt_mesh_prov *prov;
- u8_t *uuid;
- u16_t oob_info;
- u32_t uri_hash_val;
- u32_t *uri_hash = NULL;
+ uint8_t *uuid;
+ uint16_t oob_info;
+ uint32_t uri_hash_val;
+ uint32_t *uri_hash = NULL;
if (buf->om_len != 18 && buf->om_len != 22) {
BT_ERR("Invalid unprovisioned beacon length (%u)", buf->om_len);
@@ -233,13 +204,17 @@ static void unprovisioned_beacon_recv(struct os_mbuf *buf)
(bt_mesh_prov_oob_info_t)oob_info,
uri_hash);
}
-#endif
+}
+
+static void sub_update_beacon_observation(struct bt_mesh_subnet *sub)
+{
+ sub->beacons_last = sub->beacons_cur;
+ sub->beacons_cur = 0U;
}
static void update_beacon_observation(void)
{
static bool first_half;
- int i;
/* Observation period is 20 seconds, whereas the beacon timer
* runs every 10 seconds. We process what's happened during the
@@ -250,23 +225,15 @@ static void update_beacon_observation(void)
return;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- sub->beacons_last = sub->beacons_cur;
- sub->beacons_cur = 0;
- }
+ bt_mesh_subnet_foreach(sub_update_beacon_observation);
}
static void beacon_send(struct ble_npl_event *work)
{
/* Don't send anything if we have an active provisioning link */
- if ((MYNEWT_VAL(BLE_MESH_PROV)) && bt_prov_active()) {
- k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && bt_mesh_prov_active()) {
+ k_delayed_work_submit(&beacon_timer,
+ K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT)));
return;
}
@@ -274,34 +241,81 @@ static void beacon_send(struct ble_npl_event *work)
if (bt_mesh_is_provisioned()) {
update_beacon_observation();
- secure_beacon_send();
+ (void)bt_mesh_subnet_find(secure_beacon_send, NULL);
/* Only resubmit if beaconing is still enabled */
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED ||
+ if (bt_mesh_beacon_enabled() ||
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) {
k_delayed_work_submit(&beacon_timer,
PROVISIONED_INTERVAL);
}
- } else if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
- unprovisioned_beacon_send();
- k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL);
+
+ return;
}
+
+ if (IS_ENABLED(BLE_MESH_PB_ADV)) {
+ unprovisioned_beacon_send();
+ k_delayed_work_submit(&beacon_timer,
+ K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT)));
+ }
+}
+
+struct beacon_params {
+ const uint8_t *net_id;
+ const uint8_t *auth;
+ uint32_t iv_index;
+ uint8_t flags;
+
+ bool new_key;
+};
+
+static bool auth_match(struct bt_mesh_subnet_keys *keys,
+ const struct beacon_params *params)
+{
+ uint8_t net_auth[8];
+
+ if (memcmp(params->net_id, keys->net_id, 8)) {
+ return false;
+ }
+
+ bt_mesh_beacon_auth(keys->beacon, params->flags, keys->net_id,
+ params->iv_index, net_auth);
+
+ if (memcmp(params->auth, net_auth, 8)) {
+ BT_WARN("Authentication Value %s != %s",
+ bt_hex(params->auth, 8), bt_hex(net_auth, 8));
+ return false;
+ }
+
+ return true;
+}
+
+static int subnet_by_id(struct bt_mesh_subnet *sub, void *cb_data)
+{
+ struct beacon_params *params = cb_data;
+
+ for (int i = 0; i < ARRAY_SIZE(sub->keys); i++) {
+ if (sub->keys[i].valid && auth_match(&sub->keys[i], params)) {
+ params->new_key = (i > 0);
+ return true;
+ }
+ }
+
+ return false;
}
static void secure_beacon_recv(struct os_mbuf *buf)
{
- u8_t *data, *net_id, *auth;
+ struct beacon_params params;
struct bt_mesh_subnet *sub;
- u32_t iv_index;
- bool new_key, kr_change, iv_change;
- u8_t flags;
+ uint8_t *data;
if (buf->om_len < 21) {
BT_ERR("Too short secure beacon (len %u)", buf->om_len);
return;
}
- sub = cache_check(buf->om_data);
+ sub = bt_mesh_subnet_find(cache_check, buf->om_data);
if (sub) {
/* We've seen this beacon before - just update the stats */
goto update_stats;
@@ -310,27 +324,30 @@ static void secure_beacon_recv(struct os_mbuf *buf)
/* So we can add to the cache if auth matches */
data = buf->om_data;
- flags = net_buf_simple_pull_u8(buf);
- net_id = net_buf_simple_pull_mem(buf, 8);
- iv_index = net_buf_simple_pull_be32(buf);
- auth = buf->om_data;
+ params.flags = net_buf_simple_pull_u8(buf);
+ params.net_id = net_buf_simple_pull_mem(buf, 8);
+ params.iv_index = net_buf_simple_pull_be32(buf);
+ params.auth = buf->om_data;
BT_DBG("flags 0x%02x id %s iv_index 0x%08x",
- flags, bt_hex(net_id, 8), (unsigned) iv_index);
+ params.flags, bt_hex(params.net_id, 8), params.iv_index);
- sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key);
+ sub = bt_mesh_subnet_find(subnet_by_id, ¶ms);
if (!sub) {
BT_DBG("No subnet that matched beacon");
return;
}
- if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) {
+ if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !params.new_key) {
BT_WARN("Ignoring Phase 2 KR Update secured using old key");
return;
}
cache_add(data, sub);
+ bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(params.flags),
+ params.new_key);
+
/* If we have NetKey0 accept initiation only from it */
if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) &&
sub->net_idx != BT_MESH_KEY_PRIMARY) {
@@ -339,31 +356,18 @@ static void secure_beacon_recv(struct os_mbuf *buf)
}
BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
- sub->net_idx, (unsigned) iv_index, (unsigned) bt_mesh.iv_index);
+ sub->net_idx, params.iv_index, bt_mesh.iv_index);
if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) &&
(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ==
- BT_MESH_IV_UPDATE(flags))) {
+ BT_MESH_IV_UPDATE(params.flags))) {
bt_mesh_beacon_ivu_initiator(false);
}
- iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags));
-
- kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key);
- if (kr_change) {
- bt_mesh_net_beacon_update(sub);
- }
-
- if (iv_change) {
- /* Update all subnets */
- bt_mesh_net_sec_update(NULL);
- } else if (kr_change) {
- /* Key Refresh without IV Update only impacts one subnet */
- bt_mesh_net_sec_update(sub);
- }
+ bt_mesh_net_iv_update(params.iv_index, BT_MESH_IV_UPDATE(params.flags));
update_stats:
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED &&
+ if (bt_mesh_beacon_enabled() &&
sub->beacons_cur < 0xff) {
sub->beacons_cur++;
}
@@ -371,7 +375,7 @@ update_stats:
void bt_mesh_beacon_recv(struct os_mbuf *buf)
{
- u8_t type;
+ uint8_t type;
BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
@@ -383,7 +387,9 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
type = net_buf_simple_pull_u8(buf);
switch (type) {
case BEACON_TYPE_UNPROVISIONED:
- unprovisioned_beacon_recv(buf);
+ if (IS_ENABLED(BLE_MESH_PB_ADV)) {
+ unprovisioned_beacon_recv(buf);
+ }
break;
case BEACON_TYPE_SECURE:
secure_beacon_recv(buf);
@@ -394,8 +400,38 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf)
}
}
+void bt_mesh_beacon_update(struct bt_mesh_subnet *sub)
+{
+ uint8_t flags = bt_mesh_net_flags(sub);
+ struct bt_mesh_subnet_keys *keys;
+ int err;
+
+ keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)];
+
+ BT_DBG("NetIndex 0x%03x Using %s key", sub->net_idx,
+ SUBNET_KEY_TX_IDX(sub) ? "new" : "current");
+ BT_DBG("flags 0x%02x, IVI 0x%08x", flags, bt_mesh.iv_index);
+
+ err = bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
+ bt_mesh.iv_index, sub->auth);
+ if (err) {
+ BT_ERR("Failed updating net beacon for 0x%03x", sub->net_idx);
+ }
+}
+
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ if (evt != BT_MESH_KEY_DELETED) {
+ bt_mesh_beacon_update(sub);
+ }
+}
+
void bt_mesh_beacon_init(void)
{
+ if (!bt_mesh_subnet_cb_list[1]) {
+ bt_mesh_subnet_cb_list[1] = subnet_evt;
+ }
+
k_delayed_work_init(&beacon_timer, beacon_send);
}
@@ -404,35 +440,30 @@ void bt_mesh_beacon_ivu_initiator(bool enable)
atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable);
if (enable) {
- k_work_submit(&beacon_timer.work);
- } else if (bt_mesh_beacon_get() == BT_MESH_BEACON_DISABLED) {
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
+ } else if (!bt_mesh_beacon_enabled()) {
k_delayed_work_cancel(&beacon_timer);
}
}
+static void subnet_beacon_enable(struct bt_mesh_subnet *sub)
+{
+ sub->beacons_last = 0U;
+ sub->beacons_cur = 0U;
+
+ bt_mesh_beacon_update(sub);
+}
+
void bt_mesh_beacon_enable(void)
{
- int i;
-
if (!bt_mesh_is_provisioned()) {
- k_work_submit(&beacon_timer.work);
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
return;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
+ bt_mesh_subnet_foreach(subnet_beacon_enable);
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- sub->beacons_last = 0;
- sub->beacons_cur = 0;
-
- bt_mesh_net_beacon_update(sub);
- }
-
- k_work_submit(&beacon_timer.work);
+ k_delayed_work_submit(&beacon_timer, K_NO_WAIT);
}
void bt_mesh_beacon_disable(void)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h
index 08fd88d96..50f27cff9 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/beacon.h
@@ -22,5 +22,6 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
struct os_mbuf *buf);
void bt_mesh_beacon_init(void);
+void bt_mesh_beacon_update(struct bt_mesh_subnet *sub);
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cdb.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cdb.c
new file mode 100644
index 000000000..f9b5469d0
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cdb.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2019 Tobias Svehagen
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_MESH)
+
+#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_CDB)
+#define LOG_MODULE_NAME bt_mesh_cdb
+#include "nimble/porting/nimble/include/log/log.h"
+
+#include "../include/mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "settings.h"
+#include "mesh_priv.h"
+#include "../include/mesh/glue.h"
+
+#if MYNEWT_VAL(BLE_MESH_CDB)
+struct bt_mesh_cdb bt_mesh_cdb = {
+ .nodes = {
+ [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
+ .addr = BT_MESH_ADDR_UNASSIGNED,
+ }
+ },
+ .subnets = {
+ [0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = {
+ .net_idx = BT_MESH_KEY_UNUSED,
+ }
+ },
+ .app_keys = {
+ [0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = {
+ .net_idx = BT_MESH_KEY_UNUSED,
+ }
+ },
+};
+
+/*
+ * Check if an address range from addr_start for addr_start + num_elem - 1 is
+ * free for use. When a conflict is found, next will be set to the next address
+ * available after the conflicting range and -EAGAIN will be returned.
+ */
+static int addr_is_free(uint16_t addr_start, uint8_t num_elem, uint16_t *next)
+{
+ uint16_t addr_end = addr_start + num_elem - 1;
+ uint16_t other_start, other_end;
+ int i;
+
+ if (!BT_MESH_ADDR_IS_UNICAST(addr_start) ||
+ !BT_MESH_ADDR_IS_UNICAST(addr_end) ||
+ num_elem == 0) {
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+ continue;
+ }
+
+ other_start = node->addr;
+ other_end = other_start + node->num_elem - 1;
+
+ if (!(addr_end < other_start || addr_start > other_end)) {
+ if (next) {
+ *next = other_end + 1;
+ }
+
+ return -EAGAIN;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Find the lowest possible starting address that can fit num_elem elements. If
+ * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be
+ * returned. Otherwise the first address in the range is returned.
+ *
+ * NOTE: This is quite an ineffective algorithm as it might need to look
+ * through the array of nodes N+2 times. A more effective algorithm
+ * could be used if the nodes were stored in a sorted list.
+ */
+static uint16_t find_lowest_free_addr(uint8_t num_elem)
+{
+ uint16_t addr = 1, next = 0;
+ int err, i;
+
+ /*
+ * It takes a maximum of node count + 2 to find a free address if there
+ * is any. +1 for our own address and +1 for making sure that the
+ * address range is valid.
+ */
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) {
+ err = addr_is_free(addr, num_elem, &next);
+ if (err == 0) {
+ break;
+ } else if (err != -EAGAIN) {
+ addr = BT_MESH_ADDR_UNASSIGNED;
+ break;
+ }
+
+ addr = next;
+ }
+
+ return addr;
+}
+
+int bt_mesh_cdb_create(const uint8_t key[16])
+{
+ struct bt_mesh_cdb_subnet *sub;
+
+ if (atomic_test_and_set_bit(bt_mesh_cdb.flags,
+ BT_MESH_CDB_VALID)) {
+ return -EALREADY;
+ }
+
+ sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY);
+ if (sub == NULL) {
+ return -ENOMEM;
+ }
+
+ memcpy(sub->keys[0].net_key, key, 16);
+ bt_mesh_cdb.iv_index = 0;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ bt_mesh_store_cdb_subnet(sub);
+ }
+
+ return 0;
+}
+
+void bt_mesh_cdb_clear(void)
+{
+ int i;
+
+ atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID);
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+ if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) {
+ bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) {
+ bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+ if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) {
+ bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true);
+ }
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ }
+}
+
+void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update)
+{
+ BT_DBG("Updating IV index to %d\n", iv_index);
+
+ bt_mesh_cdb.iv_index = iv_index;
+
+ atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS,
+ iv_update);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb();
+ }
+}
+
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx)
+{
+ struct bt_mesh_cdb_subnet *sub;
+ int i;
+
+ if (bt_mesh_cdb_subnet_get(net_idx) != NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ sub = &bt_mesh_cdb.subnets[i];
+
+ if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ sub->net_idx = net_idx;
+
+ return sub;
+ }
+
+ return NULL;
+}
+
+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);
+ }
+
+ sub->net_idx = BT_MESH_KEY_UNUSED;
+ memset(sub->keys, 0, sizeof(sub->keys));
+}
+
+struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ if (bt_mesh_cdb.subnets[i].net_idx == net_idx) {
+ return &bt_mesh_cdb.subnets[i];
+ }
+ }
+
+ return NULL;
+}
+
+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);
+ }
+}
+
+uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub)
+{
+ uint8_t flags = 0x00;
+
+ if (sub && sub->kr_flag) {
+ flags |= BT_MESH_NET_FLAG_KR;
+ }
+
+ if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) {
+ flags |= BT_MESH_NET_FLAG_IVU;
+ }
+
+ return flags;
+}
+
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem, uint16_t net_idx)
+{
+ int i;
+
+ if (addr == BT_MESH_ADDR_UNASSIGNED) {
+ addr = find_lowest_free_addr(num_elem);
+ if (addr == BT_MESH_ADDR_UNASSIGNED) {
+ return NULL;
+ }
+ } else if (addr_is_free(addr, num_elem, NULL) < 0) {
+ BT_DBG("Address range 0x%04x-0x%04x is not free", addr,
+ addr + num_elem - 1);
+ return NULL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+ memcpy(node->uuid, uuid, 16);
+ node->addr = addr;
+ node->num_elem = num_elem;
+ node->net_idx = net_idx;
+ atomic_set(node->flags, 0);
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+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);
+ }
+
+ node->addr = BT_MESH_ADDR_UNASSIGNED;
+ memset(node->dev_key, 0, sizeof(node->dev_key));
+}
+
+struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) {
+ struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i];
+
+ if (addr >= node->addr &&
+ addr <= node->addr + node->num_elem - 1) {
+ return node;
+ }
+ }
+
+ return NULL;
+}
+
+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);
+ }
+}
+
+void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+ if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) {
+ continue;
+ }
+
+ if (func(&bt_mesh_cdb.nodes[i], user_data) ==
+ BT_MESH_CDB_ITER_STOP) {
+ break;
+ }
+ }
+}
+
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
+ uint16_t app_idx)
+{
+ struct bt_mesh_cdb_app_key *key;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+ key = &bt_mesh_cdb.app_keys[i];
+
+ if (key->net_idx != BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ key->net_idx = net_idx;
+ key->app_idx = app_idx;
+
+ return key;
+ }
+
+ return NULL;
+}
+
+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);
+ }
+
+ key->net_idx = BT_MESH_ADDR_UNASSIGNED;
+ memset(key->keys, 0, sizeof(key->keys));
+}
+
+struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) {
+ struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i];
+
+ if (key->net_idx != BT_MESH_KEY_UNUSED &&
+ key->app_idx == app_idx) {
+ return key;
+ }
+ }
+
+ return NULL;
+}
+
+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);
+ }
+}
+#endif
+
+#endif // MYNEWT_VAL(BLE_MESH)
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg.c
new file mode 100644
index 000000000..819fc48be
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_MESH)
+
+#include "../include/mesh/mesh.h"
+#include "mesh_priv.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "settings.h"
+#include "heartbeat.h"
+#include "friend.h"
+#include "cfg.h"
+#include "../include/mesh/glue.h"
+
+void bt_mesh_beacon_set(bool beacon)
+{
+ if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) {
+ return;
+ }
+
+ atomic_set_bit_to(bt_mesh.flags, BT_MESH_BEACON, beacon);
+
+ if (beacon) {
+ bt_mesh_beacon_enable();
+ } else {
+ bt_mesh_beacon_disable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+}
+
+bool bt_mesh_beacon_enabled(void)
+{
+ return atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON);
+}
+
+static int feature_set(int feature_flag, enum bt_mesh_feat_state state)
+{
+ if (state != BT_MESH_FEATURE_DISABLED &&
+ state != BT_MESH_FEATURE_ENABLED) {
+ return -EINVAL;
+ }
+
+ if (atomic_test_bit(bt_mesh.flags, feature_flag) ==
+ (state == BT_MESH_FEATURE_ENABLED)) {
+ return -EALREADY;
+ }
+
+ atomic_set_bit_to(bt_mesh.flags, feature_flag,
+ (state == BT_MESH_FEATURE_ENABLED));
+
+ return 0;
+}
+
+static enum bt_mesh_feat_state feature_get(int feature_flag)
+{
+ return atomic_test_bit(bt_mesh.flags, feature_flag) ?
+ BT_MESH_FEATURE_ENABLED :
+ BT_MESH_FEATURE_DISABLED;
+}
+
+int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy)
+{
+ int err;
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_GATT_PROXY, gatt_proxy);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_PROXY);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void)
+{
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ return BT_MESH_FEATURE_NOT_SUPPORTED;
+ }
+
+ return feature_get(BT_MESH_GATT_PROXY);
+}
+
+int bt_mesh_default_ttl_set(uint8_t default_ttl)
+{
+ if (default_ttl == 1 || default_ttl > BT_MESH_TTL_MAX) {
+ return -EINVAL;
+ }
+
+ if (default_ttl == bt_mesh.default_ttl) {
+ return 0;
+ }
+
+ bt_mesh.default_ttl = default_ttl;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+uint8_t bt_mesh_default_ttl_get(void)
+{
+ return bt_mesh.default_ttl;
+}
+
+int bt_mesh_friend_set(enum bt_mesh_feat_state friendship)
+{
+ int err;
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_FRIEND, friendship);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_FRIEND);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ if (friendship == BT_MESH_FEATURE_DISABLED) {
+ bt_mesh_friends_clear();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_friend_get(void)
+{
+ if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ return BT_MESH_FEATURE_NOT_SUPPORTED;
+ }
+
+ return feature_get(BT_MESH_FRIEND);
+}
+
+void bt_mesh_net_transmit_set(uint8_t xmit)
+{
+ if (bt_mesh.net_xmit == xmit) {
+ return;
+ }
+
+ bt_mesh.net_xmit = xmit;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+}
+
+uint8_t bt_mesh_net_transmit_get(void)
+{
+ return bt_mesh.net_xmit;
+}
+
+int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit)
+{
+ int err;
+
+ if (!CONFIG_BT_MESH_RELAY) {
+ return -ENOTSUP;
+ }
+
+ err = feature_set(BT_MESH_RELAY, relay);
+ if (err == -EINVAL) {
+ return err;
+ }
+
+ if (err == -EALREADY && bt_mesh.relay_xmit == xmit) {
+ return -EALREADY;
+ }
+
+ bt_mesh.relay_xmit = xmit;
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_RELAY);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ bt_mesh_store_cfg();
+ }
+
+ return 0;
+}
+
+enum bt_mesh_feat_state bt_mesh_relay_get(void)
+{
+ return feature_get(BT_MESH_RELAY);
+}
+
+uint8_t bt_mesh_relay_retransmit_get(void)
+{
+ if (!CONFIG_BT_MESH_RELAY) {
+ return 0;
+ }
+
+ return bt_mesh.relay_xmit;
+}
+
+bool bt_mesh_fixed_group_match(uint16_t addr)
+{
+ /* Check for fixed group addresses */
+ switch (addr) {
+ case BT_MESH_ADDR_ALL_NODES:
+ return true;
+ case BT_MESH_ADDR_PROXIES:
+ return (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED);
+ case BT_MESH_ADDR_FRIENDS:
+ return (bt_mesh_friend_get() == BT_MESH_FEATURE_ENABLED);
+ case BT_MESH_ADDR_RELAYS:
+ return (bt_mesh_relay_get() == BT_MESH_FEATURE_ENABLED);
+ default:
+ return false;
+ }
+}
+
+void bt_mesh_cfg_init(void)
+{
+ bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL;
+ bt_mesh.net_xmit =
+ BT_MESH_TRANSMIT(CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT,
+ CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL);
+
+#if defined(CONFIG_BT_MESH_RELAY)
+ bt_mesh.relay_xmit =
+ BT_MESH_TRANSMIT(CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT,
+ CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL);
+#endif
+
+ if (CONFIG_BT_MESH_RELAY_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_RELAY);
+ }
+
+ if (CONFIG_BT_MESH_BEACON_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_BEACON);
+ }
+
+ if (CONFIG_BT_MESH_GATT_PROXY_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_GATT_PROXY);
+ }
+
+ if (CONFIG_BT_MESH_FRIEND_ENABLED) {
+ atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND);
+ }
+}
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg.h
new file mode 100644
index 000000000..6f58acf8b
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+void bt_mesh_cfg_init(void);
+
+bool bt_mesh_fixed_group_match(uint16_t addr);
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c
index d2596c434..d3c88f78c 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_cli.c
@@ -27,11 +27,11 @@
#define DUMMY_2_BYTE_OP BT_MESH_MODEL_OP_2(0xff, 0xff)
struct comp_data {
- u8_t *status;
+ uint8_t *status;
struct os_mbuf *comp;
};
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_cfg_cli *cli;
@@ -63,9 +63,9 @@ static void comp_data_status(struct bt_mesh_model *model,
static void state_status_u8(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf,
- u32_t expect_status)
+ uint32_t expect_status)
{
- u8_t *status;
+ 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,
@@ -112,8 +112,8 @@ static void gatt_proxy_status(struct bt_mesh_model *model,
}
struct relay_param {
- u8_t *status;
- u8_t *transmit;
+ uint8_t *status;
+ uint8_t *transmit;
};
static void relay_status(struct bt_mesh_model *model,
@@ -139,8 +139,8 @@ static void relay_status(struct bt_mesh_model *model,
}
struct net_key_param {
- u8_t *status;
- u16_t net_idx;
+ uint8_t *status;
+ uint16_t net_idx;
};
static void net_key_status(struct bt_mesh_model *model,
@@ -148,8 +148,8 @@ static void net_key_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct net_key_param *param;
- u16_t net_idx, app_idx;
- u8_t status;
+ uint16_t net_idx;
+ 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,
@@ -161,7 +161,7 @@ static void net_key_status(struct bt_mesh_model *model,
}
status = net_buf_simple_pull_u8(buf);
- key_idx_unpack(buf, &net_idx, &app_idx);
+ net_idx = net_buf_simple_pull_le16(buf) & 0xfff;
param = cli->op_param;
if (param->net_idx != net_idx) {
@@ -176,10 +176,66 @@ static void net_key_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct net_key_list_param {
+ uint16_t *keys;
+ size_t *key_cnt;
+};
+
+static void 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;
+
+ 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_KEY_LIST) {
+ BT_WARN("Unexpected Net Key List message");
+ 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]);
+ }
+
+ if (i < *param->key_cnt && buf->om_len >= 2) {
+ param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff;
+ }
+
+ *param->key_cnt = i;
+
+ k_sem_give(&cli->op_sync);
+}
+
+static void 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",
+ ctx->net_idx, ctx->app_idx, ctx->addr);
+
+ if (cli->op_pending != OP_NODE_RESET_STATUS) {
+ BT_WARN("Unexpected Node Reset Status message");
+ return;
+ }
+
+ param = cli->op_param;
+
+ if (param) {
+ *param = true;
+ }
+ k_sem_give(&cli->op_sync);
+}
+
struct app_key_param {
- u8_t *status;
- u16_t net_idx;
- u16_t app_idx;
+ uint8_t *status;
+ uint16_t net_idx;
+ uint16_t app_idx;
};
static void app_key_status(struct bt_mesh_model *model,
@@ -187,8 +243,8 @@ static void app_key_status(struct bt_mesh_model *model,
struct os_mbuf*buf)
{
struct app_key_param *param;
- u16_t net_idx, app_idx;
- u8_t status;
+ uint16_t net_idx, app_idx;
+ 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,
@@ -215,21 +271,71 @@ static void app_key_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct app_key_list_param {
+ uint16_t net_idx;
+ uint8_t *status;
+ uint16_t *keys;
+ size_t *key_cnt;
+};
+
+static void 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;
+ uint8_t status;
+ int i;
+
+ 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_APP_KEY_LIST) {
+ BT_WARN("Unexpected App Key List message");
+ 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;
+ }
+
+ for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) {
+ key_idx_unpack(buf, ¶m->keys[i], ¶m->keys[i + 1]);
+ }
+
+ if (i < *param->key_cnt && buf->om_len >= 2) {
+ param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff;
+ }
+
+ *param->key_cnt = i;
+ if (param->status) {
+ *param->status = status;
+ }
+
+ k_sem_give(&cli->op_sync);
+}
+
struct mod_app_param {
- u8_t *status;
- u16_t elem_addr;
- u16_t mod_app_idx;
- u16_t mod_id;
- u16_t cid;
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t mod_app_idx;
+ uint16_t mod_id;
+ uint16_t cid;
};
static void mod_app_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
struct mod_app_param *param;
- u8_t status;
+ 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,
@@ -267,11 +373,92 @@ static void mod_app_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+struct mod_member_list_param {
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t mod_id;
+ uint16_t cid;
+ uint16_t *members;
+ 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;
+ uint16_t elem_addr, mod_id, cid;
+ uint8_t status;
+ int i;
+
+ status = net_buf_simple_pull_u8(buf);
+ elem_addr = net_buf_simple_pull_le16(buf);
+ if (vnd) {
+ cid = net_buf_simple_pull_le16(buf);
+ }
+
+ 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");
+ return;
+ }
+
+ if (buf->om_len % 2) {
+ BT_WARN("Model Member List invalid length");
+ return;
+ }
+
+ for (i = 0; i < *param->member_cnt && buf->om_len; i++) {
+ param->members[i] = net_buf_simple_pull_le16(buf);
+ }
+
+ *param->member_cnt = i;
+ if (param->status) {
+ *param->status = status;
+ }
+
+ k_sem_give(&cli->op_sync);
+}
+
+static void mod_app_list(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));
+
+ if (cli->op_pending != OP_SIG_MOD_APP_LIST) {
+ BT_WARN("Unexpected Model App List message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, false);
+}
+
+static void mod_app_list_vnd(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));
+
+ if (cli->op_pending != OP_VND_MOD_APP_LIST) {
+ BT_WARN("Unexpected Model App List Vendor message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, true);
+}
+
struct mod_pub_param {
- u16_t mod_id;
- u16_t cid;
- u16_t elem_addr;
- u8_t *status;
+ uint16_t mod_id;
+ uint16_t cid;
+ uint16_t elem_addr;
+ uint8_t *status;
struct bt_mesh_cfg_mod_pub *pub;
};
@@ -279,9 +466,9 @@ static void mod_pub_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t mod_id, cid, elem_addr;
+ uint16_t mod_id, cid, elem_addr;
struct mod_pub_param *param;
- u8_t status;
+ 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,
@@ -343,21 +530,21 @@ static void mod_pub_status(struct bt_mesh_model *model,
}
struct mod_sub_param {
- u8_t *status;
- u16_t elem_addr;
- u16_t *sub_addr;
- u16_t *expect_sub;
- u16_t mod_id;
- u16_t cid;
+ uint8_t *status;
+ uint16_t elem_addr;
+ uint16_t *sub_addr;
+ uint16_t *expect_sub;
+ uint16_t mod_id;
+ uint16_t cid;
};
static void mod_sub_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf*buf)
{
- u16_t elem_addr, sub_addr, mod_id, cid;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
struct mod_sub_param *param;
- u8_t status;
+ 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,
@@ -399,8 +586,40 @@ static void mod_sub_status(struct bt_mesh_model *model,
k_sem_give(&cli->op_sync);
}
+static void mod_sub_list(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));
+
+ if (cli->op_pending != OP_MOD_SUB_LIST) {
+ BT_WARN("Unexpected Model Subscription List message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, false);
+}
+
+static void mod_sub_list_vnd(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));
+
+ if (cli->op_pending != OP_MOD_SUB_LIST_VND) {
+ BT_WARN("Unexpected Model Subscription List Vendor message");
+ return;
+ }
+
+ mod_member_list_handle(ctx, buf, true);
+}
+
struct hb_sub_param {
- u8_t *status;
+ uint8_t *status;
struct bt_mesh_cfg_hb_sub *sub;
};
@@ -434,7 +653,7 @@ static void hb_sub_status(struct bt_mesh_model *model,
}
struct hb_pub_param {
- u8_t *status;
+ uint8_t *status;
struct bt_mesh_cfg_hb_pub *pub;
};
@@ -477,12 +696,19 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = {
{ OP_GATT_PROXY_STATUS, 1, gatt_proxy_status },
{ OP_RELAY_STATUS, 2, relay_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},
BT_MESH_MODEL_OP_END,
};
@@ -518,7 +744,7 @@ const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = {
.init = cfg_cli_init,
};
-static int cli_prepare(void *param, u32_t op)
+static int cli_prepare(void *param, uint32_t op)
{
if (!cli) {
BT_ERR("No available Configuration Client context!");
@@ -553,8 +779,8 @@ static int cli_wait(void)
return err;
}
-int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
- u8_t *status, struct os_mbuf *comp)
+int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
+ uint8_t *status, struct os_mbuf *comp)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEV_COMP_DATA_GET, 1);
struct bt_mesh_msg_ctx ctx = {
@@ -590,8 +816,8 @@ done:
return err;
}
-static int get_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
- u8_t *val)
+static int get_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp,
+ uint8_t *val)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -622,8 +848,8 @@ done:
return err;
}
-static int set_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp,
- u8_t new_val, u8_t *val)
+static int set_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp,
+ uint8_t new_val, uint8_t *val)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 1);
struct bt_mesh_msg_ctx ctx = {
@@ -655,57 +881,71 @@ done:
return err;
}
-int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_BEACON_GET, OP_BEACON_STATUS,
status);
}
-int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status)
+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,
val, status);
}
-int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl)
+int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl)
{
return get_state_u8(net_idx, addr, OP_DEFAULT_TTL_GET,
OP_DEFAULT_TTL_STATUS, ttl);
}
-int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl)
+int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl)
{
return set_state_u8(net_idx, addr, OP_DEFAULT_TTL_SET,
OP_DEFAULT_TTL_STATUS, val, ttl);
}
-int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_FRIEND_GET,
OP_FRIEND_STATUS, status);
}
-int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status)
+int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status)
{
return set_state_u8(net_idx, addr, OP_FRIEND_SET, OP_FRIEND_STATUS,
val, status);
}
-int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status)
+int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status)
{
return get_state_u8(net_idx, addr, OP_GATT_PROXY_GET,
OP_GATT_PROXY_STATUS, status);
}
-int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
- u8_t *status)
+int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
+ uint8_t *status)
{
return set_state_u8(net_idx, addr, OP_GATT_PROXY_SET,
OP_GATT_PROXY_STATUS, val, status);
}
-int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
- u8_t *transmit)
+int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
+ uint8_t val, uint8_t *transmit)
+{
+ return set_state_u8(net_idx, addr, OP_NET_TRANSMIT_SET,
+ OP_NET_TRANSMIT_STATUS, val, transmit);
+}
+
+int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
+ uint8_t *transmit)
+{
+ return get_state_u8(net_idx, addr, OP_NET_TRANSMIT_GET,
+ OP_NET_TRANSMIT_STATUS, transmit);
+}
+
+int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
+ uint8_t *transmit)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -740,8 +980,8 @@ done:
return err;
}
-int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
- u8_t new_transmit, u8_t *status, u8_t *transmit)
+int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
+ uint8_t new_transmit, uint8_t *status, uint8_t *transmit)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_SET, 2);
struct bt_mesh_msg_ctx ctx = {
@@ -778,8 +1018,8 @@ done:
return err;
}
-int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
- const u8_t net_key[16], u8_t *status)
+int bt_mesh_cfg_net_key_add(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_ADD, 18);
struct bt_mesh_msg_ctx ctx = {
@@ -821,9 +1061,85 @@ done:
return err;
}
-int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
- u16_t key_app_idx, const u8_t app_key[16],
- u8_t *status)
+int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
+ size_t *key_cnt)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_GET, 0);
+ 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_list_param param = {
+ .keys = keys,
+ .key_cnt = key_cnt,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_NET_KEY_LIST);
+ if (err) {
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NET_KEY_GET);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ return err;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint8_t *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_DEL, 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 net_key_param param = {
+ .status = status,
+ .net_idx = key_net_idx,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_NET_KEY_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NET_KEY_DEL);
+ 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);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ return err;
+}
+
+int bt_mesh_cfg_app_key_add(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_ADD, 19);
struct bt_mesh_msg_ctx ctx = {
@@ -866,9 +1182,137 @@ done:
return err;
}
-static int mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u16_t cid,
- u8_t *status)
+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);
+ 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,
+ };
+
+ int err;
+
+ if (status) {
+ *status = false;
+ }
+
+ err = cli_prepare(status, OP_NODE_RESET_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_NODE_RESET);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ if (err) {
+ return err;
+ } else {
+ return 0;
+ }
+}
+
+int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
+ uint8_t *status, uint16_t *keys, size_t *key_cnt)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_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 app_key_list_param param = {
+ .net_idx = key_net_idx,
+ .status = status,
+ .keys = keys,
+ .key_cnt = key_cnt,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_APP_KEY_LIST);
+ if (err) {
+ os_mbuf_free_chain(msg);
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_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);
+ os_mbuf_free_chain(msg);
+ cli_reset();
+ return err;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
+ uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_DEL, 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 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);
+ if (err) {
+ os_mbuf_free_chain(msg);
+ return err;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_DEL);
+ key_idx_pack(msg, key_net_idx, key_app_idx);
+
+ err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL);
+ if (err) {
+ BT_ERR("model_send() failed (err %d)", err);
+ os_mbuf_free_chain(msg);
+ cli_reset();
+ return err;
+ }
+
+ if (!status) {
+ cli_reset();
+ os_mbuf_free_chain(msg);
+ return 0;
+ }
+
+ os_mbuf_free_chain(msg);
+ return cli_wait();
+}
+
+static int mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+ uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_BIND, 8);
struct bt_mesh_msg_ctx ctx = {
@@ -919,16 +1363,16 @@ done:
return err;
}
-int bt_mesh_cfg_mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u8_t *status)
+int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status)
{
return mod_app_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
CID_NVAL, status);
}
-int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_app_idx, u16_t mod_id, u16_t cid,
- u8_t *status)
+int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+ uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -938,8 +1382,160 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
status);
}
-static int mod_sub(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid, u8_t *status)
+static int mod_app_unbind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
+ uint8_t *status)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_UNBIND, 8);
+ 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_app_param param = {
+ .status = status,
+ .elem_addr = elem_addr,
+ .mod_app_idx = mod_app_idx,
+ .mod_id = mod_id,
+ .cid = cid,
+ };
+ int err;
+
+ err = cli_prepare(¶m, OP_MOD_APP_STATUS);
+ if (err) {
+ goto done;
+ }
+
+ bt_mesh_model_msg_init(msg, OP_MOD_APP_UNBIND);
+ net_buf_simple_add_le16(msg, elem_addr);
+ net_buf_simple_add_le16(msg, mod_app_idx);
+
+ 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);
+ cli_reset();
+ goto done;
+ }
+
+ if (!status) {
+ cli_reset();
+ err = 0;
+ goto done;
+ }
+
+done:
+ os_mbuf_free_chain(msg);
+ if (err) {
+ return err;
+ } else {
+ return cli_wait();
+ }
+}
+
+int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t mod_app_idx,
+ uint16_t mod_id, uint8_t *status)
+{
+ return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx, mod_id,
+ CID_NVAL, status);
+}
+
+int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, uint16_t mod_app_idx,
+ uint16_t mod_id, uint16_t cid, uint8_t *status)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx,
+ mod_id, cid, status);
+}
+
+static int mod_member_list_get(uint32_t op, uint32_t expect_op, uint16_t net_idx,
+ uint16_t addr, uint16_t elem_addr, uint16_t mod_id,
+ uint16_t cid, uint8_t *status, uint16_t *apps,
+ size_t *app_cnt)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 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_member_list_param param = {
+ .status = status,
+ .elem_addr = elem_addr,
+ .mod_id = mod_id,
+ .cid = cid,
+ .members = apps,
+ .member_cnt = app_cnt,
+ };
+ int err;
+
+ err = cli_prepare(¶m, expect_op);
+ if (err) {
+ goto done;
+ }
+
+ BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x",
+ net_idx, addr, elem_addr);
+ BT_DBG("mod_id 0x%04x cid 0x%04x op: %x", mod_id, cid, op);
+
+ bt_mesh_model_msg_init(msg, op);
+ net_buf_simple_add_le16(msg, elem_addr);
+
+ 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);
+ cli_reset();
+ goto done;
+ }
+
+ err = cli_wait();
+done:
+ os_mbuf_free_chain(msg);
+ return err;
+}
+
+int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint8_t *status, uint16_t *apps,
+ size_t *app_cnt)
+{
+ return mod_member_list_get(OP_SIG_MOD_APP_GET, OP_SIG_MOD_APP_LIST,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, apps, app_cnt);
+}
+
+int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status,
+ uint16_t *apps, size_t *app_cnt)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_member_list_get(OP_VND_MOD_APP_GET, OP_VND_MOD_APP_LIST,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, apps, app_cnt);
+}
+
+static int mod_sub(uint32_t op, 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)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 8);
struct bt_mesh_msg_ctx ctx = {
@@ -981,6 +1577,7 @@ static int mod_sub(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
if (!status) {
cli_reset();
+ err = 0;
goto done;
}
@@ -990,16 +1587,16 @@ done:
return err;
}
-int bt_mesh_cfg_mod_sub_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status)
+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)
{
return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr,
mod_id, CID_NVAL, status);
}
-int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid,
- u8_t *status)
+int bt_mesh_cfg_mod_sub_add_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) {
return -EINVAL;
@@ -1009,16 +1606,16 @@ int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, status);
}
-int bt_mesh_cfg_mod_sub_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *status)
+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)
{
return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr,
mod_id, CID_NVAL, status);
}
-int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u16_t cid,
- u8_t *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) {
return -EINVAL;
@@ -1028,16 +1625,16 @@ int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, status);
}
-int bt_mesh_cfg_mod_sub_overwrite(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t sub_addr, u16_t mod_id, u8_t *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)
{
return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr,
sub_addr, mod_id, CID_NVAL, status);
}
-int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
- u16_t elem_addr, u16_t sub_addr,
- u16_t mod_id, u16_t cid, u8_t *status)
+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) {
return -EINVAL;
@@ -1047,9 +1644,9 @@ int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
sub_addr, mod_id, cid, status);
}
-static int mod_sub_va(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id, u16_t cid,
- u16_t *virt_addr, u8_t *status)
+static int mod_sub_va(uint32_t op, uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id, uint16_t cid,
+ uint16_t *virt_addr, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 22);
struct bt_mesh_msg_ctx ctx = {
@@ -1104,17 +1701,17 @@ done:
return err;
}
-int bt_mesh_cfg_mod_sub_va_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t *virt_addr, uint8_t *status)
{
return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label,
mod_id, CID_NVAL, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t cid, u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t cid, uint16_t *virt_addr, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1124,17 +1721,17 @@ int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t *virt_addr, uint8_t *status)
{
return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label,
mod_id, CID_NVAL, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- const u8_t label[16], u16_t mod_id,
- u16_t cid, u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ const uint8_t label[16], uint16_t mod_id,
+ uint16_t cid, uint16_t *virt_addr, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1144,19 +1741,19 @@ int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
mod_id, cid, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_overwrite(u16_t net_idx, u16_t addr,
- u16_t elem_addr, const u8_t label[16],
- u16_t mod_id, u16_t *virt_addr,
- u8_t *status)
+int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, const uint8_t label[16],
+ uint16_t mod_id, uint16_t *virt_addr,
+ uint8_t *status)
{
return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr,
label, mod_id, CID_NVAL, virt_addr, status);
}
-int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
- u16_t elem_addr, const u8_t label[16],
- u16_t mod_id, u16_t cid,
- u16_t *virt_addr, u8_t *status)
+int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
+ uint16_t elem_addr, const uint8_t label[16],
+ uint16_t mod_id, uint16_t cid,
+ uint16_t *virt_addr, uint8_t *status)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1166,9 +1763,31 @@ int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
label, mod_id, cid, virt_addr, status);
}
-static int mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
+int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint8_t *status, uint16_t *subs,
+ size_t *sub_cnt)
+{
+ return mod_member_list_get(OP_MOD_SUB_GET, OP_MOD_SUB_LIST, net_idx,
+ addr, elem_addr, mod_id, CID_NVAL, status,
+ subs, sub_cnt);
+}
+
+int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
+ uint16_t mod_id, uint16_t cid, uint8_t *status,
+ uint16_t *subs, size_t *sub_cnt)
+{
+ if (cid == CID_NVAL) {
+ return -EINVAL;
+ }
+
+ return mod_member_list_get(OP_MOD_SUB_GET_VND, OP_MOD_SUB_LIST_VND,
+ net_idx, addr, elem_addr, mod_id, CID_NVAL,
+ status, subs, sub_cnt);
+}
+
+static int mod_pub_get(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_GET, 6);
struct bt_mesh_msg_ctx ctx = {
@@ -1219,17 +1838,17 @@ done:
return err;
}
-int bt_mesh_cfg_mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
- u8_t *status)
+int bt_mesh_cfg_mod_pub_get(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_get(net_idx, addr, elem_addr, mod_id, CID_NVAL,
pub, status);
}
-int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
+int bt_mesh_cfg_mod_pub_get_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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1238,9 +1857,9 @@ int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
return mod_pub_get(net_idx, addr, elem_addr, mod_id, cid, pub, status);
}
-static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *status)
+static int mod_pub_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_SET, 13);
struct bt_mesh_msg_ctx ctx = {
@@ -1267,7 +1886,7 @@ static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
net_buf_simple_add_le16(msg, elem_addr);
net_buf_simple_add_le16(msg, pub->addr);
- net_buf_simple_add_le16(msg, (pub->app_idx | (pub->cred_flag << 12)));
+ 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);
@@ -1296,17 +1915,17 @@ done:
return err;
}
-int bt_mesh_cfg_mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
- u8_t *status)
+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);
}
-int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
- u16_t mod_id, u16_t cid,
- struct bt_mesh_cfg_mod_pub *pub, u8_t *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)
{
if (cid == CID_NVAL) {
return -EINVAL;
@@ -1315,8 +1934,8 @@ int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status);
}
-int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_sub *sub, u8_t *status)
+int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_sub *sub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_SET, 5);
struct bt_mesh_msg_ctx ctx = {
@@ -1359,8 +1978,8 @@ done:
return err;
}
-int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_sub *sub, u8_t *status)
+int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_sub *sub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -1400,8 +2019,8 @@ done:
return err;
}
-int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
- const struct bt_mesh_cfg_hb_pub *pub, u8_t *status)
+int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
+ const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_SET, 9);
struct bt_mesh_msg_ctx ctx = {
@@ -1446,8 +2065,8 @@ done:
return err;
}
-int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
- struct bt_mesh_cfg_hb_pub *pub, u8_t *status)
+int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
+ struct bt_mesh_cfg_hb_pub *pub, uint8_t *status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_GET, 0);
struct bt_mesh_msg_ctx ctx = {
@@ -1487,12 +2106,12 @@ done:
return err;
}
-s32_t bt_mesh_cfg_cli_timeout_get(void)
+int32_t bt_mesh_cfg_cli_timeout_get(void)
{
return msg_timeout;
}
-void bt_mesh_cfg_cli_timeout_set(s32_t timeout)
+void bt_mesh_cfg_cli_timeout_set(int32_t timeout)
{
msg_timeout = timeout;
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c
index f5de01cbf..14ada332a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/cfg_srv.c
@@ -19,23 +19,23 @@
#include "mesh_priv.h"
#include "adv.h"
+#include "app_keys.h"
#include "net.h"
+#include "rpl.h"
#include "lpn.h"
#include "transport.h"
+#include "heartbeat.h"
#include "crypto.h"
#include "access.h"
#include "beacon.h"
#include "proxy.h"
#include "foundation.h"
#include "friend.h"
-#include "testing.h"
#include "settings.h"
+#include "cfg.h"
-#define DEFAULT_TTL 7
-
-static struct bt_mesh_cfg_srv *conf;
-
-static struct label labels[CONFIG_BT_MESH_LABEL_COUNT];
+void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt);
static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
bool primary)
@@ -44,7 +44,7 @@ static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
int i;
if (net_buf_simple_tailroom(buf) <
- 4 + (elem->model_count * 2) + (elem->vnd_model_count * 2)) {
+ 4 + (elem->model_count * 2) + (elem->vnd_model_count * 4)) {
BT_ERR("Too large device composition");
return -E2BIG;
}
@@ -70,7 +70,7 @@ static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem,
static int comp_get_page_0(struct os_mbuf *buf)
{
- u16_t feat = 0;
+ uint16_t feat = 0;
const struct bt_mesh_comp *comp;
int i;
@@ -115,7 +115,7 @@ static void dev_comp_data_get(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
- u8_t page;
+ uint8_t page;
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,
@@ -147,7 +147,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
struct os_mbuf *buf, bool *vnd)
{
if (buf->om_len < 4) {
- u16_t id;
+ uint16_t id;
id = net_buf_simple_pull_le16(buf);
@@ -157,7 +157,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
return bt_mesh_model_find(elem, id);
} else {
- u16_t company, id;
+ uint16_t company, id;
company = net_buf_simple_pull_le16(buf);
id = net_buf_simple_pull_le16(buf);
@@ -171,25 +171,9 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem,
}
}
-static bool app_key_is_valid(u16_t app_idx)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != BT_MESH_KEY_UNUSED &&
- key->app_idx == app_idx) {
- return true;
- }
- }
-
- return false;
-}
-
-static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
- u16_t app_idx, u8_t cred_flag, u8_t ttl, u8_t period,
- u8_t retransmit, bool store)
+static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr,
+ uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period,
+ uint8_t retransmit, bool store)
{
if (!model->pub) {
return STATUS_NVAL_PUB_PARAM;
@@ -227,10 +211,20 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
return STATUS_SUCCESS;
}
- if (!bt_mesh_app_key_find(app_idx)) {
+ if (!bt_mesh_app_key_exists(app_idx)) {
return STATUS_INVALID_APPKEY;
}
+#if CONFIG_BT_MESH_LABEL_COUNT > 0
+ if (BT_MESH_ADDR_IS_VIRTUAL(model->pub->addr)) {
+ uint8_t *uuid = bt_mesh_va_label_get(model->pub->addr);
+
+ if (uuid) {
+ bt_mesh_va_del(uuid, NULL);
+ }
+ }
+#endif
+
model->pub->addr = pub_addr;
model->pub->key = app_idx;
model->pub->cred = cred_flag;
@@ -239,12 +233,12 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
model->pub->retransmit = retransmit;
if (model->pub->update) {
- s32_t period_ms;
+ int32_t period_ms;
period_ms = bt_mesh_model_pub_period_get(model);
BT_DBG("period %u ms", (unsigned) period_ms);
- if (period_ms) {
+ if (period_ms > 0) {
k_delayed_work_submit(&model->pub->timer, period_ms);
} else {
k_delayed_work_cancel(&model->pub->timer);
@@ -258,13 +252,13 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr,
return STATUS_SUCCESS;
}
-u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx)
+uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx)
{
int i;
BT_DBG("model %p key_idx 0x%03x", model, key_idx);
- if (!app_key_is_valid(key_idx)) {
+ if (!bt_mesh_app_key_exists(key_idx)) {
return STATUS_INVALID_APPKEY;
}
@@ -290,13 +284,13 @@ u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx)
return STATUS_INSUFF_RESOURCES;
}
-u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store)
+uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store)
{
int i;
BT_DBG("model %p key_idx 0x%03x store %u", model, key_idx, store);
- if (!app_key_is_valid(key_idx)) {
+ if (!bt_mesh_app_key_exists(key_idx)) {
return STATUS_INVALID_APPKEY;
}
@@ -320,240 +314,88 @@ u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store)
return STATUS_SUCCESS;
}
-struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx)
+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)
{
- int i;
+ struct os_mbuf *msg = NET_BUF_SIMPLE(
+ BT_MESH_MODEL_BUF_LEN(OP_APP_KEY_STATUS, 4));
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
+ bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
+ net_buf_simple_add_u8(msg, status);
+ key_idx_pack(msg, net_idx, app_idx);
- if (key->net_idx == BT_MESH_KEY_UNUSED) {
- return key;
- }
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ BT_ERR("Unable to send App Key Status response");
}
- return NULL;
-}
-
-static u8_t app_key_set(u16_t net_idx, u16_t app_idx, const u8_t val[16],
- bool update)
-{
- struct bt_mesh_app_keys *keys;
- struct bt_mesh_app_key *key;
- struct bt_mesh_subnet *sub;
-
- BT_DBG("net_idx 0x%04x app_idx %04x update %u val %s",
- net_idx, app_idx, update, bt_hex(val, 16));
-
- sub = bt_mesh_subnet_get(net_idx);
- if (!sub) {
- return STATUS_INVALID_NETKEY;
- }
-
- key = bt_mesh_app_key_find(app_idx);
- if (update) {
- if (!key) {
- return STATUS_INVALID_APPKEY;
- }
-
- if (key->net_idx != net_idx) {
- return STATUS_INVALID_BINDING;
- }
-
- keys = &key->keys[1];
-
- /* The AppKey Update message shall generate an error when node
- * is in normal operation, Phase 2, or Phase 3 or in Phase 1
- * when the AppKey Update message on a valid AppKeyIndex when
- * the AppKey value is different.
- */
- if (sub->kr_phase != BT_MESH_KR_PHASE_1) {
- return STATUS_CANNOT_UPDATE;
- }
-
- if (key->updated) {
- if (memcmp(keys->val, val, 16)) {
- return STATUS_CANNOT_UPDATE;
- } else {
- return STATUS_SUCCESS;
- }
- }
-
- key->updated = true;
- } else {
- if (key) {
- if (key->net_idx == net_idx &&
- !memcmp(key->keys[0].val, val, 16)) {
- return STATUS_SUCCESS;
- }
-
- if (key->net_idx == net_idx) {
- return STATUS_IDX_ALREADY_STORED;
- } else {
- return STATUS_INVALID_NETKEY;
- }
- }
-
- key = bt_mesh_app_key_alloc(app_idx);
- if (!key) {
- return STATUS_INSUFF_RESOURCES;
- }
-
- keys = &key->keys[0];
- }
-
- if (bt_mesh_app_id(val, &keys->id)) {
- if (update) {
- key->updated = false;
- }
-
- return STATUS_STORAGE_FAIL;
- }
-
- BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, keys->id);
-
- key->net_idx = net_idx;
- key->app_idx = app_idx;
- memcpy(keys->val, val, 16);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing AppKey persistently");
- bt_mesh_store_app_key(key);
- }
-
- return STATUS_SUCCESS;
+ os_mbuf_free_chain(msg);
}
static void app_key_add(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_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
+ status = bt_mesh_app_key_add(key_app_idx, key_net_idx, buf->om_data);
- status = app_key_set(key_net_idx, key_app_idx, buf->om_data, false);
- BT_DBG("status 0x%02x", status);
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
-
- os_mbuf_free_chain(msg);
+ send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
static void app_key_update(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_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
-
- status = app_key_set(key_net_idx, key_app_idx, buf->om_data, true);
+ status = bt_mesh_app_key_update(key_app_idx, key_net_idx, buf->om_data);
BT_DBG("status 0x%02x", status);
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
-
- os_mbuf_free_chain(msg);
+ send_app_key_status(model, ctx, status, key_app_idx, key_net_idx);
}
-struct unbind_data {
- u16_t app_idx;
- bool store;
-};
-
-static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
- bool vnd, bool primary, void *user_data)
+static void mod_app_key_del(struct bt_mesh_model *mod,
+ struct bt_mesh_elem *elem, bool vnd, bool primary,
+ void *user_data)
{
- struct unbind_data *data = user_data;
+ uint16_t *app_idx = user_data;
- mod_unbind(mod, data->app_idx, data->store);
+ mod_unbind(mod, *app_idx, true);
}
-void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store)
+static void app_key_evt(uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt)
{
- struct unbind_data data = { .app_idx = key->app_idx, .store = store };
-
- BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store);
-
- bt_mesh_model_foreach(_mod_unbind, &data);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_clear_app_key(key);
+ if (evt == BT_MESH_KEY_DELETED) {
+ bt_mesh_model_foreach(&mod_app_key_del, &app_idx);
}
-
- key->net_idx = BT_MESH_KEY_UNUSED;
- memset(key->keys, 0, sizeof(key->keys));
}
static void app_key_del(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_STATUS, 4);
- u16_t key_net_idx, key_app_idx;
- struct bt_mesh_app_key *key;
- u8_t status;
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
key_idx_unpack(buf, &key_net_idx, &key_app_idx);
BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx);
- if (!bt_mesh_subnet_get(key_net_idx)) {
- status = STATUS_INVALID_NETKEY;
- goto send_status;
- }
+ status = bt_mesh_app_key_del(key_app_idx, key_net_idx);
- key = bt_mesh_app_key_find(key_app_idx);
- if (!key) {
- /* Treat as success since the client might have missed a
- * previous response and is resending the request.
- */
- status = STATUS_SUCCESS;
- goto send_status;
- }
-
- if (key->net_idx != key_net_idx) {
- status = STATUS_INVALID_BINDING;
- goto send_status;
- }
-
- bt_mesh_app_key_del(key, true);
- status = STATUS_SUCCESS;
-
-send_status:
- bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS);
-
- net_buf_simple_add_u8(msg, status);
-
- key_idx_pack(msg, key_net_idx, key_app_idx);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send App Key Status response");
- }
-
- os_mbuf_free_chain(msg);
+ 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 */
@@ -566,8 +408,11 @@ static void app_key_get(struct bt_mesh_model *model,
struct os_mbuf *msg =
BT_MESH_MODEL_BUF(OP_APP_KEY_LIST,
3 + IDX_LEN(CONFIG_BT_MESH_APP_KEY_COUNT));
- u16_t get_idx, i, prev;
- u8_t status;
+ uint16_t app_idx[CONFIG_BT_MESH_APP_KEY_COUNT];
+ uint16_t get_idx;
+ uint8_t status;
+ ssize_t count;
+ int i;
get_idx = net_buf_simple_pull_le16(buf);
if (get_idx > 0xfff) {
@@ -579,7 +424,7 @@ static void app_key_get(struct bt_mesh_model *model,
bt_mesh_model_msg_init(msg, OP_APP_KEY_LIST);
- if (!bt_mesh_subnet_get(get_idx)) {
+ if (!bt_mesh_subnet_exists(get_idx)) {
status = STATUS_INVALID_NETKEY;
} else {
status = STATUS_SUCCESS;
@@ -592,25 +437,17 @@ static void app_key_get(struct bt_mesh_model *model,
goto send_status;
}
- prev = BT_MESH_KEY_UNUSED;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != get_idx) {
- continue;
- }
-
- if (prev == BT_MESH_KEY_UNUSED) {
- prev = key->app_idx;
- continue;
- }
-
- key_idx_pack(msg, prev, key->app_idx);
- prev = BT_MESH_KEY_UNUSED;
+ count = bt_mesh_app_keys_get(get_idx, app_idx, ARRAY_SIZE(app_idx), 0);
+ if (count < 0 || count > ARRAY_SIZE(app_idx)) {
+ count = ARRAY_SIZE(app_idx);
}
- if (prev != BT_MESH_KEY_UNUSED) {
- net_buf_simple_add_le16(msg, prev);
+ for (i = 0; i < count - 1; i += 2) {
+ key_idx_pack(msg, app_idx[i], app_idx[i + 1]);
+ }
+
+ if (i < count) {
+ net_buf_simple_add_le16(msg, app_idx[i]);
}
send_status:
@@ -633,7 +470,7 @@ static void beacon_get(struct bt_mesh_model *model,
bt_hex(buf->om_data, buf->om_len));
bt_mesh_model_msg_init(msg, OP_BEACON_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_beacon_get());
+ net_buf_simple_add_u8(msg, bt_mesh_beacon_enabled());
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Config Beacon Status response");
@@ -646,35 +483,20 @@ static void beacon_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_BEACON_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
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 (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) {
- if (buf->om_data[0] != cfg->beacon) {
- cfg->beacon = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
-
- if (cfg->beacon) {
- bt_mesh_beacon_enable();
- } else {
- bt_mesh_beacon_disable();
- }
- }
- } else {
+ if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) {
BT_WARN("Invalid Config Beacon value 0x%02x", buf->om_data[0]);
goto done;
}
+ bt_mesh_beacon_set(buf->om_data[0]);
+
bt_mesh_model_msg_init(msg, OP_BEACON_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_beacon_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Config Beacon Status response");
@@ -711,29 +533,20 @@ static void default_ttl_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
+ 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,
bt_hex(buf->om_data, buf->om_len));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] <= BT_MESH_TTL_MAX && buf->om_data[0] != 0x01) {
- if (cfg->default_ttl != buf->om_data[0]) {
- cfg->default_ttl = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
- } else {
+ err = bt_mesh_default_ttl_set(buf->om_data[0]);
+ if (err) {
BT_WARN("Prohibited Default TTL value 0x%02x", buf->om_data[0]);
goto done;
}
bt_mesh_model_msg_init(msg, OP_DEFAULT_TTL_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_default_ttl_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Default TTL Status response");
@@ -774,8 +587,6 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
-
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));
@@ -785,35 +596,8 @@ static void gatt_proxy_set(struct bt_mesh_model *model,
return;
}
- if (!(MYNEWT_VAL(BLE_MESH_GATT_PROXY)) ||
- bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_NOT_SUPPORTED) {
- goto send_status;
- }
+ (void)bt_mesh_gatt_proxy_set(buf->om_data[0]);
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- goto send_status;
- }
-
- BT_DBG("GATT Proxy 0x%02x -> 0x%02x", cfg->gatt_proxy, buf->om_data[0]);
-
- if (cfg->gatt_proxy == buf->om_data[0]) {
- goto send_status;
- }
-
- cfg->gatt_proxy = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
-
- bt_mesh_adv_update();
-
- if (cfg->hb_pub.feat & BT_MESH_FEAT_PROXY) {
- bt_mesh_heartbeat_send();
- }
-
-send_status:
send_gatt_proxy_status(model, ctx);
}
@@ -843,7 +627,6 @@ static void net_transmit_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
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,
@@ -853,18 +636,10 @@ static void net_transmit_set(struct bt_mesh_model *model,
BT_MESH_TRANSMIT_COUNT(buf->om_data[0]),
BT_MESH_TRANSMIT_INT(buf->om_data[0]));
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else {
- cfg->net_transmit = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
+ bt_mesh_net_transmit_set(buf->om_data[0]);
bt_mesh_model_msg_init(msg, OP_NET_TRANSMIT_STATUS);
- net_buf_simple_add_u8(msg, bt_mesh_net_transmit_get());
+ net_buf_simple_add_u8(msg, buf->om_data[0]);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Network Transmit Status");
@@ -900,43 +675,18 @@ static void relay_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_STATUS, 2);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
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 (!cfg) {
- BT_WARN("No Configuration Server context available");
- } else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) {
- bool change;
-
- if (cfg->relay == BT_MESH_RELAY_NOT_SUPPORTED) {
- change = false;
- } else {
- change = (cfg->relay != buf->om_data[0]);
- cfg->relay = buf->om_data[0];
- cfg->relay_retransmit = buf->om_data[1];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
- }
-
- BT_DBG("Relay 0x%02x (%s) xmit 0x%02x (count %u interval %u)",
- cfg->relay, change ? "changed" : "not changed",
- cfg->relay_retransmit,
- BT_MESH_TRANSMIT_COUNT(cfg->relay_retransmit),
- BT_MESH_TRANSMIT_INT(cfg->relay_retransmit));
-
- if ((cfg->hb_pub.feat & BT_MESH_FEAT_RELAY) && change) {
- bt_mesh_heartbeat_send();
- }
- } else {
+ if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) {
BT_WARN("Invalid Relay value 0x%02x", buf->om_data[0]);
goto done;
}
+ (void)bt_mesh_relay_set(buf->om_data[0], buf->om_data[1]);
+
bt_mesh_model_msg_init(msg, OP_RELAY_STATUS);
net_buf_simple_add_u8(msg, bt_mesh_relay_get());
net_buf_simple_add_u8(msg, bt_mesh_relay_retransmit_get());
@@ -952,9 +702,9 @@ done:
static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
struct bt_mesh_msg_ctx *ctx,
- u16_t elem_addr, u16_t pub_addr,
+ uint16_t elem_addr, uint16_t pub_addr,
bool vnd, struct bt_mesh_model *mod,
- u8_t status, u8_t *mod_id)
+ uint8_t status, uint8_t *mod_id)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_STATUS, 14);
@@ -966,11 +716,11 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod,
if (status != STATUS_SUCCESS) {
memset(net_buf_simple_add(msg, 7), 0, 7);
} else {
- u16_t idx_cred;
+ uint16_t idx_cred;
net_buf_simple_add_le16(msg, pub_addr);
- idx_cred = mod->pub->key | (u16_t)mod->pub->cred << 12;
+ idx_cred = mod->pub->key | (uint16_t)mod->pub->cred << 12;
net_buf_simple_add_le16(msg, idx_cred);
net_buf_simple_add_u8(msg, mod->pub->ttl);
net_buf_simple_add_u8(msg, mod->pub->period);
@@ -994,10 +744,10 @@ static void mod_pub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, pub_addr = 0;
+ uint16_t elem_addr, pub_addr = 0;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1041,11 +791,11 @@ static void mod_pub_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t retransmit, status, pub_ttl, pub_period, cred_flag;
- u16_t elem_addr, pub_addr, pub_app_idx;
+ uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
+ uint16_t elem_addr, pub_addr, pub_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
+ uint8_t *mod_id;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1099,102 +849,9 @@ send_status:
status, mod_id);
}
-struct label *get_label(u16_t index)
-{
- if (index >= ARRAY_SIZE(labels)) {
- return NULL;
- }
-
- return &labels[index];
-}
-
-#if CONFIG_BT_MESH_LABEL_COUNT > 0
-static inline void va_store(struct label *store)
-{
- atomic_set_bit(store->flags, BT_MESH_VA_CHANGED);
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_label();
- }
-}
-
-static struct label *va_find(const u8_t *label_uuid,
- struct label **free_slot)
-{
- struct label *match = NULL;
- int i;
-
- if (free_slot != NULL) {
- *free_slot = NULL;
- }
-
- for (i = 0; i < ARRAY_SIZE(labels); i++) {
- if (labels[i].ref == 0) {
- if (free_slot != NULL) {
- *free_slot = &labels[i];
- }
- continue;
- }
-
- if (!memcmp(labels[i].uuid, label_uuid, 16)) {
- match = &labels[i];
- }
- }
-
- return match;
-}
-
-static u8_t va_add(u8_t *label_uuid, u16_t *addr)
-{
- struct label *update, *free_slot = NULL;
-
- update = va_find(label_uuid, &free_slot);
- if (update) {
- update->ref++;
- va_store(update);
- return 0;
- }
-
- if (!free_slot) {
- return STATUS_INSUFF_RESOURCES;
- }
-
- if (bt_mesh_virtual_addr(label_uuid, addr) < 0) {
- return STATUS_UNSPECIFIED;
- }
-
- free_slot->ref = 1;
- free_slot->addr = *addr;
- memcpy(free_slot->uuid, label_uuid, 16);
- va_store(free_slot);
-
- return STATUS_SUCCESS;
-}
-
-static u8_t va_del(u8_t *label_uuid, u16_t *addr)
-{
- struct label *update;
-
- update = va_find(label_uuid, NULL);
- if (update) {
- update->ref--;
-
- if (addr) {
- *addr = update->addr;
- }
-
- va_store(update);
- }
-
- if (addr) {
- *addr = BT_MESH_ADDR_UNASSIGNED;
- }
-
- return STATUS_CANNOT_REMOVE;
-}
-
static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
{
- u8_t *label_uuid;
+ uint8_t *label_uuid;
size_t clear_count;
int i;
@@ -1209,13 +866,13 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
continue;
}
- label_uuid = bt_mesh_label_uuid_get(mod->groups[i]);
+ label_uuid = bt_mesh_va_label_get(mod->groups[i]);
mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
clear_count++;
if (label_uuid) {
- va_del(label_uuid, NULL);
+ bt_mesh_va_del(label_uuid, NULL);
} else {
BT_ERR("Label UUID not found");
}
@@ -1228,12 +885,12 @@ static void mod_pub_va_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t retransmit, status, pub_ttl, pub_period, cred_flag;
- u16_t elem_addr, pub_addr, pub_app_idx;
+ uint8_t retransmit, status, pub_ttl, pub_period, cred_flag;
+ uint16_t elem_addr, pub_addr, pub_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1279,85 +936,25 @@ static void mod_pub_va_set(struct bt_mesh_model *model,
goto send_status;
}
- status = va_add(label_uuid, &pub_addr);
- if (status == STATUS_SUCCESS) {
- status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag,
- pub_ttl, pub_period, retransmit, true);
+ status = bt_mesh_va_add(label_uuid, &pub_addr);
+ if (status != STATUS_SUCCESS) {
+ goto send_status;
+ }
+
+ status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl,
+ pub_period, retransmit, true);
+ if (status != STATUS_SUCCESS) {
+ bt_mesh_va_del(label_uuid, NULL);
}
send_status:
send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
status, mod_id);
}
-#else
-static size_t mod_sub_list_clear(struct bt_mesh_model *mod)
-{
- size_t clear_count;
- int i;
-
- /* Unref stored labels related to this model */
- for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) {
- if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) {
- mod->groups[i] = BT_MESH_ADDR_UNASSIGNED;
- clear_count++;
- }
- }
-
- return clear_count;
-}
-
-static void mod_pub_va_set(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- u8_t *mod_id, status;
- struct bt_mesh_model *mod;
- struct bt_mesh_elem *elem;
- u16_t elem_addr, pub_addr = 0;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
- mod_id = net_buf_simple_pull(buf, 4);
-
- BT_DBG("elem_addr 0x%04x", elem_addr);
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- mod = NULL;
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- mod = get_model(elem, buf, &vnd);
- if (!mod) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- if (!mod->pub) {
- status = STATUS_NVAL_PUB_PARAM;
- goto send_status;
- }
-
- pub_addr = mod->pub->addr;
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod,
- status, mod_id);
-}
-#endif /* MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 */
static void send_mod_sub_status(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx, u8_t status,
- u16_t elem_addr, u16_t sub_addr, u8_t *mod_id,
+ 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);
@@ -1388,12 +985,12 @@ static void mod_sub_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u8_t status;
- u16_t *entry;
+ uint8_t *mod_id;
+ uint8_t status;
+ uint16_t *entry;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1461,12 +1058,12 @@ static void mod_sub_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u16_t *match;
- u8_t status;
+ uint8_t *mod_id;
+ uint16_t *match;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1524,7 +1121,7 @@ send_status:
}
static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *user_data)
+ uint32_t depth, void *user_data)
{
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups));
@@ -1539,11 +1136,11 @@ static void mod_sub_overwrite(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id;
- u8_t status;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1607,9 +1204,9 @@ static void mod_sub_del_all(struct bt_mesh_model *model,
{
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
+ uint16_t elem_addr;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1651,12 +1248,12 @@ send_status:
}
struct mod_sub_list_ctx {
- u16_t elem_idx;
+ uint16_t elem_idx;
struct os_mbuf *msg;
};
static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod,
- u32_t depth, void *ctx)
+ uint32_t depth, void *ctx)
{
struct mod_sub_list_ctx *visit = ctx;
int count = 0;
@@ -1695,7 +1292,7 @@ static void mod_sub_get(struct bt_mesh_model *model,
struct mod_sub_list_ctx visit_ctx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u16_t addr, id;
+ uint16_t addr, id;
addr = net_buf_simple_pull_le16(buf);
if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
@@ -1750,9 +1347,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
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;
- u16_t company, addr, id;
+ uint16_t company, addr, id;
addr = net_buf_simple_pull_le16(buf);
if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
@@ -1791,8 +1389,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model,
net_buf_simple_add_le16(msg, company);
net_buf_simple_add_le16(msg, id);
+ 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,
- msg);
+ &visit_ctx);
send_list:
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -1804,18 +1404,17 @@ done:
}
-#if MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0
static void mod_sub_va_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u16_t *entry;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint16_t *entry;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1845,7 +1444,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
goto send_status;
}
- status = va_add(label_uuid, &sub_addr);
+ status = bt_mesh_va_add(label_uuid, &sub_addr);
if (status != STATUS_SUCCESS) {
goto send_status;
}
@@ -1853,6 +1452,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
if (bt_mesh_model_find_group(&mod, sub_addr)) {
/* Tried to add existing subscription */
status = STATUS_SUCCESS;
+ bt_mesh_va_del(label_uuid, NULL);
goto send_status;
}
@@ -1860,6 +1460,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model,
entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED);
if (!entry) {
status = STATUS_INSUFF_RESOURCES;
+ bt_mesh_va_del(label_uuid, NULL);
goto send_status;
}
@@ -1884,13 +1485,13 @@ static void mod_sub_va_del(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr;
+ uint16_t elem_addr, sub_addr;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u16_t *match;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint16_t *match;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1921,7 +1522,7 @@ static void mod_sub_va_del(struct bt_mesh_model *model,
goto send_status;
}
- status = va_del(label_uuid, &sub_addr);
+ status = bt_mesh_va_del(label_uuid, &sub_addr);
if (sub_addr == BT_MESH_ADDR_UNASSIGNED) {
goto send_status;
}
@@ -1952,12 +1553,12 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
+ uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *label_uuid;
- u8_t *mod_id;
- u8_t status;
+ uint8_t *label_uuid;
+ uint8_t *mod_id;
+ uint8_t status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -1987,11 +1588,10 @@ static void mod_sub_va_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);
-
- status = va_add(label_uuid, &sub_addr);
+ 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);
mod->groups[0] = sub_addr;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
@@ -2010,131 +1610,10 @@ send_status:
send_mod_sub_status(model, ctx, status, elem_addr, sub_addr,
mod_id, vnd);
}
-#else
-static void mod_sub_va_add(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;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- mod = NULL;
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- mod = get_model(elem, buf, &vnd);
- if (!mod) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-
-static void mod_sub_va_del(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 16);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- if (!get_model(elem, buf, &vnd)) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-
-static void mod_sub_va_overwrite(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_elem *elem;
- u16_t elem_addr;
- u8_t *mod_id;
- u8_t status;
- bool vnd;
-
- elem_addr = net_buf_simple_pull_le16(buf);
- if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) {
- BT_WARN("Prohibited element address");
- return;
- }
-
- net_buf_simple_pull(buf, 18);
-
- mod_id = buf->om_data;
-
- elem = bt_mesh_elem_find(elem_addr);
- if (!elem) {
- vnd = (buf->om_len == 4);
- status = STATUS_INVALID_ADDRESS;
- goto send_status;
- }
-
- if (!get_model(elem, buf, &vnd)) {
- status = STATUS_INVALID_MODEL;
- goto send_status;
- }
-
- status = STATUS_INSUFF_RESOURCES;
-
-send_status:
- send_mod_sub_status(model, ctx, status, elem_addr,
- BT_MESH_ADDR_UNASSIGNED, mod_id, vnd);
-}
-#endif /* MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 */
static void send_net_key_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
- u16_t idx, u8_t status)
+ uint16_t idx, uint8_t status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_STATUS, 3);
@@ -2154,9 +1633,8 @@ static void net_key_add(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
- int err;
+ uint8_t status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2166,72 +1644,16 @@ static void net_key_add(struct bt_mesh_model *model,
BT_DBG("idx 0x%04x", idx);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
- sub = &bt_mesh.sub[i];
- break;
- }
- }
-
- if (!sub) {
- send_net_key_status(model, ctx, idx,
- STATUS_INSUFF_RESOURCES);
- return;
- }
- }
-
- /* Check for already existing subnet */
- if (sub->net_idx == idx) {
- u8_t status;
-
- if (memcmp(buf->om_data, sub->keys[0].net, 16)) {
- status = STATUS_IDX_ALREADY_STORED;
- } else {
- status = STATUS_SUCCESS;
- }
-
- send_net_key_status(model, ctx, idx, status);
- return;
- }
-
- err = bt_mesh_net_keys_create(&sub->keys[0], buf->om_data);
- if (err) {
- send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
- return;
- }
-
- sub->net_idx = idx;
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing NetKey persistently");
- bt_mesh_store_subnet(sub);
- }
-
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
-
- if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- bt_mesh_proxy_beacon_send(sub);
- bt_mesh_adv_update();
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
+ status = bt_mesh_subnet_add(idx, buf->om_data);
+ 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)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
- int err;
+ uint8_t status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2239,80 +1661,16 @@ static void net_key_update(struct bt_mesh_model *model,
return;
}
- BT_DBG("idx 0x%04x", idx);
+ status = bt_mesh_subnet_update(idx, buf->om_data);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_net_key_status(model, ctx, idx, STATUS_INVALID_NETKEY);
- return;
- }
-
- /* The node shall successfully process a NetKey Update message on a
- * valid NetKeyIndex when the NetKey value is different and the Key
- * Refresh procedure has not been started, or when the NetKey value is
- * the same in Phase 1. The NetKey Update message shall generate an
- * error when the node is in Phase 2, or Phase 3.
- */
- switch (sub->kr_phase) {
- case BT_MESH_KR_NORMAL:
- if (!memcmp(buf->om_data, sub->keys[0].net, 16)) {
- return;
- }
- break;
- case BT_MESH_KR_PHASE_1:
- if (!memcmp(buf->om_data, sub->keys[1].net, 16)) {
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
- return;
- }
- /* fall through */
- case BT_MESH_KR_PHASE_2:
- case BT_MESH_KR_PHASE_3:
- send_net_key_status(model, ctx, idx, STATUS_CANNOT_UPDATE);
- return;
- }
-
- err = bt_mesh_net_keys_create(&sub->keys[1], buf->om_data);
- if (!err && ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND)))) {
- err = friend_cred_update(sub);
- }
-
- if (err) {
- send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED);
- return;
- }
-
- sub->kr_phase = BT_MESH_KR_PHASE_1;
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing NetKey persistently");
- bt_mesh_store_subnet(sub);
- }
-
- bt_mesh_net_beacon_update(sub);
-
- send_net_key_status(model, ctx, idx, STATUS_SUCCESS);
-}
-
-static void hb_pub_disable(struct bt_mesh_cfg_srv *cfg)
-{
- BT_DBG("");
-
- cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_pub.count = 0;
- cfg->hb_pub.ttl = 0;
- cfg->hb_pub.period = 0;
-
- k_delayed_work_cancel(&cfg->hb_pub.timer);
+ 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)
{
- struct bt_mesh_subnet *sub;
- u16_t del_idx;
- u8_t status;
+ uint16_t del_idx;
del_idx = net_buf_simple_pull_le16(buf);
if (del_idx > 0xfff) {
@@ -2322,28 +1680,18 @@ static void net_key_del(struct bt_mesh_model *model,
BT_DBG("idx 0x%04x", del_idx);
- sub = bt_mesh_subnet_get(del_idx);
- if (!sub) {
- /* This could be a retry of a previous attempt that had its
- * response lost, so pretend that it was a success.
- */
- status = STATUS_SUCCESS;
- goto send_status;
- }
-
/* The key that the message was encrypted with cannot be removed.
* The NetKey List must contain a minimum of one NetKey.
*/
if (ctx->net_idx == del_idx) {
- status = STATUS_CANNOT_REMOVE;
- goto send_status;
+ send_net_key_status(model, ctx, del_idx,
+ STATUS_CANNOT_REMOVE);
+ return;
}
- bt_mesh_subnet_del(sub, true);
- status = STATUS_SUCCESS;
+ bt_mesh_subnet_del(del_idx);
-send_status:
- send_net_key_status(model, ctx, del_idx, status);
+ send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS);
}
static void net_key_get(struct bt_mesh_model *model,
@@ -2353,29 +1701,23 @@ static void net_key_get(struct bt_mesh_model *model,
struct os_mbuf *msg =
BT_MESH_MODEL_BUF(OP_NET_KEY_LIST,
IDX_LEN(CONFIG_BT_MESH_SUBNET_COUNT));
- u16_t prev, i;
+ uint16_t net_idx[CONFIG_BT_MESH_SUBNET_COUNT];
+ ssize_t count;
+ int i;
bt_mesh_model_msg_init(msg, OP_NET_KEY_LIST);
- prev = BT_MESH_KEY_UNUSED;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (prev == BT_MESH_KEY_UNUSED) {
- prev = sub->net_idx;
- continue;
- }
-
- key_idx_pack(msg, prev, sub->net_idx);
- prev = BT_MESH_KEY_UNUSED;
+ count = bt_mesh_subnets_get(net_idx, ARRAY_SIZE(net_idx), 0);
+ if (count < 0 || count > ARRAY_SIZE(net_idx)) {
+ count = ARRAY_SIZE(net_idx);
}
- if (prev != BT_MESH_KEY_UNUSED) {
- net_buf_simple_add_le16(msg, prev);
+ for (i = 0; i < count - 1; i += 2) {
+ key_idx_pack(msg, net_idx[i], net_idx[i + 1]);
+ }
+
+ if (i < count) {
+ net_buf_simple_add_le16(msg, net_idx[i]);
}
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -2385,14 +1727,32 @@ static void net_key_get(struct bt_mesh_model *model,
os_mbuf_free_chain(msg);
}
+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)
+{
+ struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
+
+ bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
+ net_buf_simple_add_u8(msg, status);
+ net_buf_simple_add_le16(msg, net_idx);
+ net_buf_simple_add_u8(msg, node_id);
+
+ if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
+ BT_ERR("Unable to send Node Identity Status");
+ }
+
+ os_mbuf_free_chain(msg);
+}
+
static void node_identity_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_NODE_IDENTITY_STATUS, 4);
- struct bt_mesh_subnet *sub;
- u8_t node_id;
- u16_t idx;
+ enum bt_mesh_feat_state node_id;
+ uint8_t status;
+ uint16_t idx;
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,
@@ -2401,39 +1761,20 @@ 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);
- goto done;
+ return;
}
- bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
+ status = bt_mesh_subnet_node_id_get(idx, &node_id);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- net_buf_simple_add_u8(msg, STATUS_INVALID_NETKEY);
- node_id = 0x00;
- } else {
- net_buf_simple_add_u8(msg, STATUS_SUCCESS);
- node_id = sub->node_id;
- }
-
- net_buf_simple_add_le16(msg, idx);
- net_buf_simple_add_u8(msg, node_id);
-
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send Node Identity Status");
- }
-
-done:
- os_mbuf_free_chain(msg);
+ 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)
{
- struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4);
- struct bt_mesh_subnet *sub;
- u8_t node_id;
- u16_t idx;
+ uint8_t node_id, status;
+ uint16_t idx;
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,
@@ -2442,51 +1783,36 @@ 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);
- goto done;
+ return;
}
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);
- goto done;
+ return;
}
- bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS);
-
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- net_buf_simple_add_u8(msg, STATUS_INVALID_NETKEY);
- net_buf_simple_add_le16(msg, idx);
- net_buf_simple_add_u8(msg, node_id);
- } else {
- net_buf_simple_add_u8(msg, STATUS_SUCCESS);
- net_buf_simple_add_le16(msg, idx);
-
- if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) {
- if (node_id) {
- bt_mesh_proxy_identity_start(sub);
- } else {
- bt_mesh_proxy_identity_stop(sub);
- }
- bt_mesh_adv_update();
- }
-
- net_buf_simple_add_u8(msg, sub->node_id);
+ 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;
}
- if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
- BT_ERR("Unable to send Node Identity Status");
+ 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;
}
-done:
- os_mbuf_free_chain(msg);
-
+ send_node_id_status(model, ctx, status, idx, node_id);
}
static void create_mod_app_status(struct os_mbuf *msg,
struct bt_mesh_model *mod, bool vnd,
- u16_t elem_addr, u16_t app_idx,
- u8_t status, u8_t *mod_id)
+ uint16_t elem_addr, uint16_t app_idx,
+ uint8_t status, uint8_t *mod_id)
{
bt_mesh_model_msg_init(msg, OP_MOD_APP_STATUS);
@@ -2506,10 +1832,10 @@ static void mod_app_bind(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9);
- u16_t elem_addr, key_app_idx;
+ uint16_t elem_addr, key_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2567,10 +1893,10 @@ static void mod_app_unbind(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9);
- u16_t elem_addr, key_app_idx;
+ uint16_t elem_addr, key_app_idx;
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
+ uint8_t *mod_id, status;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2628,8 +1954,8 @@ static void mod_app_get(struct bt_mesh_model *model,
struct bt_mesh_model *mod;
struct bt_mesh_elem *elem;
- u8_t *mod_id, status;
- u16_t elem_addr;
+ uint8_t *mod_id, status;
+ uint16_t elem_addr;
bool vnd;
elem_addr = net_buf_simple_pull_le16(buf);
@@ -2696,6 +2022,8 @@ 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};
+
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET_STATUS, 0);
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -2712,7 +2040,15 @@ static void node_reset(struct bt_mesh_model *model,
BT_ERR("Unable to send Node Reset Status");
}
- bt_mesh_reset();
+ 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);
}
@@ -2720,10 +2056,9 @@ static void 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);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
bt_mesh_model_msg_init(msg, OP_FRIEND_STATUS);
- net_buf_simple_add_u8(msg, cfg->frnd);
+ net_buf_simple_add_u8(msg, bt_mesh_friend_get());
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Friend Status");
@@ -2746,8 +2081,6 @@ static void friend_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
-
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));
@@ -2757,34 +2090,8 @@ static void friend_set(struct bt_mesh_model *model,
return;
}
- if (!cfg) {
- BT_WARN("No Configuration Server context available");
- goto send_status;
- }
+ (void)bt_mesh_friend_set(buf->om_data[0]);
- BT_DBG("Friend 0x%02x -> 0x%02x", cfg->frnd, buf->om_data[0]);
-
- if (cfg->frnd == buf->om_data[0]) {
- goto send_status;
- }
-
- if (MYNEWT_VAL(BLE_MESH_FRIEND)) {
- cfg->frnd = buf->om_data[0];
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_cfg();
- }
-
- if (cfg->frnd == BT_MESH_FRIEND_DISABLED) {
- bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
- }
- }
-
- if (cfg->hb_pub.feat & BT_MESH_FEAT_FRIEND) {
- bt_mesh_heartbeat_send();
- }
-
-send_status:
send_friend_status(model, ctx);
}
@@ -2794,8 +2101,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;
- u16_t lpn_addr;
- s32_t timeout;
+ uint16_t lpn_addr;
+ int32_t timeout;
lpn_addr = net_buf_simple_pull_le16(buf);
@@ -2825,9 +2132,7 @@ static void lpn_timeout_get(struct bt_mesh_model *model,
timeout = k_delayed_work_remaining_get(&frnd->timer) / 100;
send_rsp:
- net_buf_simple_add_u8(msg, timeout);
- net_buf_simple_add_u8(msg, timeout >> 8);
- net_buf_simple_add_u8(msg, timeout >> 16);
+ net_buf_simple_add_le24(msg, timeout);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send LPN PollTimeout Status");
@@ -2839,7 +2144,7 @@ done:
static void send_krp_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
- u16_t idx, u8_t phase, u8_t status)
+ uint16_t idx, uint8_t phase, uint8_t status)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_STATUS, 4);
@@ -2859,8 +2164,8 @@ static void send_krp_status(struct bt_mesh_model *model,
static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- struct bt_mesh_subnet *sub;
- u16_t idx;
+ uint8_t kr_phase, status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
if (idx > 0xfff) {
@@ -2870,21 +2175,16 @@ static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
BT_DBG("idx 0x%04x", idx);
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
- } else {
- send_krp_status(model, ctx, idx, sub->kr_phase,
- STATUS_SUCCESS);
- }
+ status = bt_mesh_subnet_kr_phase_get(idx, &kr_phase);
+
+ 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)
{
- struct bt_mesh_subnet *sub;
- u8_t phase;
- u16_t idx;
+ uint8_t phase, status;
+ uint16_t idx;
idx = net_buf_simple_pull_le16(buf);
phase = net_buf_simple_pull_u8(buf);
@@ -2894,56 +2194,16 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
return;
}
- BT_DBG("idx 0x%04x transition 0x%02x", idx, phase);
-
- sub = bt_mesh_subnet_get(idx);
- if (!sub) {
- send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY);
+ status = bt_mesh_subnet_kr_phase_set(idx, &phase);
+ if (status == STATUS_CANNOT_UPDATE) {
+ BT_ERR("Invalid kr phase transition 0x%02x", phase);
return;
}
- BT_DBG("%u -> %u", sub->kr_phase, phase);
-
- if (phase < BT_MESH_KR_PHASE_2 || phase > BT_MESH_KR_PHASE_3 ||
- (sub->kr_phase == BT_MESH_KR_NORMAL &&
- phase == BT_MESH_KR_PHASE_2)) {
- BT_WARN("Prohibited transition %u -> %u", sub->kr_phase, phase);
- return;
- }
-
- if (sub->kr_phase == BT_MESH_KR_PHASE_1 &&
- phase == BT_MESH_KR_PHASE_2) {
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- sub->kr_flag = 1;
- bt_mesh_net_beacon_update(sub);
- } else if ((sub->kr_phase == BT_MESH_KR_PHASE_1 ||
- sub->kr_phase == BT_MESH_KR_PHASE_2) &&
- phase == BT_MESH_KR_PHASE_3) {
- bt_mesh_net_revoke_keys(sub);
- if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND))) {
- friend_cred_refresh(ctx->net_idx);
- }
- sub->kr_phase = BT_MESH_KR_NORMAL;
- sub->kr_flag = 0;
- bt_mesh_net_beacon_update(sub);
- }
-
- send_krp_status(model, ctx, idx, sub->kr_phase, STATUS_SUCCESS);
+ send_krp_status(model, ctx, idx, phase, status);
}
-static u8_t hb_log(u16_t val)
-{
- if (!val) {
- return 0x00;
- } else if (val == 0xffff) {
- return 0xff;
- } else {
- return 32 - __builtin_clz(val);
- }
-}
-
-static u8_t hb_pub_count_log(u16_t val)
+static uint8_t hb_pub_count_log(uint16_t val)
{
if (!val) {
return 0x00;
@@ -2956,32 +2216,20 @@ static u8_t hb_pub_count_log(u16_t val)
}
}
-static u16_t hb_pwr2(u8_t val, u8_t sub)
-{
- if (!val) {
- return 0x0000;
- } else if (val == 0xff || val == 0x11) {
- return 0xffff;
- } else {
- return (1 << (val - sub));
- }
-}
-
struct hb_pub_param {
- u16_t dst;
- u8_t count_log;
- u8_t period_log;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx;
+ uint16_t dst;
+ uint8_t count_log;
+ uint8_t period_log;
+ uint8_t ttl;
+ uint16_t feat;
+ uint16_t net_idx;
} __packed;
static void hb_pub_send_status(struct bt_mesh_model *model,
- struct bt_mesh_msg_ctx *ctx, u8_t status,
- struct hb_pub_param *orig_msg)
+ 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);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
@@ -2989,20 +2237,13 @@ static void hb_pub_send_status(struct bt_mesh_model *model,
net_buf_simple_add_u8(msg, status);
- if (orig_msg) {
- memcpy(net_buf_simple_add(msg, sizeof(*orig_msg)), orig_msg,
- sizeof(*orig_msg));
- goto send;
- }
+ net_buf_simple_add_le16(msg, pub->dst);
+ net_buf_simple_add_u8(msg, hb_pub_count_log(pub->count));
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(pub->period));
+ net_buf_simple_add_u8(msg, pub->ttl);
+ net_buf_simple_add_le16(msg, pub->feat);
+ net_buf_simple_add_le16(msg, pub->net_idx);
- net_buf_simple_add_le16(msg, cfg->hb_pub.dst);
- net_buf_simple_add_u8(msg, hb_pub_count_log(cfg->hb_pub.count));
- net_buf_simple_add_u8(msg, cfg->hb_pub.period);
- net_buf_simple_add_u8(msg, cfg->hb_pub.ttl);
- net_buf_simple_add_le16(msg, cfg->hb_pub.feat);
- net_buf_simple_add_le16(msg, cfg->hb_pub.net_idx);
-
-send:
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
BT_ERR("Unable to send Heartbeat Publication Status");
}
@@ -3014,9 +2255,13 @@ static void heartbeat_pub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
+ struct bt_mesh_hb_pub pub;
+
BT_DBG("src 0x%04x", ctx->addr);
- hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
+ bt_mesh_hb_pub_get(&pub);
+
+ hb_pub_send_status(model, ctx, STATUS_SUCCESS, &pub);
}
static void heartbeat_pub_set(struct bt_mesh_model *model,
@@ -3024,27 +2269,32 @@ static void heartbeat_pub_set(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct hb_pub_param *param = (void *)buf->om_data;
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t dst, feat, idx;
- u8_t status;
+ struct bt_mesh_hb_pub pub;
+ uint8_t status;
BT_DBG("src 0x%04x", ctx->addr);
- dst = sys_le16_to_cpu(param->dst);
+ pub.dst = sys_le16_to_cpu(param->dst);
+ pub.count = bt_mesh_hb_pwr2(param->count_log);
+ pub.period = bt_mesh_hb_pwr2(param->period_log);
+ pub.ttl = param->ttl;
+ pub.feat = sys_le16_to_cpu(param->feat);
+ pub.net_idx = sys_le16_to_cpu(param->net_idx);
+
/* All other address types but virtual are valid */
- if (BT_MESH_ADDR_IS_VIRTUAL(dst)) {
+ if (BT_MESH_ADDR_IS_VIRTUAL(pub.dst)) {
status = STATUS_INVALID_ADDRESS;
- goto failed;
+ goto rsp;
}
if (param->count_log > 0x11 && param->count_log != 0xff) {
status = STATUS_CANNOT_SET;
- goto failed;
+ goto rsp;
}
if (param->period_log > 0x10) {
status = STATUS_CANNOT_SET;
- goto failed;
+ goto rsp;
}
if (param->ttl > BT_MESH_TTL_MAX && param->ttl != BT_MESH_TTL_DEFAULT) {
@@ -3052,84 +2302,32 @@ static void heartbeat_pub_set(struct bt_mesh_model *model,
return;
}
- feat = sys_le16_to_cpu(param->feat);
-
- idx = sys_le16_to_cpu(param->net_idx);
- if (idx > 0xfff) {
- BT_ERR("Invalid NetKeyIndex 0x%04x", idx);
+ if (pub.net_idx > 0xfff) {
+ BT_ERR("Invalid NetKeyIndex 0x%04x", pub.net_idx);
return;
}
- if (!bt_mesh_subnet_get(idx)) {
- status = STATUS_INVALID_NETKEY;
- goto failed;
- }
-
- cfg->hb_pub.dst = dst;
- cfg->hb_pub.period = param->period_log;
- cfg->hb_pub.feat = feat & BT_MESH_FEAT_SUPPORTED;
- cfg->hb_pub.net_idx = idx;
-
- if (dst == BT_MESH_ADDR_UNASSIGNED) {
- hb_pub_disable(cfg);
- } else {
- /* 2^(n-1) */
- cfg->hb_pub.count = hb_pwr2(param->count_log, 1);
- cfg->hb_pub.ttl = param->ttl;
-
- BT_DBG("period %u ms", hb_pwr2(param->period_log, 1) * 1000);
-
- /* The first Heartbeat message shall be published as soon
- * as possible after the Heartbeat Publication Period state
- * has been configured for periodic publishing.
- */
- if (param->period_log && param->count_log) {
- k_work_submit(&cfg->hb_pub.timer.work);
- } else {
- k_delayed_work_cancel(&cfg->hb_pub.timer);
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_hb_pub();
- }
-
- hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL);
-
- return;
-
-failed:
- hb_pub_send_status(model, ctx, status, param);
+ status = bt_mesh_hb_pub_set(&pub);
+rsp:
+ 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, u8_t status)
+ 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);
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t period;
- s64_t uptime;
-
- BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status);
-
- uptime = k_uptime_get();
- if (uptime > cfg->hb_sub.expiry) {
- period = 0;
- } else {
- period = (cfg->hb_sub.expiry - uptime) / 1000;
- }
+ BT_DBG("src 0x%04x ", ctx->addr);
bt_mesh_model_msg_init(msg, OP_HEARTBEAT_SUB_STATUS);
- net_buf_simple_add_u8(msg, status);
-
- net_buf_simple_add_le16(msg, cfg->hb_sub.src);
- net_buf_simple_add_le16(msg, cfg->hb_sub.dst);
-
- net_buf_simple_add_u8(msg, hb_log(period));
- net_buf_simple_add_u8(msg, hb_log(cfg->hb_sub.count));
- net_buf_simple_add_u8(msg, cfg->hb_sub.min_hops);
- net_buf_simple_add_u8(msg, cfg->hb_sub.max_hops);
+ net_buf_simple_add_u8(msg, STATUS_SUCCESS);
+ net_buf_simple_add_le16(msg, sub->src);
+ net_buf_simple_add_le16(msg, sub->dst);
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(sub->remaining));
+ net_buf_simple_add_u8(msg, bt_mesh_hb_log(sub->count));
+ net_buf_simple_add_u8(msg, sub->min_hops);
+ net_buf_simple_add_u8(msg, sub->max_hops);
if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) {
@@ -3143,92 +2341,58 @@ static void heartbeat_sub_get(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
+ struct bt_mesh_hb_sub sub;
+
BT_DBG("src 0x%04x", ctx->addr);
- hb_sub_send_status(model, ctx, STATUS_SUCCESS);
+ bt_mesh_hb_sub_get(&sub);
+
+ 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)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
- u16_t sub_src, sub_dst;
- u8_t sub_period;
- s32_t period_ms;
+ uint8_t period_log, status;
+ struct bt_mesh_hb_sub sub;
+ uint16_t sub_src, sub_dst;
+ uint32_t period;
BT_DBG("src 0x%04x", ctx->addr);
sub_src = net_buf_simple_pull_le16(buf);
sub_dst = net_buf_simple_pull_le16(buf);
- sub_period = net_buf_simple_pull_u8(buf);
+ period_log = net_buf_simple_pull_u8(buf);
BT_DBG("sub_src 0x%04x sub_dst 0x%04x period 0x%02x",
- sub_src, sub_dst, sub_period);
+ sub_src, sub_dst, period_log);
- if (sub_src != BT_MESH_ADDR_UNASSIGNED &&
- !BT_MESH_ADDR_IS_UNICAST(sub_src)) {
- BT_WARN("Prohibited source address");
+ if (period_log > 0x11) {
+ BT_WARN("Prohibited subscription period 0x%02x", period_log);
return;
}
- if (BT_MESH_ADDR_IS_VIRTUAL(sub_dst) || BT_MESH_ADDR_IS_RFU(sub_dst) ||
- (BT_MESH_ADDR_IS_UNICAST(sub_dst) &&
- sub_dst != bt_mesh_primary_addr())) {
- BT_WARN("Prohibited destination address");
- return;
- }
+ period = bt_mesh_hb_pwr2(period_log);
- if (sub_period > 0x11) {
- BT_WARN("Prohibited subscription period 0x%02x", sub_period);
- return;
- }
-
- if (sub_src == BT_MESH_ADDR_UNASSIGNED ||
- sub_dst == BT_MESH_ADDR_UNASSIGNED ||
- sub_period == 0x00) {
- /* Only an explicit address change to unassigned should
- * trigger clearing of the values according to
- * MESH/NODE/CFG/HBS/BV-02-C.
+ status = bt_mesh_hb_sub_set(sub_src, sub_dst, period);
+ if (status != STATUS_SUCCESS) {
+ /* All errors are caused by invalid packets, which should be
+ * ignored.
*/
- if (sub_src == BT_MESH_ADDR_UNASSIGNED ||
- sub_dst == BT_MESH_ADDR_UNASSIGNED) {
- cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.min_hops = BT_MESH_TTL_MAX;
- cfg->hb_sub.max_hops = 0;
- cfg->hb_sub.count = 0;
- }
-
- period_ms = 0;
- } else {
- cfg->hb_sub.src = sub_src;
- cfg->hb_sub.dst = sub_dst;
- cfg->hb_sub.min_hops = BT_MESH_TTL_MAX;
- cfg->hb_sub.max_hops = 0;
- cfg->hb_sub.count = 0;
- period_ms = hb_pwr2(sub_period, 1) * 1000;
+ return;
}
- /* Let the transport layer know it needs to handle this address */
- bt_mesh_set_hb_sub_dst(cfg->hb_sub.dst);
-
- BT_DBG("period_ms %u", (unsigned) period_ms);
-
- if (period_ms) {
- cfg->hb_sub.expiry = k_uptime_get() + period_ms;
- } else {
- cfg->hb_sub.expiry = 0;
- }
-
- hb_sub_send_status(model, ctx, STATUS_SUCCESS);
+ bt_mesh_hb_sub_get(&sub);
/* MESH/NODE/CFG/HBS/BV-01-C expects the MinHops to be 0x7f after
* disabling subscription, but 0x00 for subsequent Get requests.
*/
- if (!period_ms) {
- cfg->hb_sub.min_hops = 0;
+ if (!period_log) {
+ sub.min_hops = BT_MESH_TTL_MAX;
}
+
+ hb_sub_send_status(model, ctx, &sub);
}
const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
@@ -3282,58 +2446,9 @@ const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = {
BT_MESH_MODEL_OP_END,
};
-static void hb_publish(struct ble_npl_event *work)
-{
- struct bt_mesh_cfg_srv *cfg = ble_npl_event_get_arg(work);
- struct bt_mesh_subnet *sub;
- u16_t period_ms;
-
- BT_DBG("hb_pub.count: %u", cfg->hb_pub.count);
-
- sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx);
- if (!sub) {
- BT_ERR("No matching subnet for idx 0x%02x",
- cfg->hb_pub.net_idx);
- cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED;
- return;
- }
-
- if (cfg->hb_pub.count == 0) {
- return;
- }
-
- period_ms = hb_pwr2(cfg->hb_pub.period, 1) * 1000;
- if (period_ms && cfg->hb_pub.count > 1) {
- k_delayed_work_submit(&cfg->hb_pub.timer, period_ms);
- }
-
- bt_mesh_heartbeat_send();
-
- if (cfg->hb_pub.count != 0xffff) {
- cfg->hb_pub.count--;
- }
-}
-
-static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg)
-{
- if (cfg->relay > 0x02) {
- return false;
- }
-
- if (cfg->beacon > 0x01) {
- return false;
- }
-
- if (cfg->default_ttl > BT_MESH_TTL_MAX) {
- return false;
- }
-
- return true;
-}
-
static int cfg_srv_init(struct bt_mesh_model *model)
{
- struct bt_mesh_cfg_srv *cfg = model->user_data;
+ bt_mesh_app_key_cb_list[0] = app_key_evt;
BT_DBG("");
@@ -3342,43 +2457,12 @@ static int cfg_srv_init(struct bt_mesh_model *model)
return -EINVAL;
}
- if (!cfg) {
- BT_ERR("No Configuration Server context provided");
- return -EINVAL;
- }
-
- if (!conf_is_valid(cfg)) {
- BT_ERR("Invalid values in configuration");
- return -EINVAL;
- }
-
/*
* Configuration Model security is device-key based and only the local
* device-key is allowed to access this model.
*/
model->keys[0] = BT_MESH_KEY_DEV_LOCAL;
- if (!(MYNEWT_VAL(BLE_MESH_RELAY))) {
- cfg->relay = BT_MESH_RELAY_NOT_SUPPORTED;
- }
-
- if (!(MYNEWT_VAL(BLE_MESH_FRIEND))) {
- cfg->frnd = BT_MESH_FRIEND_NOT_SUPPORTED;
- }
-
- if (!(MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- cfg->gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED;
- }
-
- k_delayed_work_init(&cfg->hb_pub.timer, hb_publish);
- k_delayed_work_add_arg(&cfg->hb_pub.timer, cfg);
- cfg->hb_pub.net_idx = BT_MESH_KEY_UNUSED;
- cfg->hb_sub.expiry = 0;
-
- cfg->model = model;
-
- conf = cfg;
-
return 0;
}
@@ -3403,8 +2487,6 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
if (clear_count) {
bt_mesh_store_mod_sub(mod);
}
-
- bt_mesh_model_data_store(mod, vnd, NULL, 0);
}
if (mod->cb && mod->cb->reset) {
@@ -3414,209 +2496,6 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
void bt_mesh_cfg_reset(void)
{
- struct bt_mesh_cfg_srv *cfg = conf;
- int i;
-
- BT_DBG("");
-
- if (!cfg) {
- return;
- }
-
- bt_mesh_set_hb_sub_dst(BT_MESH_ADDR_UNASSIGNED);
-
- cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED;
- cfg->hb_sub.expiry = 0;
-
- /* Delete all net keys, which also takes care of all app keys which
- * are associated with each net key.
- */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_subnet_del(sub, true);
- }
- }
-
bt_mesh_model_foreach(mod_reset, NULL);
-
- memset(labels, 0, sizeof(labels));
-}
-
-void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat)
-{
- struct bt_mesh_cfg_srv *cfg = conf;
-
- if (!cfg) {
- BT_WARN("No configuaration server context available");
- return;
- }
-
- if (src != cfg->hb_sub.src || dst != cfg->hb_sub.dst) {
- BT_WARN("No subscription for received heartbeat");
- return;
- }
-
- if (k_uptime_get() > cfg->hb_sub.expiry) {
- BT_WARN("Heartbeat subscription period expired");
- return;
- }
-
- cfg->hb_sub.min_hops = min(cfg->hb_sub.min_hops, hops);
- cfg->hb_sub.max_hops = max(cfg->hb_sub.max_hops, hops);
-
- if (cfg->hb_sub.count < 0xffff) {
- cfg->hb_sub.count++;
- }
-
- BT_DBG("src 0x%04x dst 0x%04x hops %u min %u max %u count %u", src,
- dst, hops, cfg->hb_sub.min_hops, cfg->hb_sub.max_hops,
- cfg->hb_sub.count);
-
- if (cfg->hb_sub.func) {
- cfg->hb_sub.func(hops, feat);
- }
-}
-
-u8_t bt_mesh_net_transmit_get(void)
-{
- if (conf) {
- return conf->net_transmit;
- }
-
- return 0;
-}
-
-u8_t bt_mesh_relay_get(void)
-{
- if (conf) {
- return conf->relay;
- }
-
- return BT_MESH_RELAY_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_friend_get(void)
-{
- BT_DBG("conf %p conf->frnd 0x%02x", conf, conf->frnd);
-
- if (conf) {
- return conf->frnd;
- }
-
- return BT_MESH_FRIEND_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_relay_retransmit_get(void)
-{
- if (conf) {
- return conf->relay_retransmit;
- }
-
- return 0;
-}
-
-u8_t bt_mesh_beacon_get(void)
-{
- if (conf) {
- return conf->beacon;
- }
-
- return BT_MESH_BEACON_DISABLED;
-}
-
-u8_t bt_mesh_gatt_proxy_get(void)
-{
- if (conf) {
- return conf->gatt_proxy;
- }
-
- return BT_MESH_GATT_PROXY_NOT_SUPPORTED;
-}
-
-u8_t bt_mesh_default_ttl_get(void)
-{
- if (conf) {
- return conf->default_ttl;
- }
-
- return DEFAULT_TTL;
-}
-
-u8_t *bt_mesh_label_uuid_get(u16_t addr)
-{
- int i;
-
- BT_DBG("addr 0x%04x", addr);
-
- for (i = 0; i < ARRAY_SIZE(labels); i++) {
- if (labels[i].addr == addr) {
- BT_DBG("Found Label UUID for 0x%04x: %s", addr,
- bt_hex(labels[i].uuid, 16));
- return labels[i].uuid;
- }
- }
-
- BT_WARN("No matching Label UUID for 0x%04x", addr);
-
- return NULL;
-}
-
-struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void)
-{
- if (!conf) {
- return NULL;
- }
-
- return &conf->hb_pub;
-}
-
-void bt_mesh_hb_pub_disable(void)
-{
- if (conf) {
- hb_pub_disable(conf);
- }
-}
-
-struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void)
-{
- return conf;
-}
-
-void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store)
-{
- int i;
-
- BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store);
-
- if (conf && conf->hb_pub.net_idx == sub->net_idx) {
- hb_pub_disable(conf);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_store_hb_pub();
- }
- }
-
- /* Delete any app keys bound to this NetKey index */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx == sub->net_idx) {
- bt_mesh_app_key_del(key, store);
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_clear_net_idx(sub->net_idx);
- }
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) {
- bt_mesh_clear_subnet(sub);
- }
-
- memset(sub, 0, sizeof(*sub));
- sub->net_idx = BT_MESH_KEY_UNUSED;
}
#endif
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c
index 425897630..cc75f65f8 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.c
@@ -38,8 +38,8 @@
#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
#if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS)
-int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
- size_t sg_len, u8_t mac[16])
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+ size_t sg_len, uint8_t mac[16])
{
int rc = BLE_HS_EUNKNOWN;
mbedtls_cipher_context_t ctx = {0};
@@ -80,8 +80,8 @@ exit:
}
#else
-int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
- size_t sg_len, u8_t mac[16])
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+ size_t sg_len, uint8_t mac[16])
{
struct tc_aes_key_sched_struct sched;
struct tc_cmac_struct state;
@@ -105,8 +105,8 @@ int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
}
#endif
-int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
- const char *info, u8_t okm[16])
+int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
+ const char *info, uint8_t okm[16])
{
int err;
@@ -118,14 +118,14 @@ int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
return bt_mesh_aes_cmac_one(okm, info, strlen(info), okm);
}
-int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
- u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16])
+int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
+ uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16])
{
struct bt_mesh_sg sg[3];
- u8_t salt[16];
- u8_t out[16];
- u8_t t[16];
- u8_t pad;
+ uint8_t salt[16];
+ uint8_t out[16];
+ uint8_t t[16];
+ uint8_t pad;
int err;
BT_DBG("n %s", bt_hex(n, 16));
@@ -183,11 +183,11 @@ int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
return 0;
}
-int bt_mesh_k3(const u8_t n[16], u8_t out[8])
+int bt_mesh_k3(const uint8_t n[16], uint8_t out[8])
{
- u8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
- u8_t tmp[16];
- u8_t t[16];
+ uint8_t id64[] = { 'i', 'd', '6', '4', 0x01 };
+ uint8_t tmp[16];
+ uint8_t t[16];
int err;
err = bt_mesh_s1("smk3", tmp);
@@ -210,11 +210,11 @@ int bt_mesh_k3(const u8_t n[16], u8_t out[8])
return 0;
}
-int bt_mesh_k4(const u8_t n[16], u8_t out[1])
+int bt_mesh_k4(const uint8_t n[16], uint8_t out[1])
{
- u8_t id6[] = { 'i', 'd', '6', 0x01 };
- u8_t tmp[16];
- u8_t t[16];
+ uint8_t id6[] = { 'i', 'd', '6', 0x01 };
+ uint8_t tmp[16];
+ uint8_t t[16];
int err;
err = bt_mesh_s1("smk4", tmp);
@@ -237,10 +237,10 @@ int bt_mesh_k4(const u8_t n[16], u8_t out[1])
return 0;
}
-int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
+int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16])
{
const char *id128 = "id128\x01";
- u8_t salt[16];
+ uint8_t salt[16];
int err;
err = bt_mesh_s1(s, salt);
@@ -251,326 +251,8 @@ int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16])
return bt_mesh_k1(n, 16, salt, id128, out);
}
-static int bt_mesh_ccm_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t *enc_msg, size_t msg_len,
- const u8_t *aad, size_t aad_len,
- u8_t *out_msg, size_t mic_size)
-{
- u8_t msg[16], pmsg[16], cmic[16], cmsg[16], Xn[16], mic[16];
- u16_t last_blk, blk_cnt;
- size_t i, j;
- int err;
-
- if (msg_len < 1 || aad_len >= 0xff00) {
- return -EINVAL;
- }
-
- /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(0x0000, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmic);
- if (err) {
- return err;
- }
-
- /* X_0 = e(AppKey, 0x09 || nonce || length) */
- if (mic_size == sizeof(u64_t)) {
- pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
- } else {
- pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
- }
-
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(msg_len, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* If AAD is being used to authenticate, include it here */
- if (aad_len) {
- sys_put_be16(aad_len, pmsg);
-
- for (i = 0; i < sizeof(u16_t); i++) {
- pmsg[i] = Xn[i] ^ pmsg[i];
- }
-
- j = 0;
- aad_len += sizeof(u16_t);
- while (aad_len > 16) {
- do {
- pmsg[i] = Xn[i] ^ aad[j];
- i++, j++;
- } while (i < 16);
-
- aad_len -= 16;
- i = 0;
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- for (; i < aad_len; i++, j++) {
- pmsg[i] = Xn[i] ^ aad[j];
- }
-
- for (i = aad_len; i < 16; i++) {
- pmsg[i] = Xn[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- last_blk = msg_len % 16;
- blk_cnt = (msg_len + 15) / 16;
- if (!last_blk) {
- last_blk = 16;
- }
-
- for (j = 0; j < blk_cnt; j++) {
- if (j + 1 == blk_cnt) {
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < last_blk; i++) {
- msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
- }
-
- memcpy(out_msg + (j * 16), msg, last_blk);
-
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < last_blk; i++) {
- pmsg[i] = Xn[i] ^ msg[i];
- }
-
- for (i = last_blk; i < 16; i++) {
- pmsg[i] = Xn[i] ^ 0x00;
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* MIC = C_mic ^ X_1 */
- for (i = 0; i < sizeof(mic); i++) {
- mic[i] = cmic[i] ^ Xn[i];
- }
- } else {
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < 16; i++) {
- msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i];
- }
-
- memcpy(out_msg + (j * 16), msg, 16);
-
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < 16; i++) {
- pmsg[i] = Xn[i] ^ msg[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
- }
-
- if (memcmp(mic, enc_msg + msg_len, mic_size)) {
- return -EBADMSG;
- }
-
- return 0;
-}
-
-static int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t *msg, size_t msg_len,
- const u8_t *aad, size_t aad_len,
- u8_t *out_msg, size_t mic_size)
-{
- u8_t pmsg[16], cmic[16], cmsg[16], mic[16], Xn[16];
- u16_t blk_cnt, last_blk;
- size_t i, j;
- int err;
-
- BT_DBG("key %s", bt_hex(key, 16));
- BT_DBG("nonce %s", bt_hex(nonce, 13));
- BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len));
- BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);
-
- /* Unsupported AAD size */
- if (aad_len >= 0xff00) {
- return -EINVAL;
- }
-
- /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(0x0000, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmic);
- if (err) {
- return err;
- }
-
- /* X_0 = e(AppKey, 0x09 || nonce || length) */
- if (mic_size == sizeof(u64_t)) {
- pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00);
- } else {
- pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00);
- }
-
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(msg_len, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* If AAD is being used to authenticate, include it here */
- if (aad_len) {
- sys_put_be16(aad_len, pmsg);
-
- for (i = 0; i < sizeof(u16_t); i++) {
- pmsg[i] = Xn[i] ^ pmsg[i];
- }
-
- j = 0;
- aad_len += sizeof(u16_t);
- while (aad_len > 16) {
- do {
- pmsg[i] = Xn[i] ^ aad[j];
- i++, j++;
- } while (i < 16);
-
- aad_len -= 16;
- i = 0;
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- for (; i < aad_len; i++, j++) {
- pmsg[i] = Xn[i] ^ aad[j];
- }
-
- for (i = aad_len; i < 16; i++) {
- pmsg[i] = Xn[i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
- }
-
- last_blk = msg_len % 16;
- blk_cnt = (msg_len + 15) / 16;
- if (!last_blk) {
- last_blk = 16;
- }
-
- for (j = 0; j < blk_cnt; j++) {
- if (j + 1 == blk_cnt) {
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < last_blk; i++) {
- pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
- }
- for (i = last_blk; i < 16; i++) {
- pmsg[i] = Xn[i] ^ 0x00;
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* MIC = C_mic ^ X_1 */
- for (i = 0; i < sizeof(mic); i++) {
- mic[i] = cmic[i] ^ Xn[i];
- }
-
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_1 */
- for (i = 0; i < last_blk; i++) {
- out_msg[(j * 16) + i] =
- msg[(j * 16) + i] ^ cmsg[i];
- }
- } else {
- /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
- for (i = 0; i < 16; i++) {
- pmsg[i] = Xn[i] ^ msg[(j * 16) + i];
- }
-
- err = bt_encrypt_be(key, pmsg, Xn);
- if (err) {
- return err;
- }
-
- /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */
- pmsg[0] = 0x01;
- memcpy(pmsg + 1, nonce, 13);
- sys_put_be16(j + 1, pmsg + 14);
-
- err = bt_encrypt_be(key, pmsg, cmsg);
- if (err) {
- return err;
- }
-
- /* Encrypted = Payload[0-15] ^ C_N */
- for (i = 0; i < 16; i++) {
- out_msg[(j * 16) + i] =
- msg[(j * 16) + i] ^ cmsg[i];
- }
-
- }
- }
-
- memcpy(out_msg + msg_len, mic, mic_size);
-
- return 0;
-}
-
-static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
- u32_t iv_index)
+static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu,
+ uint32_t iv_index)
{
/* Nonce Type */
nonce[0] = 0x03;
@@ -595,8 +277,8 @@ static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu,
sys_put_be32(iv_index, &nonce[9]);
}
-static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
- u32_t iv_index)
+static void create_net_nonce(uint8_t nonce[13], const uint8_t *pdu,
+ uint32_t iv_index)
{
/* Nonce Type */
nonce[0] = 0x00;
@@ -621,11 +303,11 @@ static void create_net_nonce(u8_t nonce[13], const u8_t *pdu,
sys_put_be32(iv_index, &nonce[9]);
}
-int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
- const u8_t privacy_key[16])
+int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
+ const uint8_t privacy_key[16])
{
- u8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
- u8_t tmp[16];
+ uint8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, };
+ uint8_t tmp[16];
int err, i;
BT_DBG("IVIndex %u, PrivacyKey %s", (unsigned) iv_index,
@@ -648,11 +330,11 @@ int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
return 0;
}
-int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy)
+int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy)
{
- u8_t mic_len = NET_MIC_LEN(buf->om_data);
- u8_t nonce[13];
+ uint8_t mic_len = NET_MIC_LEN(buf->om_data);
+ uint8_t nonce[13];
int err;
BT_DBG("IVIndex %u EncKey %s mic_len %u", (unsigned) iv_index,
@@ -667,7 +349,7 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- err = bt_mesh_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
+ err = bt_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
NULL, 0, &buf->om_data[7], mic_len);
if (!err) {
net_buf_simple_add(buf, mic_len);
@@ -676,11 +358,11 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
return err;
}
-int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy)
+int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy)
{
- u8_t mic_len = NET_MIC_LEN(buf->om_data);
- u8_t nonce[13];
+ uint8_t mic_len = NET_MIC_LEN(buf->om_data);
+ uint8_t nonce[13];
BT_DBG("PDU (%u bytes) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
BT_DBG("iv_index %u, key %s mic_len %u", (unsigned) iv_index,
@@ -696,118 +378,74 @@ int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
buf->om_len -= mic_len;
- return bt_mesh_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
+ return bt_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7,
NULL, 0, &buf->om_data[7], mic_len);
}
-static void create_app_nonce(u8_t nonce[13], bool dev_key, u8_t aszmic,
- u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index)
+static void create_app_nonce(uint8_t nonce[13],
+ const struct bt_mesh_app_crypto_ctx *ctx)
{
- if (dev_key) {
+ if (ctx->dev_key) {
nonce[0] = 0x02;
} else {
nonce[0] = 0x01;
}
- sys_put_be32((seq_num | ((u32_t)aszmic << 31)), &nonce[1]);
+ sys_put_be32((ctx->seq_num | ((uint32_t)ctx->aszmic << 31)), &nonce[1]);
- sys_put_be16(src, &nonce[5]);
- sys_put_be16(dst, &nonce[7]);
+ sys_put_be16(ctx->src, &nonce[5]);
+ sys_put_be16(ctx->dst, &nonce[7]);
- sys_put_be32(iv_index, &nonce[9]);
+ sys_put_be32(ctx->iv_index, &nonce[9]);
}
-static int mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
+int bt_mesh_app_encrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf)
{
- u8_t nonce[13];
+ int err;
+ uint8_t nonce[13];
BT_DBG("AppKey %s", bt_hex(key, 16));
- BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst);
- BT_DBG("seq_num 0x%08x iv_index 0x%08x", (unsigned) seq_num,
- (unsigned) iv_index);
+ BT_DBG("dev_key %u src 0x%04x dst 0x%04x", ctx->dev_key, ctx->src,
+ ctx->dst);
+ BT_DBG("seq_num 0x%08x iv_index 0x%08x", ctx->seq_num, ctx->iv_index);
BT_DBG("Clear: %s", bt_hex(buf->om_data, buf->om_len));
- create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
+ create_app_nonce(nonce, ctx);
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- return bt_mesh_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ad,
- ad ? 16 : 0, buf->om_data,
- APP_MIC_LEN(aszmic));
-}
+ err = bt_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad,
+ ctx->ad ? 16 : 0, buf->om_data,
+ APP_MIC_LEN(ctx->aszmic));
-int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index)
-{
- int err;
-
- err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
- seq_num, iv_index);
if (!err) {
+ net_buf_simple_add(buf, APP_MIC_LEN(ctx->aszmic));
BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
}
return err;
}
-int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index)
+int bt_mesh_app_decrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf, struct os_mbuf *out)
{
+ uint8_t nonce[13];
int err;
- err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst,
- seq_num, iv_index);
-
- if (!err) {
- net_buf_simple_add(buf, APP_MIC_LEN(aszmic));
- BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len));
- }
-
- return err;
-}
-
-static int mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, struct os_mbuf *out,
- const u8_t *ad, u16_t src, u16_t dst,
- u32_t seq_num, u32_t iv_index)
-{
- u8_t nonce[13];
-
BT_DBG("EncData (len %u) %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index);
+ create_app_nonce(nonce, ctx);
BT_DBG("AppKey %s", bt_hex(key, 16));
BT_DBG("Nonce %s", bt_hex(nonce, 13));
- return bt_mesh_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ad,
- ad ? 16 : 0, out->om_data,
- APP_MIC_LEN(aszmic));
-}
-
-int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index)
-{
- return mesh_app_decrypt(key, dev_key, aszmic, buf, buf,
- ad, src, dst, seq_num, iv_index);
-}
-
-int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, struct os_mbuf *out,
- const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index)
-{
- int err;
-
- err = mesh_app_decrypt(key, dev_key, aszmic, buf, out,
- ad, src, dst, seq_num, iv_index);
+ err = bt_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad,
+ ctx->ad ? 16 : 0, out->om_data,
+ APP_MIC_LEN(ctx->aszmic));
if (!err) {
net_buf_simple_add(out, buf->om_len);
}
@@ -816,7 +454,7 @@ int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
}
/* reversed, 8-bit, poly=0x07 */
-static const u8_t crc_table[256] = {
+static const uint8_t crc_table[256] = {
0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
@@ -858,9 +496,9 @@ static const u8_t crc_table[256] = {
0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
};
-u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
+uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len)
{
- u8_t fcs = 0xff;
+ uint8_t fcs = 0xff;
while (data_len--) {
fcs = crc_table[fcs ^ *data++];
@@ -871,11 +509,11 @@ u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len)
return 0xff - fcs;
}
-bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs)
+bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs)
{
- const u8_t *data = buf->om_data;
- u16_t data_len = buf->om_len;
- u8_t fcs = 0xff;
+ const uint8_t *data = buf->om_data;
+ uint16_t data_len = buf->om_len;
+ uint8_t fcs = 0xff;
while (data_len--) {
fcs = crc_table[fcs ^ *data++];
@@ -884,10 +522,10 @@ bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs)
return crc_table[fcs ^ received_fcs] == 0xcf;
}
-int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
+int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr)
{
- u8_t salt[16];
- u8_t tmp[16];
+ uint8_t salt[16];
+ uint8_t tmp[16];
int err;
err = bt_mesh_s1("vtad", salt);
@@ -905,21 +543,21 @@ int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr)
return 0;
}
-int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16])
+int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16])
{
- const u8_t conf_salt_key[16] = { 0 };
+ const uint8_t conf_salt_key[16] = { 0 };
return bt_mesh_aes_cmac_one(conf_salt_key, conf_inputs, 145, salt);
}
-int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
- u8_t conf_key[16])
+int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
+ uint8_t conf_key[16])
{
return bt_mesh_k1(dhkey, 32, conf_salt, "prck", conf_key);
}
-int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
- const u8_t auth[16], u8_t conf[16])
+int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
+ const uint8_t auth[16], uint8_t conf[16])
{
struct bt_mesh_sg sg[] = { { rand, 16 }, { auth, 16 } };
@@ -930,23 +568,23 @@ int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
return bt_mesh_aes_cmac(conf_key, sg, ARRAY_SIZE(sg), conf);
}
-int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25 + 8], u8_t out[25])
+int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25 + 8], uint8_t out[25])
{
- return bt_mesh_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
+ return bt_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8);
}
-int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25], u8_t out[25 + 8])
+int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25], uint8_t out[25 + 8])
{
- return bt_mesh_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
+ return bt_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8);
}
-int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
- const u8_t net_id[8], u32_t iv_index,
- u8_t auth[8])
+int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
+ const uint8_t net_id[8], uint32_t iv_index,
+ uint8_t auth[8])
{
- u8_t msg[13], tmp[16];
+ uint8_t msg[13], tmp[16];
int err;
BT_DBG("BeaconKey %s", bt_hex(beacon_key, 16));
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h
index 8af371c60..4fbbc119e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/crypto.h
@@ -15,81 +15,81 @@ struct bt_mesh_sg {
size_t len;
};
-int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg,
- size_t sg_len, u8_t mac[16]);
+int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg,
+ size_t sg_len, uint8_t mac[16]);
-static inline int bt_mesh_aes_cmac_one(const u8_t key[16], const void *m,
- size_t len, u8_t mac[16])
+static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m,
+ size_t len, uint8_t mac[16])
{
struct bt_mesh_sg sg = { m, len };
return bt_mesh_aes_cmac(key, &sg, 1, mac);
}
-static inline bool bt_mesh_s1(const char *m, u8_t salt[16])
+static inline bool bt_mesh_s1(const char *m, uint8_t salt[16])
{
- const u8_t zero[16] = { 0 };
+ const uint8_t zero[16] = { 0 };
return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt);
}
-int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16],
- const char *info, u8_t okm[16]);
+int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16],
+ const char *info, uint8_t okm[16]);
#define bt_mesh_k1_str(ikm, ikm_len, salt_str, info, okm) \
({ \
- const u8_t salt[16] = salt_str; \
+ const uint8_t salt[16] = salt_str; \
bt_mesh_k1(ikm, ikm_len, salt, info, okm); \
})
-int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len,
- u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16]);
+int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len,
+ uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16]);
-int bt_mesh_k3(const u8_t n[16], u8_t out[8]);
+int bt_mesh_k3(const uint8_t n[16], uint8_t out[8]);
-int bt_mesh_k4(const u8_t n[16], u8_t out[1]);
+int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]);
-int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]);
+int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16]);
-static inline int bt_mesh_id_resolving_key(const u8_t net_key[16],
- u8_t resolving_key[16])
+static inline int bt_mesh_id_resolving_key(const uint8_t net_key[16],
+ uint8_t resolving_key[16])
{
return bt_mesh_k1_str(net_key, 16, "smbt", "smbi", resolving_key);
}
-static inline int bt_mesh_identity_key(const u8_t net_key[16],
- u8_t identity_key[16])
+static inline int bt_mesh_identity_key(const uint8_t net_key[16],
+ uint8_t identity_key[16])
{
return bt_mesh_id128(net_key, "nkik", identity_key);
}
-static inline int bt_mesh_beacon_key(const u8_t net_key[16],
- u8_t beacon_key[16])
+static inline int bt_mesh_beacon_key(const uint8_t net_key[16],
+ uint8_t beacon_key[16])
{
return bt_mesh_id128(net_key, "nkbk", beacon_key);
}
-int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags,
- const u8_t net_id[16], u32_t iv_index,
- u8_t auth[8]);
+int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags,
+ const uint8_t net_id[8], uint32_t iv_index,
+ uint8_t auth[8]);
-static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1])
+static inline int bt_mesh_app_id(const uint8_t app_key[16], uint8_t app_id[1])
{
return bt_mesh_k4(app_key, app_id);
}
-static inline int bt_mesh_session_key(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t session_key[16])
+static inline int bt_mesh_session_key(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t session_key[16])
{
return bt_mesh_k1(dhkey, 32, prov_salt, "prsk", session_key);
}
-static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t nonce[13])
+static inline int bt_mesh_prov_nonce(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t nonce[13])
{
- u8_t tmp[16];
+ uint8_t tmp[16];
int err;
err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp);
@@ -100,19 +100,19 @@ static inline int bt_mesh_prov_nonce(const u8_t dhkey[32],
return err;
}
-static inline int bt_mesh_dev_key(const u8_t dhkey[32],
- const u8_t prov_salt[16],
- u8_t dev_key[16])
+static inline int bt_mesh_dev_key(const uint8_t dhkey[32],
+ const uint8_t prov_salt[16],
+ uint8_t dev_key[16])
{
return bt_mesh_k1(dhkey, 32, prov_salt, "prdk", dev_key);
}
-static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
- const u8_t prov_rand[16],
- const u8_t dev_rand[16],
- u8_t prov_salt[16])
+static inline int bt_mesh_prov_salt(const uint8_t conf_salt[16],
+ const uint8_t prov_rand[16],
+ const uint8_t dev_rand[16],
+ uint8_t prov_salt[16])
{
- const u8_t prov_salt_key[16] = { 0 };
+ const uint8_t prov_salt_key[16] = { 0 };
struct bt_mesh_sg sg[] = {
{ conf_salt, 16 },
{ prov_rand, 16 },
@@ -122,49 +122,50 @@ static inline int bt_mesh_prov_salt(const u8_t conf_salt[16],
return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt);
}
-int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index,
- const u8_t privacy_key[16]);
+int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index,
+ const uint8_t privacy_key[16]);
-int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy);
+int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy);
-int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf,
- u32_t iv_index, bool proxy);
+int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf,
+ uint32_t iv_index, bool proxy);
-int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index);
+struct bt_mesh_app_crypto_ctx {
+ bool dev_key;
+ uint8_t aszmic;
+ uint16_t src;
+ uint16_t dst;
+ uint32_t seq_num;
+ uint32_t iv_index;
+ const uint8_t *ad;
+};
-int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, const u8_t *ad,
- u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index);
+int bt_mesh_app_encrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf);
-int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf *buf, const u8_t *ad, u16_t src,
- u16_t dst, u32_t seq_num, u32_t iv_index);
+int bt_mesh_app_decrypt(const uint8_t key[16],
+ const struct bt_mesh_app_crypto_ctx *ctx,
+ struct os_mbuf *buf, struct os_mbuf *out);
-int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic,
- struct os_mbuf*buf, struct os_mbuf*out,
- const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num,
- u32_t iv_index);
+uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len);
-u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len);
+bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs);
-bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs);
+int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr);
-int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr);
+int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16]);
-int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16]);
+int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16],
+ uint8_t conf_key[16]);
-int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16],
- u8_t conf_key[16]);
+int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16],
+ const uint8_t auth[16], uint8_t conf[16]);
-int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16],
- const u8_t auth[16], u8_t conf[16]);
+int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25 + 8], uint8_t out[25]);
-int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25 + 8], u8_t out[25]);
-
-int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13],
- const u8_t data[25], u8_t out[25 + 8]);
+int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13],
+ const uint8_t data[25], uint8_t out[25 + 8]);
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/foundation.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/foundation.h
index ee615ae9e..012afbbb0 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/foundation.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/foundation.h
@@ -115,57 +115,23 @@
#define STATUS_UNSPECIFIED 0x10
#define STATUS_INVALID_BINDING 0x11
-enum {
- BT_MESH_VA_CHANGED, /* Label information changed */
-};
-
-struct label {
- u16_t ref;
- u16_t addr;
- u8_t uuid[16];
- atomic_t flags[1];
-};
-
void bt_mesh_cfg_reset(void);
-void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat);
-
-void bt_mesh_attention(struct bt_mesh_model *model, u8_t time);
-
-struct label *get_label(u16_t index);
-
-u8_t *bt_mesh_label_uuid_get(u16_t addr);
-
-struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void);
-void bt_mesh_hb_pub_disable(void);
-struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void);
-
-u8_t bt_mesh_net_transmit_get(void);
-u8_t bt_mesh_relay_get(void);
-u8_t bt_mesh_friend_get(void);
-u8_t bt_mesh_relay_retransmit_get(void);
-u8_t bt_mesh_beacon_get(void);
-u8_t bt_mesh_gatt_proxy_get(void);
-u8_t bt_mesh_default_ttl_get(void);
-
-void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store);
-
-struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx);
-void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store);
+void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time);
static inline void key_idx_pack(struct os_mbuf *buf,
- u16_t idx1, u16_t idx2)
+ uint16_t idx1, uint16_t idx2)
{
net_buf_simple_add_le16(buf, idx1 | ((idx2 & 0x00f) << 12));
net_buf_simple_add_u8(buf, idx2 >> 4);
}
static inline void key_idx_unpack(struct os_mbuf *buf,
- u16_t *idx1, u16_t *idx2)
+ uint16_t *idx1, uint16_t *idx2)
{
*idx1 = sys_get_le16(&buf->om_data[0]) & 0xfff;
*idx2 = sys_get_le16(&buf->om_data[1]) >> 4;
- net_buf_simple_pull(buf, 3);
+ net_buf_simple_pull_mem(buf, 3);
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c
index c10a93ec7..d15d3bbe5 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.c
@@ -7,9 +7,7 @@
*/
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
-#if MYNEWT_VAL(BLE_MESH)
-
-#define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG
+#define MESH_LOG_MODULE BLE_MESH_FRIEND_LOG
#if MYNEWT_VAL(BLE_MESH_FRIEND)
@@ -23,10 +21,12 @@
#include "crypto.h"
#include "adv.h"
#include "net.h"
+#include "app_keys.h"
#include "transport.h"
#include "access.h"
#include "foundation.h"
#include "friend.h"
+#include "subnet.h"
/* We reserve one extra buffer for each friendship, since we need to be able
* to resend the last sent PDU, which sits separately outside of the queue.
@@ -50,20 +50,20 @@ static struct os_mempool friend_buf_mempool;
#define FRIEND_XMIT BT_MESH_TRANSMIT(0, 20)
struct friend_pdu_info {
- u16_t src;
- u16_t dst;
+ uint16_t src;
+ uint16_t dst;
- u8_t seq[3];
+ uint8_t seq[3];
- u8_t ttl:7,
+ uint8_t ttl:7,
ctl:1;
- u32_t iv_index;
+ uint32_t iv_index;
};
static struct friend_adv {
struct bt_mesh_adv adv;
- u16_t app_idx;
+ uint16_t app_idx;
} adv_pool[FRIEND_BUF_COUNT];
static struct bt_mesh_adv *adv_alloc(int id)
@@ -72,7 +72,7 @@ static struct bt_mesh_adv *adv_alloc(int id)
return &adv_pool[id].adv;
}
-static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr)
+static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr)
{
if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) {
return false;
@@ -81,7 +81,7 @@ static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr)
return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem));
}
-struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
+struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
bool valid, bool established)
{
int i;
@@ -91,7 +91,7 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_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->valid) {
+ if (valid && !frnd->subnet) {
continue;
}
@@ -99,7 +99,8 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
continue;
}
- if (net_idx != BT_MESH_KEY_ANY && frnd->net_idx != net_idx) {
+ if (net_idx != BT_MESH_KEY_ANY &&
+ (!frnd->subnet || frnd->subnet->net_idx != net_idx)) {
continue;
}
@@ -111,11 +112,18 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
return NULL;
}
+static int friend_cred_create(struct bt_mesh_friend *frnd, uint8_t idx)
+{
+ return bt_mesh_friend_cred_create(&frnd->cred[idx], frnd->lpn,
+ bt_mesh_primary_addr(),
+ frnd->lpn_counter, frnd->counter,
+ frnd->subnet->keys[idx].net);
+}
+
static void purge_buffers(struct net_buf_slist_t *list)
{
- struct os_mbuf *buf;
-
while (!net_buf_slist_is_empty(list)) {
+ struct os_mbuf *buf;
buf = (void *)net_buf_slist_get(list);
BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS;
net_buf_unref(buf);
@@ -127,10 +135,10 @@ static void purge_buffers(struct net_buf_slist_t *list)
* like the PTS, where the receiver might not have sufficiently compensated
* for internal latencies required to start scanning.
*/
-static s32_t recv_delay(struct bt_mesh_friend *frnd)
+static int32_t recv_delay(struct bt_mesh_friend *frnd)
{
#if CONFIG_BT_MESH_FRIEND_RECV_WIN > 50
- return (s32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
+ return (int32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5);
#else
return frnd->recv_delay;
#endif
@@ -144,7 +152,7 @@ static void friend_clear(struct bt_mesh_friend *frnd)
k_delayed_work_cancel(&frnd->timer);
- friend_cred_del(frnd->net_idx, frnd->lpn);
+ memset(frnd->cred, 0, sizeof(frnd->cred));
if (frnd->last) {
/* Cancel the sending if necessary */
@@ -165,7 +173,8 @@ static void friend_clear(struct bt_mesh_friend *frnd)
seg->seg_count = 0U;
}
- frnd->valid = 0;
+ frnd->counter++;
+ frnd->subnet = NULL;
frnd->established = 0;
frnd->pending_buf = 0;
frnd->fsn = 0;
@@ -174,26 +183,26 @@ static void friend_clear(struct bt_mesh_friend *frnd)
memset(frnd->sub_list, 0, sizeof(frnd->sub_list));
}
-void bt_mesh_friend_clear_net_idx(u16_t net_idx)
+void bt_mesh_friends_clear(void)
{
int i;
- BT_DBG("net_idx 0x%04x", net_idx);
+ BT_DBG("");
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
- if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
+ if (!frnd->subnet) {
continue;
}
- if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
- friend_clear(frnd);
- }
+ friend_clear(frnd);
}
}
-void bt_mesh_friend_sec_update(u16_t net_idx)
+static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md);
+
+void bt_mesh_friend_sec_update(uint16_t net_idx)
{
int i;
@@ -202,12 +211,13 @@ void bt_mesh_friend_sec_update(u16_t net_idx)
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
- if (frnd->net_idx == BT_MESH_KEY_UNUSED) {
+ if (!frnd->subnet) {
continue;
}
- if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) {
- frnd->sec_update = 1;
+ if (net_idx == BT_MESH_KEY_ANY ||
+ frnd->subnet->net_idx == net_idx) {
+ enqueue_update(frnd, 0x00);
}
}
}
@@ -216,7 +226,7 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_clear *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd;
- u16_t lpn_addr, lpn_counter;
+ uint16_t lpn_addr, lpn_counter;
struct bt_mesh_net_tx tx = {
.sub = rx->sub,
.ctx = &rx->ctx,
@@ -259,14 +269,14 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
cfm.lpn_counter = msg->lpn_counter;
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm,
- sizeof(cfm), NULL, NULL, NULL);
+ sizeof(cfm), NULL, NULL);
friend_clear(frnd);
return 0;
}
-static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr)
+static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr)
{
int i;
@@ -280,7 +290,7 @@ static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr)
BT_WARN("No space in friend subscription list");
}
-static void friend_sub_rem(struct bt_mesh_friend *frnd, u16_t addr)
+static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr)
{
int i;
@@ -324,38 +334,41 @@ static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd,
}
struct unseg_app_sdu_meta {
- struct bt_mesh_net_rx net;
- const u8_t *key;
+ struct bt_mesh_app_crypto_ctx crypto;
+ const uint8_t *key;
struct bt_mesh_subnet *subnet;
- bool is_dev_key;
- u8_t aid;
- u8_t *ad;
+ uint8_t aid;
};
static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd,
struct os_mbuf *buf,
struct unseg_app_sdu_meta *meta)
{
- u16_t app_idx = FRIEND_ADV(buf)->app_idx;
+ uint16_t app_idx = FRIEND_ADV(buf)->app_idx;
+ struct bt_mesh_net_rx net;
int err;
- meta->subnet = bt_mesh_subnet_get(frnd->net_idx);
- meta->is_dev_key = (app_idx == BT_MESH_KEY_DEV);
- meta->is_dev_key = BT_MESH_IS_DEV_KEY(app_idx);
- bt_mesh_net_header_parse(buf, &meta->net);
- err = bt_mesh_app_key_get(meta->subnet, app_idx, meta->net.ctx.recv_dst,
- &meta->key, &meta->aid);
+ meta->subnet = frnd->subnet;
+ bt_mesh_net_header_parse(buf, &net);
+ err = bt_mesh_keys_resolve(&net.ctx, &net.sub, &meta->key, &meta->aid);
if (err) {
return err;
}
- if (BT_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) {
- meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst);
- if (!meta->ad) {
+ meta->crypto.src = net.ctx.addr;
+ meta->crypto.dst = net.ctx.recv_dst;
+ meta->crypto.iv_index = BT_MESH_NET_IVI_TX;
+ meta->crypto.dev_key = BT_MESH_IS_DEV_KEY(app_idx);
+ meta->crypto.seq_num = net.seq;
+ meta->crypto.aszmic = 0;
+
+ if (BT_MESH_ADDR_IS_VIRTUAL(meta->crypto.dst)) {
+ meta->crypto.ad = bt_mesh_va_label_get(meta->crypto.dst);
+ if (!meta->crypto.ad) {
return -ENOENT;
}
} else {
- meta->ad = NULL;
+ meta->crypto.ad = NULL;
}
return 0;
@@ -374,12 +387,10 @@ static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd,
net_buf_simple_pull_mem(buf, 10);
buf->om_len -= 4;
- err = bt_mesh_app_decrypt_in_place(meta->key, meta->is_dev_key,
- 0, buf, meta->ad, meta->net.ctx.addr,
- meta->net.ctx.recv_dst, meta->net.seq,
- BT_MESH_NET_IVI_TX);
+ err = bt_mesh_app_decrypt(meta->key, &meta->crypto, buf, buf);
net_buf_simple_restore(buf, &state);
+ net_buf_unref(buf);
return err;
}
@@ -396,10 +407,7 @@ static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd,
net_buf_simple_pull_mem(buf, 10);
buf->om_len -= 4;
- err = bt_mesh_app_encrypt_in_place(meta->key, meta->is_dev_key, 0, buf,
- meta->ad, meta->net.ctx.addr,
- meta->net.ctx.recv_dst, bt_mesh.seq,
- BT_MESH_NET_IVI_TX);
+ err = bt_mesh_app_encrypt(meta->key, &meta->crypto, buf);
net_buf_simple_restore(buf, &state);
return err;
@@ -425,7 +433,7 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd,
/* No need to reencrypt the message if the sequence number is
* unchanged.
*/
- if (meta.net.seq == bt_mesh.seq) {
+ if (meta.crypto.seq_num == bt_mesh.seq) {
return 0;
}
@@ -446,28 +454,22 @@ 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)
{
- struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
- const u8_t *enc, *priv;
- u32_t iv_index;
- u16_t src;
- u8_t nid;
+ const struct bt_mesh_net_cred *cred;
+ uint32_t iv_index;
+ uint16_t src;
int err;
if (master_cred) {
- enc = sub->keys[sub->kr_flag].enc;
- priv = sub->keys[sub->kr_flag].privacy;
- nid = sub->keys[sub->kr_flag].nid;
+ cred = &frnd->subnet->keys[SUBNET_KEY_TX_IDX(frnd->subnet)]
+ .msg;
} else {
- if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) {
- BT_ERR("friend_cred_get failed");
- return -ENOENT;
- }
+ cred = &frnd->cred[SUBNET_KEY_TX_IDX(frnd->subnet)];
}
src = sys_get_be16(&buf->om_data[5]);
if (bt_mesh_elem_find(src)) {
- u32_t seq;
+ uint32_t seq;
if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) {
err = unseg_app_sdu_prepare(frnd, buf);
@@ -477,25 +479,23 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
}
seq = bt_mesh_next_seq();
- buf->om_data[2] = seq >> 16;
- buf->om_data[3] = seq >> 8;
- buf->om_data[4] = seq;
+ sys_put_be24(seq, &buf->om_data[2]);
iv_index = BT_MESH_NET_IVI_TX;
FRIEND_ADV(buf)->app_idx = BT_MESH_KEY_UNUSED;
} else {
- u8_t ivi = (buf->om_data[0] >> 7);
+ uint8_t ivi = (buf->om_data[0] >> 7);
iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi));
}
- buf->om_data[0] = (nid | (iv_index & 1) << 7);
+ buf->om_data[0] = (cred->nid | (iv_index & 1) << 7);
- if (bt_mesh_net_encrypt(enc, buf, iv_index, false)) {
+ if (bt_mesh_net_encrypt(cred->enc, buf, iv_index, false)) {
BT_ERR("Encrypting failed");
return -EINVAL;
}
- if (bt_mesh_net_obfuscate(buf->om_data, iv_index, priv)) {
+ if (bt_mesh_net_obfuscate(buf->om_data, iv_index, cred->privacy)) {
BT_ERR("Obfuscating failed");
return -EINVAL;
}
@@ -504,7 +504,7 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf,
}
static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
- u8_t ctl_op,
+ uint8_t ctl_op,
struct os_mbuf *sdu)
{
struct friend_pdu_info info;
@@ -526,21 +526,20 @@ static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd,
return create_friend_pdu(frnd, &info, sdu);
}
-static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
+static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, uint8_t md)
{
struct bt_mesh_ctl_friend_update *upd;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*upd));
- struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx);
struct os_mbuf *buf;
- __ASSERT_NO_MSG(sub != NULL);
+ __ASSERT_NO_MSG(frnd->subnet);
BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md);
net_buf_simple_init(sdu, 1);
upd = net_buf_simple_add(sdu, sizeof(*upd));
- upd->flags = bt_mesh_net_flags(sub);
+ upd->flags = bt_mesh_net_flags(frnd->subnet);
upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index);
upd->md = md;
@@ -550,7 +549,7 @@ static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md)
return buf;
}
-static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact)
+static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact)
{
struct bt_mesh_ctl_friend_sub_confirm *cfm;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*cfm));
@@ -587,16 +586,18 @@ done:
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, recv_delay(frnd));
- BT_DBG("Waiting RecvDelay of %d ms", (int) recv_delay(frnd));
+ k_delayed_work_submit(&frnd->timer, K_MSEC(delay));
+ BT_DBG("Waiting RecvDelay of %d ms", delay);
}
int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_friend *frnd;
- u8_t xact;
+ uint8_t xact;
if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
BT_WARN("Too short Friend Subscription Add");
@@ -631,7 +632,7 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_friend *frnd;
- u8_t xact;
+ uint8_t xact;
if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) {
BT_WARN("Too short Friend Subscription Remove");
@@ -668,7 +669,7 @@ static void enqueue_buf(struct bt_mesh_friend *frnd, struct os_mbuf *buf)
frnd->queue_size++;
}
-static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md)
+static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md)
{
struct os_mbuf *buf;
@@ -678,7 +679,6 @@ static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md)
return;
}
- frnd->sec_update = 0;
enqueue_buf(frnd, buf);
}
@@ -737,7 +737,7 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
return 0;
}
-static struct bt_mesh_friend *find_clear(u16_t prev_friend)
+static struct bt_mesh_friend *find_clear(uint16_t prev_friend)
{
int i;
@@ -768,13 +768,13 @@ static const struct bt_mesh_send_cb clear_sent_cb = {
static void send_friend_clear(struct bt_mesh_friend *frnd)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = frnd->net_idx,
+ .net_idx = frnd->subnet->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = frnd->clear.frnd,
.send_ttl = BT_MESH_TTL_MAX,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = frnd->subnet,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = bt_mesh_net_transmit_get(),
@@ -787,13 +787,13 @@ static void send_friend_clear(struct bt_mesh_friend *frnd)
BT_DBG("");
bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
- sizeof(req), NULL, &clear_sent_cb, frnd);
+ sizeof(req), &clear_sent_cb, frnd);
}
static void clear_timeout(struct ble_npl_event *work)
{
struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
- u32_t duration;
+ uint32_t duration;
BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd);
@@ -822,7 +822,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
{
struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd;
- u16_t lpn_addr, lpn_counter;
+ uint16_t lpn_addr, lpn_counter;
BT_DBG("");
@@ -857,7 +857,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx,
return 0;
}
-static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
+static void enqueue_offer(struct bt_mesh_friend *frnd, int8_t rssi)
{
struct bt_mesh_ctl_friend_offer *off;
struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*off));
@@ -882,11 +882,9 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi)
}
if (encrypt_friend_pdu(frnd, buf, true)) {
- return;
+ goto done;
}
- frnd->counter++;
-
if (frnd->last) {
net_buf_unref(frnd->last);
}
@@ -899,43 +897,45 @@ done:
}
#define RECV_WIN CONFIG_BT_MESH_FRIEND_RECV_WIN
-#define RSSI_FACT(crit) (((crit) >> 5) & (u8_t)BIT_MASK(2))
-#define RECV_WIN_FACT(crit) (((crit) >> 3) & (u8_t)BIT_MASK(2))
-#define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (u8_t)BIT_MASK(3))
-#define MIN_QUEUE_SIZE(crit) ((u32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
+#define RSSI_FACT(crit) (((crit) >> 5) & (uint8_t)BIT_MASK(2))
+#define RECV_WIN_FACT(crit) (((crit) >> 3) & (uint8_t)BIT_MASK(2))
+#define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (uint8_t)BIT_MASK(3))
+#define MIN_QUEUE_SIZE(crit) ((uint32_t)BIT(MIN_QUEUE_SIZE_LOG(crit)))
-static s32_t offer_delay(struct bt_mesh_friend *frnd, s8_t rssi, u8_t crit)
+static int32_t offer_delay(struct bt_mesh_friend *frnd, int8_t rssi, uint8_t crit)
{
/* Scaling factors. The actual values are 1, 1.5, 2 & 2.5, but we
* want to avoid floating-point arithmetic.
*/
- static const u8_t fact[] = { 10, 15, 20, 25 };
- s32_t delay;
+ static const uint8_t fact[] = { 10, 15, 20, 25 };
+ int32_t delay;
BT_DBG("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d",
fact[RECV_WIN_FACT(crit)], RECV_WIN,
fact[RSSI_FACT(crit)], rssi);
/* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */
- delay = (s32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
- delay -= (s32_t)fact[RSSI_FACT(crit)] * rssi;
+ delay = (int32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN;
+ delay -= (int32_t)fact[RSSI_FACT(crit)] * rssi;
delay /= 10;
BT_DBG("Local Delay calculated as %d ms", (int) delay);
- if (delay < 100) {
- return K_MSEC(100);
- }
-
- return K_MSEC(delay);
+ return MAX(delay, 100);
}
int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_req *msg = (void *)buf->om_data;
struct bt_mesh_friend *frnd = NULL;
- u32_t poll_to;
- int i;
+ uint32_t poll_to;
+ int32_t delay;
+ int i, err;
+
+ if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+ BT_WARN("Ignoring Friend request from local interface");
+ return 0;
+ }
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Request");
@@ -947,9 +947,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
return -EINVAL;
}
- poll_to = (((u32_t)msg->poll_to[0] << 16) |
- ((u32_t)msg->poll_to[1] << 8) |
- ((u32_t)msg->poll_to[2]));
+ poll_to = sys_get_be24(msg->poll_to);
if (poll_to <= 0x000009 || poll_to >= 0x34bc00) {
BT_WARN("Prohibited PollTimeout (0x%06x)", (unsigned) poll_to);
@@ -986,9 +984,8 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
}
for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
- if (!bt_mesh.frnd[i].valid) {
+ if (!bt_mesh.frnd[i].subnet) {
frnd = &bt_mesh.frnd[i];
- frnd->valid = 1;
break;
}
}
@@ -1001,12 +998,19 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
init_friend:
frnd->lpn = rx->ctx.addr;
frnd->num_elem = msg->num_elem;
- frnd->net_idx = rx->sub->net_idx;
+ frnd->subnet = rx->sub;
frnd->recv_delay = msg->recv_delay;
frnd->poll_to = poll_to * 100;
frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter);
frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr);
+ err = friend_cred_create(frnd, SUBNET_KEY_TX_IDX(frnd->subnet));
+ if (err) {
+ BT_ERR("Failed to create friend credentials");
+ friend_clear(frnd);
+ return -EIO;
+ }
+
BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums",
frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay,
(unsigned) frnd->poll_to);
@@ -1016,24 +1020,20 @@ init_friend:
clear_procedure_start(frnd);
}
- k_delayed_work_submit(&frnd->timer,
- offer_delay(frnd, rx->ctx.recv_rssi,
- msg->criteria));
-
- friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter,
- frnd->counter);
+ delay = offer_delay(frnd, rx->ctx.recv_rssi, msg->criteria);
+ k_delayed_work_submit(&frnd->timer, K_MSEC(delay));
enqueue_offer(frnd, rx->ctx.recv_rssi);
return 0;
}
-static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero)
+static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_zero)
{
struct os_mbuf *buf = (void *)net_buf_slist_peek_head(&seg->queue);
struct net_buf_simple_state state;
- u16_t buf_seq_zero;
- u16_t buf_src;
+ uint16_t buf_seq_zero;
+ uint16_t buf_src;
if (!buf) {
return false;
@@ -1050,8 +1050,8 @@ static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero)
}
static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
- u16_t src, u16_t seq_zero,
- u8_t seg_count)
+ uint16_t src, uint16_t seq_zero,
+ uint8_t seg_count)
{
struct bt_mesh_friend_seg *unassigned = NULL;
int i;
@@ -1077,7 +1077,7 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd,
static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
enum bt_mesh_friend_pdu_type type,
- u16_t src, u8_t seg_count,
+ uint16_t src, uint8_t seg_count,
struct os_mbuf *buf)
{
struct bt_mesh_friend_seg *seg;
@@ -1085,15 +1085,11 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
BT_DBG("type %u", type);
if (type == BT_MESH_FRIEND_PDU_SINGLE) {
- if (frnd->sec_update) {
- enqueue_update(frnd, 1);
- }
-
enqueue_buf(frnd, buf);
return;
}
- u16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
+ uint16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK);
seg = get_seg(frnd, src, seq_zero, seg_count);
if (!seg) {
@@ -1105,10 +1101,6 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
net_buf_slist_put(&seg->queue, buf);
if (type == BT_MESH_FRIEND_PDU_COMPLETE) {
- if (frnd->sec_update) {
- enqueue_update(frnd, 1);
- }
-
net_buf_slist_merge_slist(&frnd->queue, &seg->queue);
frnd->queue_size += seg->seg_count;
@@ -1119,7 +1111,7 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd,
}
}
-static void buf_send_start(u16_t duration, int err, void *user_data)
+static void buf_send_start(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_friend *frnd = user_data;
@@ -1128,7 +1120,7 @@ static void buf_send_start(u16_t duration, int err, void *user_data)
frnd->pending_buf = 0;
/* Friend Offer doesn't follow the re-sending semantics */
- if (!frnd->established) {
+ if (!frnd->established && frnd->last) {
net_buf_unref(frnd->last);
frnd->last = NULL;
}
@@ -1156,6 +1148,38 @@ static void buf_send_end(int err, void *user_data)
}
}
+static void update_overwrite(struct os_mbuf *buf, uint8_t md)
+{
+ struct net_buf_simple_state state;
+ struct bt_mesh_ctl_friend_update *upd;
+
+ if (buf->om_len != 16) {
+ return;
+ }
+
+ net_buf_simple_save(buf, &state);
+
+ net_buf_skip(buf, 1); /* skip IVI, NID */
+
+ if (!(net_buf_pull_u8(buf) >> 7)) {
+ goto end;
+ }
+
+ net_buf_skip(buf, 7); /* skip seqnum src dec*/
+
+ if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1))
+ != TRANS_CTL_OP_FRIEND_UPDATE) {
+ goto end;
+ }
+
+ upd = net_buf_pull_mem(buf, sizeof(*upd));
+ BT_DBG("Update Previous Friend Update MD 0x%02x -> 0x%02x", upd->md, md);
+ upd->md = md;
+
+end:
+ net_buf_simple_restore(buf, &state);
+}
+
static void friend_timeout(struct ble_npl_event *work)
{
struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work);
@@ -1164,6 +1188,8 @@ static void friend_timeout(struct ble_npl_event *work)
.end = buf_send_end,
};
+ uint8_t md;
+
__ASSERT_NO_MSG(frnd->pending_buf == 0);
BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn,
@@ -1189,12 +1215,17 @@ static void friend_timeout(struct ble_npl_event *work)
return;
}
+ md = (uint8_t)(net_buf_slist_peek_head(&frnd->queue) != NULL);
+
+ update_overwrite(frnd->last, md);
+
if (encrypt_friend_pdu(frnd, frnd->last, false)) {
return;
}
/* 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_DBG("Sending buf %p from Friend Queue of LPN 0x%04x",
frnd->last, frnd->lpn);
@@ -1206,8 +1237,56 @@ send_last:
bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd);
}
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ int i, err;
+
+ if (evt == BT_MESH_KEY_ADDED) {
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+ struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+ if (frnd->subnet != sub) {
+ continue;
+ }
+
+ switch (evt) {
+ case BT_MESH_KEY_DELETED:
+ BT_DBG("Cleared network for 0x%04x", frnd->lpn);
+ friend_clear(frnd);
+ break;
+ case BT_MESH_KEY_UPDATED:
+ BT_DBG("Generating new keys for 0x%04x", frnd->lpn);
+ err = friend_cred_create(frnd, 1);
+ if (err) {
+ BT_ERR("Failed updating friend cred for 0x%04x",
+ frnd->lpn);
+ friend_clear(frnd);
+ }
+ break;
+ case BT_MESH_KEY_SWAPPED:
+ enqueue_update(frnd, 0);
+ break;
+ case BT_MESH_KEY_REVOKED:
+ BT_DBG("Revoking old keys for 0x%04x", frnd->lpn);
+ memcpy(&frnd->cred[0], &frnd->cred[1],
+ sizeof(frnd->cred[0]));
+ memset(&frnd->cred[1], 0, sizeof(frnd->cred[1]));
+ enqueue_update(frnd, 0);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
int bt_mesh_friend_init(void)
{
+ if (!bt_mesh_subnet_cb_list[3]) {
+ bt_mesh_subnet_cb_list[3] = subnet_evt;
+ }
int rc;
int i;
@@ -1225,8 +1304,6 @@ int bt_mesh_friend_init(void)
struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
int j;
- frnd->net_idx = BT_MESH_KEY_UNUSED;
-
net_buf_slist_init(&frnd->queue);
k_delayed_work_init(&frnd->timer, friend_timeout);
@@ -1242,7 +1319,7 @@ int bt_mesh_friend_init(void)
return 0;
}
-static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src)
+static bool is_segack(struct os_mbuf *buf, uint64_t *seqauth, uint16_t src)
{
struct net_buf_simple_state state;
bool found = false;
@@ -1267,7 +1344,7 @@ static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src)
net_buf_skip(buf, 2); /* skip dst */
- if (TRANS_CTL_OP((u8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
+ if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) {
goto end;
}
@@ -1278,8 +1355,8 @@ end:
return found;
}
-static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
- u16_t src)
+static void friend_purge_old_ack(struct bt_mesh_friend *frnd, uint64_t *seq_auth,
+ uint16_t src)
{
struct os_mbuf *cur, *prev = NULL;
@@ -1304,7 +1381,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth,
static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
struct friend_pdu_info info;
@@ -1336,9 +1413,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
info.ctl = rx->ctl;
- info.seq[0] = (rx->seq >> 16);
- info.seq[1] = (rx->seq >> 8);
- info.seq[2] = rx->seq;
+ sys_put_be24(rx->seq, info.seq);
info.iv_index = BT_MESH_NET_IVI_RX(rx);
@@ -1357,7 +1432,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd,
static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
struct friend_pdu_info info;
@@ -1375,9 +1450,7 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
info.ttl = tx->ctx->send_ttl;
info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
- info.seq[0] = (bt_mesh.seq >> 16);
- info.seq[1] = (bt_mesh.seq >> 8);
- info.seq[2] = bt_mesh.seq;
+ sys_put_be24(bt_mesh.seq, info.seq);
info.iv_index = BT_MESH_NET_IVI_TX;
@@ -1400,8 +1473,8 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd,
BT_DBG("Queued message for LPN 0x%04x", frnd->lpn);
}
-static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
- u16_t addr)
+static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx,
+ uint16_t addr)
{
int i;
@@ -1409,7 +1482,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
return false;
}
- if (net_idx != frnd->net_idx) {
+ if (net_idx != frnd->subnet->net_idx) {
return false;
}
@@ -1426,7 +1499,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx,
return false;
}
-bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
+bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr)
{
int i;
@@ -1445,10 +1518,10 @@ bool bt_mesh_friend_match(u16_t net_idx, u16_t addr)
return false;
}
-static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr,
- u64_t *seq_auth, u8_t seg_count)
+static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr,
+ uint64_t *seq_auth, uint8_t seg_count)
{
- u32_t total = 0;
+ uint32_t total = 0;
int i;
if (seg_count > CONFIG_BT_MESH_FRIEND_QUEUE_SIZE) {
@@ -1476,8 +1549,8 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr,
return (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - total) > seg_count;
}
-bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
- u64_t *seq_auth, u8_t seg_count)
+bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
+ uint64_t *seq_auth, uint8_t seg_count)
{
bool someone_has_space = false, friend_match = false;
int i;
@@ -1511,11 +1584,11 @@ bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
return someone_has_space;
}
-static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr,
- u64_t *seq_auth, u8_t seg_count)
+static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t addr,
+ uint64_t *seq_auth, uint8_t seg_count)
{
bool pending_segments;
- u8_t avail_space;
+ uint8_t avail_space;
if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) {
return false;
@@ -1549,7 +1622,7 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr,
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
int i;
@@ -1572,6 +1645,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;
@@ -1584,7 +1662,7 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf)
{
bool matched = false;
@@ -1619,8 +1697,22 @@ bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
return matched;
}
-void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
- u16_t dst, u64_t *seq_auth)
+int bt_mesh_friend_terminate(uint16_t lpn_addr)
+{
+ struct bt_mesh_friend *frnd;
+
+ frnd = bt_mesh_friend_find(BT_MESH_KEY_ANY, lpn_addr, false, false);
+ if (!frnd) {
+ return -ENOENT;
+ }
+
+ friend_clear(frnd);
+
+ return 0;
+}
+
+void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
+ uint16_t dst, uint64_t *seq_auth)
{
int i;
@@ -1651,4 +1743,3 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
}
#endif /* MYNEWT_VAL(BLE_MESH_FRIEND) */
-#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h
index 361c1f097..04998c2e3 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/friend.h
@@ -17,29 +17,29 @@ enum bt_mesh_friend_pdu_type {
BT_MESH_FRIEND_PDU_COMPLETE,
};
-bool bt_mesh_friend_match(u16_t net_idx, u16_t addr);
+bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr);
-struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr,
+struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr,
bool valid, bool established);
-bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst,
- u64_t *seq_auth, u8_t seg_count);
+bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst,
+ uint64_t *seq_auth, uint8_t seg_count);
void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf);
bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx,
enum bt_mesh_friend_pdu_type type,
- u64_t *seq_auth, u8_t seg_count,
+ uint64_t *seq_auth, uint8_t seg_count,
struct os_mbuf *sbuf);
-void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src,
- u16_t dst, u64_t *seq_auth);
+void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src,
+ uint16_t dst, uint64_t *seq_auth);
-void bt_mesh_friend_sec_update(u16_t net_idx);
+void bt_mesh_friend_sec_update(uint16_t net_idx);
-void bt_mesh_friend_clear_net_idx(u16_t net_idx);
+void bt_mesh_friends_clear(void);
int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c
index 14e515b91..34d46cfd2 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/glue.c
@@ -18,10 +18,10 @@
*/
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
-#if MYNEWT_VAL(BLE_MESH)
-
#define MESH_LOG_MODULE BLE_MESH_LOG
+#if MYNEWT_VAL(BLE_MESH)
+
#include "../include/mesh/glue.h"
#include "adv.h"
#ifndef MYNEWT
@@ -32,7 +32,7 @@
#include "base64/base64.h"
#endif
-extern u8_t g_mesh_addr_type;
+extern uint8_t g_mesh_addr_type;
#if MYNEWT_VAL(BLE_EXT_ADV)
/* Store configuration for different bearers */
@@ -46,8 +46,8 @@ bt_hex(const void *buf, size_t len)
{
static const char hex[] = "0123456789abcdef";
static char hexbufs[4][137];
- static u8_t curbuf;
- const u8_t *b = buf;
+ static uint8_t curbuf;
+ const uint8_t *b = buf;
char *str;
int i;
@@ -239,6 +239,14 @@ net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val)
ASSERT_NOT_CHAIN(om);
}
+void
+net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val)
+{
+ val = htole32(val);
+ os_mbuf_append(om, &val, 3);
+ ASSERT_NOT_CHAIN(om);
+}
+
void
net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val)
{
@@ -294,6 +302,22 @@ net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val)
ASSERT_NOT_CHAIN(om);
}
+void
+net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val)
+{
+ uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len];
+
+ assert(headroom >= 3);
+ om->om_data -= 3;
+ put_be24(om->om_data, val);
+ om->om_len += 3;
+
+ if (om->om_pkthdr_len) {
+ OS_MBUF_PKTHDR(om)->omp_len += 3;
+ }
+ ASSERT_NOT_CHAIN(om);
+}
+
void
net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val)
{
@@ -358,7 +382,7 @@ k_fifo_is_empty(struct ble_npl_eventq *q)
return ble_npl_eventq_is_empty(q);
}
-void * net_buf_get(struct ble_npl_eventq *fifo, s32_t t)
+void * net_buf_get(struct ble_npl_eventq *fifo, int32_t t)
{
struct ble_npl_event *ev = ble_npl_eventq_get(fifo, 0);
@@ -409,6 +433,12 @@ k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f)
#endif
}
+bool
+k_delayed_work_pending(struct k_delayed_work *w)
+{
+ return ble_npl_callout_is_active(&w->work);
+}
+
void
k_delayed_work_cancel(struct k_delayed_work *w)
{
@@ -465,7 +495,7 @@ int64_t k_uptime_get(void)
return ble_npl_time_ticks_to_ms32(ble_npl_time_get());
}
-u32_t k_uptime_get_32(void)
+uint32_t k_uptime_get_32(void)
{
return k_uptime_get();
}
@@ -484,7 +514,7 @@ static uint8_t priv[32];
static bool has_pub = false;
int
-bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb)
+bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb)
{
uint8_t dh[32];
@@ -535,7 +565,7 @@ bt_pub_key_get(void)
}
static int
-set_ad(const struct bt_data *ad, size_t ad_len, u8_t *buf, u8_t *buf_len)
+set_ad(const struct bt_data *ad, size_t ad_len, uint8_t *buf, uint8_t *buf_len)
{
int i;
@@ -871,6 +901,52 @@ void net_buf_slist_merge_slist(struct net_buf_slist_t *list,
}
}
+/** Memory slab methods */
+extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem)
+{
+ **(char ***)mem = slab->free_list;
+ slab->free_list = *(char **)mem;
+ slab->num_used--;
+}
+
+extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem)
+{
+ int result;
+
+ if (slab->free_list != NULL) {
+ /* take a free block */
+ *mem = slab->free_list;
+ slab->free_list = *(char **)(slab->free_list);
+ slab->num_used++;
+ result = 0;
+ } else {
+ *mem = NULL;
+ result = -ENOMEM;
+ }
+ return result;
+}
+
+int create_free_list(struct k_mem_slab *slab)
+{
+ uint32_t j;
+ char *p;
+
+ if(((slab->block_size | (uintptr_t)slab->buffer) &
+ (sizeof(void *) - 1)) != 0) {
+ return -EINVAL;
+ }
+
+ slab->free_list = NULL;
+ p = slab->buffer;
+
+ for (j = 0U; j < slab->num_blocks; j++) {
+ *(char **)p = slab->free_list;
+ slab->free_list = p;
+ p += slab->block_size;
+ }
+ return 0;
+}
+
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
int settings_bytes_from_str(char *val_str, void *vp, int *len)
@@ -892,4 +968,4 @@ char *settings_str_from_bytes(const void *vp, int vp_len,
}
#endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */
-#endif
+#endif /* MYNEWT_VAL(BLE_MESH) */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c
index 3fc29e52f..40da8de6d 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_cli.c
@@ -23,15 +23,15 @@
#include "foundation.h"
#include "../include/mesh/health_cli.h"
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_health_cli *health_cli;
struct health_fault_param {
- u16_t cid;
- u8_t *expect_test_id;
- u8_t *test_id;
- u8_t *faults;
+ uint16_t cid;
+ uint8_t *expect_test_id;
+ uint8_t *test_id;
+ uint8_t *faults;
size_t *fault_count;
};
@@ -40,8 +40,8 @@ static void health_fault_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct health_fault_param *param;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
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,
@@ -86,8 +86,8 @@ static void health_current_status(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_cli *cli = model->user_data;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
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,
@@ -108,7 +108,7 @@ static void health_current_status(struct bt_mesh_model *model,
}
struct health_period_param {
- u8_t *divisor;
+ uint8_t *divisor;
};
static void health_period_status(struct bt_mesh_model *model,
@@ -134,7 +134,7 @@ static void health_period_status(struct bt_mesh_model *model,
}
struct health_attention_param {
- u8_t *attention;
+ uint8_t *attention;
};
static void health_attention_status(struct bt_mesh_model *model,
@@ -169,7 +169,7 @@ const struct bt_mesh_model_op bt_mesh_health_cli_op[] = {
BT_MESH_MODEL_OP_END,
};
-static int cli_prepare(void *param, u32_t op)
+static int cli_prepare(void *param, uint32_t op)
{
if (!health_cli) {
BT_ERR("No available Health Client context!");
@@ -204,12 +204,10 @@ static int cli_wait(void)
return err;
}
-int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *attention)
+int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_GET, 0);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -239,12 +237,11 @@ done:
return err;
}
-int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t attention, u8_t *updated_attention)
+int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
+ uint8_t *updated_attention)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_SET, 1);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -285,12 +282,10 @@ done:
return err;
}
-int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *divisor)
+int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_GET, 0);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -320,12 +315,11 @@ done:
return err;
}
-int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t divisor, u8_t *updated_divisor)
+int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
+ uint8_t *updated_divisor)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_SET, 1);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -366,13 +360,12 @@ done:
return err;
}
-int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t test_id, u8_t *faults,
- size_t *fault_count)
+int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t test_id, uint8_t *faults,
+ size_t *fault_count)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_TEST, 3);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -417,13 +410,12 @@ done:
return err;
}
-int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t *test_id, u8_t *faults,
- size_t *fault_count)
+int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults,
+ size_t *fault_count)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_CLEAR, 2);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -467,13 +459,12 @@ done:
return err;
}
-int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u16_t cid, u8_t *test_id, u8_t *faults,
- size_t *fault_count)
+int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults,
+ size_t *fault_count)
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_GET, 2);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = net_idx,
.app_idx = app_idx,
.addr = addr,
.send_ttl = BT_MESH_TTL_DEFAULT,
@@ -507,12 +498,12 @@ done:
return err;
}
-s32_t bt_mesh_health_cli_timeout_get(void)
+int32_t bt_mesh_health_cli_timeout_get(void)
{
return msg_timeout;
}
-void bt_mesh_health_cli_timeout_set(s32_t timeout)
+void bt_mesh_health_cli_timeout_set(int32_t timeout)
{
msg_timeout = timeout;
}
@@ -525,6 +516,7 @@ int bt_mesh_health_cli_set(struct bt_mesh_model *model)
}
health_cli = model->user_data;
+ msg_timeout = 2 * MSEC_PER_SEC;
return 0;
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c
index 7063d9203..d8951939a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/health_srv.c
@@ -29,11 +29,11 @@
struct bt_mesh_health_srv *health_srv;
static void health_get_registered(struct bt_mesh_model *mod,
- u16_t company_id,
+ uint16_t company_id,
struct os_mbuf *msg)
{
struct bt_mesh_health_srv *srv = mod->user_data;
- u8_t *test_id;
+ uint8_t *test_id;
BT_DBG("Company ID 0x%04x", company_id);
@@ -43,7 +43,7 @@ static void health_get_registered(struct bt_mesh_model *mod,
net_buf_simple_add_le16(msg, company_id);
if (srv->cb && srv->cb->fault_get_reg) {
- u8_t fault_count = net_buf_simple_tailroom(msg) - 4;
+ uint8_t fault_count = net_buf_simple_tailroom(msg) - 4;
int err;
err = srv->cb->fault_get_reg(mod, company_id, test_id,
@@ -66,9 +66,9 @@ static size_t health_get_current(struct bt_mesh_model *mod,
{
struct bt_mesh_health_srv *srv = mod->user_data;
const struct bt_mesh_comp *comp;
- u8_t *test_id, *company_ptr;
- u16_t company_id;
- u8_t fault_count;
+ 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);
@@ -106,7 +106,7 @@ static void health_fault_get(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -126,7 +126,7 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -143,7 +143,7 @@ static void health_fault_clear(struct bt_mesh_model *model,
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
+ uint16_t company_id;
company_id = net_buf_simple_pull_le16(buf);
@@ -167,8 +167,8 @@ static void health_fault_test_unrel(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
- u8_t test_id;
+ uint16_t company_id;
+ uint8_t test_id;
test_id = net_buf_simple_pull_u8(buf);
company_id = net_buf_simple_pull_le16(buf);
@@ -186,8 +186,8 @@ static void health_fault_test(struct bt_mesh_model *model,
{
struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX);
struct bt_mesh_health_srv *srv = model->user_data;
- u16_t company_id;
- u8_t test_id;
+ uint16_t company_id;
+ uint8_t test_id;
BT_DBG("");
@@ -221,7 +221,7 @@ static void send_attention_status(struct bt_mesh_model *model,
{
struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_STATUS, 1);
struct bt_mesh_health_srv *srv = model->user_data;
- u8_t time;
+ uint8_t time;
time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000;
BT_DBG("%u second%s", time, (time == 1) ? "" : "s");
@@ -250,7 +250,7 @@ static void attention_set_unrel(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t time;
+ uint8_t time;
time = net_buf_simple_pull_u8(buf);
@@ -299,7 +299,7 @@ static void health_period_set_unrel(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
- u8_t period;
+ uint8_t period;
period = net_buf_simple_pull_u8(buf);
if (period > 15) {
@@ -391,10 +391,6 @@ static int health_srv_init(struct bt_mesh_model *model)
struct bt_mesh_health_srv *srv = model->user_data;
if (!srv) {
- if (!bt_mesh_model_in_primary(model)) {
- return 0;
- }
-
BT_ERR("No Health Server context provided");
return -EINVAL;
}
@@ -422,7 +418,7 @@ const struct bt_mesh_model_cb bt_mesh_health_srv_cb = {
.init = health_srv_init,
};
-void bt_mesh_attention(struct bt_mesh_model *model, u8_t time)
+void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time)
{
struct bt_mesh_health_srv *srv;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/heartbeat.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/heartbeat.c
new file mode 100644
index 000000000..6948f20d0
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/heartbeat.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_MESH)
+
+#define MESH_LOG_MODULE BLE_MESH_HEARTBEAT_LOG
+
+#include "mesh_priv.h"
+#include "net.h"
+#include "rpl.h"
+#include "access.h"
+#include "lpn.h"
+#include "settings.h"
+#include "transport.h"
+#include "heartbeat.h"
+#include "foundation.h"
+#include "../include/mesh/glue.h"
+
+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 int64_t sub_remaining(void)
+{
+ if (sub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return 0U;
+ }
+
+ return k_delayed_work_remaining_get(&sub_timer) / 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));
+ }
+
+ if (pub.count != 0xffff) {
+ pub.count--;
+ }
+}
+
+static void notify_recv(uint8_t hops, uint16_t feat)
+{
+ sub.remaining = sub_remaining();
+
+ if (hb_cb.recv != NULL) {
+ hb_cb.recv(&sub, hops, feat);
+ }
+}
+
+static void notify_sub_end(void)
+{
+ sub.remaining = 0;
+
+ if (hb_cb.sub_end != NULL) {
+ hb_cb.sub_end(&sub);
+ }
+}
+
+static void sub_end(struct ble_npl_event *work)
+{
+ notify_sub_end();
+}
+
+static int heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data)
+{
+ uint16_t feat = 0U;
+ struct __packed {
+ uint8_t init_ttl;
+ uint16_t feat;
+ } hb;
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = pub.net_idx,
+ .app_idx = BT_MESH_KEY_UNUSED,
+ .addr = pub.dst,
+ .send_ttl = pub.ttl,
+ };
+ struct bt_mesh_net_tx tx = {
+ .sub = bt_mesh_subnet_get(pub.net_idx),
+ .ctx = &ctx,
+ .src = bt_mesh_primary_addr(),
+ .xmit = bt_mesh_net_transmit_get(),
+ };
+
+ /* Do nothing if heartbeat publication is not enabled */
+ if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return 0U;
+ }
+
+ hb.init_ttl = pub.ttl;
+
+ if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) {
+ feat |= BT_MESH_FEAT_RELAY;
+ }
+
+ if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
+ feat |= BT_MESH_FEAT_PROXY;
+ }
+
+ if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) {
+ feat |= BT_MESH_FEAT_FRIEND;
+ }
+
+ if (bt_mesh_lpn_established()) {
+ feat |= BT_MESH_FEAT_LOW_POWER;
+ }
+
+ hb.feat = sys_cpu_to_be16(feat);
+
+ BT_DBG("InitTTL %u feat 0x%04x", pub.ttl, feat);
+
+ return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
+ cb, cb_data);
+}
+
+static void hb_publish_start_cb(uint16_t duration, int err, void *cb_data)
+{
+ if (err) {
+ hb_publish_end_cb(err, cb_data);
+ }
+}
+
+static void hb_publish(struct ble_npl_event *work)
+{
+ static const struct bt_mesh_send_cb publish_cb = {
+ .start = hb_publish_start_cb,
+ .end = hb_publish_end_cb,
+ };
+ struct bt_mesh_subnet *sub;
+ int err;
+
+ BT_DBG("hb_pub.count: %u", pub.count);
+
+ sub = bt_mesh_subnet_get(pub.net_idx);
+ if (!sub) {
+ BT_ERR("No matching subnet for idx 0x%02x", pub.net_idx);
+ pub.dst = BT_MESH_ADDR_UNASSIGNED;
+ return;
+ }
+
+ if (pub.count == 0U) {
+ return;
+ }
+
+ err = heartbeat_send(&publish_cb, NULL);
+ if (err) {
+ hb_publish_end_cb(err, NULL);
+ }
+}
+
+int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t init_ttl, hops;
+ uint16_t feat;
+
+ if (buf->om_len < 3) {
+ BT_ERR("Too short heartbeat message");
+ return -EINVAL;
+ }
+
+ init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
+ feat = net_buf_simple_pull_be16(buf);
+
+ hops = (init_ttl - rx->ctx.recv_ttl + 1);
+
+ if (rx->ctx.addr != sub.src || rx->ctx.recv_dst != sub.dst) {
+ BT_DBG("No subscription for received heartbeat");
+ return 0;
+ }
+
+ if (!k_delayed_work_pending(&sub_timer)) {
+ BT_DBG("Heartbeat subscription period expired");
+ return 0;
+ }
+
+ sub.min_hops = MIN(sub.min_hops, hops);
+ sub.max_hops = MAX(sub.max_hops, hops);
+
+ if (sub.count < 0xffff) {
+ sub.count++;
+ }
+
+ BT_DBG("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x",
+ rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
+ (hops == 1U) ? "" : "s", feat);
+
+ notify_recv(hops, feat);
+
+ return 0;
+}
+
+static void pub_disable(void)
+{
+ BT_DBG("");
+
+ pub.dst = BT_MESH_ADDR_UNASSIGNED;
+ pub.count = 0U;
+ pub.ttl = 0U;
+ pub.period = 0U;
+
+ k_delayed_work_cancel(&pub_timer);
+}
+
+uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub)
+{
+ if (!new_pub || new_pub->dst == BT_MESH_ADDR_UNASSIGNED) {
+ pub_disable();
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS) &&
+ bt_mesh_is_provisioned()) {
+ bt_mesh_store_hb_pub();
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ if (!bt_mesh_subnet_get(new_pub->net_idx)) {
+ BT_ERR("Unknown NetKey 0x%04x", new_pub->net_idx);
+ return STATUS_INVALID_NETKEY;
+ }
+
+ new_pub->feat &= BT_MESH_FEAT_SUPPORTED;
+ pub = *new_pub;
+
+ if (!bt_mesh_is_provisioned()) {
+ return STATUS_SUCCESS;
+ }
+
+ /* The first Heartbeat message shall be published as soon as possible
+ * after the Heartbeat Publication Period state has been configured for
+ * periodic publishing.
+ */
+ if (pub.period && pub.count) {
+ k_delayed_work_submit(&pub_timer, K_NO_WAIT);
+ } else {
+ k_delayed_work_cancel(&pub_timer);
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_hb_pub();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get)
+{
+ *get = pub;
+}
+
+uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period)
+{
+ if (src != BT_MESH_ADDR_UNASSIGNED && !BT_MESH_ADDR_IS_UNICAST(src)) {
+ BT_WARN("Prohibited source address");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ if (BT_MESH_ADDR_IS_VIRTUAL(dst) || BT_MESH_ADDR_IS_RFU(dst) ||
+ (BT_MESH_ADDR_IS_UNICAST(dst) && dst != bt_mesh_primary_addr())) {
+ BT_WARN("Prohibited destination address");
+ return STATUS_INVALID_ADDRESS;
+ }
+
+ if (period > (1U << 16)) {
+ BT_WARN("Prohibited subscription period %u s", period);
+ return STATUS_CANNOT_SET;
+ }
+
+ /* Only an explicit address change to unassigned should trigger clearing
+ * of the values according to MESH/NODE/CFG/HBS/BV-02-C.
+ */
+ if (src == BT_MESH_ADDR_UNASSIGNED || dst == BT_MESH_ADDR_UNASSIGNED) {
+ sub.src = BT_MESH_ADDR_UNASSIGNED;
+ sub.dst = BT_MESH_ADDR_UNASSIGNED;
+ 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();
+ } else if (period) {
+ sub.src = src;
+ sub.dst = dst;
+ sub.min_hops = BT_MESH_TTL_MAX;
+ 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();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get)
+{
+ *get = sub;
+ get->remaining = sub_remaining();
+}
+
+void bt_mesh_hb_feature_changed(uint16_t features)
+{
+ if (pub.dst == BT_MESH_ADDR_UNASSIGNED) {
+ return;
+ }
+
+ if (!(pub.feat & features)) {
+ return;
+ }
+
+ heartbeat_send(NULL, NULL);
+}
+
+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);
+}
+
+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);
+ }
+}
+
+void bt_mesh_hb_suspend(void)
+{
+ k_delayed_work_cancel(&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);
+ }
+}
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/heartbeat.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/heartbeat.h
new file mode 100644
index 000000000..9cb0ca17e
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/heartbeat.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "../include/mesh/heartbeat.h"
+
+static inline uint16_t bt_mesh_hb_pwr2(uint8_t val)
+{
+ if (!val) {
+ return 0x0000;
+ } else if (val == 0xff || val == 0x11) {
+ return 0xffff;
+ } else {
+ return (1 << (val - 1));
+ }
+}
+
+static inline uint8_t bt_mesh_hb_log(uint32_t val)
+{
+ if (!val) {
+ return 0x00;
+ } else if (val == 0xffff) {
+ return 0xff;
+ } else {
+ return 32 - __builtin_clz(val);
+ }
+}
+
+void bt_mesh_hb_init(void);
+void bt_mesh_hb_start(void);
+void bt_mesh_hb_suspend(void);
+void bt_mesh_hb_resume(void);
+
+int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
+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);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c
index a390bf86b..fc8f66180 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.c
@@ -7,52 +7,52 @@
#include "light_model.h"
-static u8_t gen_onoff_state;
-static s16_t gen_level_state;
+static uint8_t gen_onoff_state;
+static int16_t gen_level_state;
static void update_light_state(void)
{
- console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (u16_t)gen_level_state);
+ console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (uint16_t)gen_level_state);
}
-int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state)
+int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state)
{
*state = gen_onoff_state;
return 0;
}
-int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state)
+int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state)
{
gen_onoff_state = state;
update_light_state();
return 0;
}
-int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level)
+int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level)
{
*level = gen_level_state;
return 0;
}
-int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level)
+int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level)
{
gen_level_state = level;
- if ((u16_t)gen_level_state > 0x0000) {
+ if ((uint16_t)gen_level_state > 0x0000) {
gen_onoff_state = 1;
}
- if ((u16_t)gen_level_state == 0x0000) {
+ if ((uint16_t)gen_level_state == 0x0000) {
gen_onoff_state = 0;
}
update_light_state();
return 0;
}
-int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness)
+int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness)
{
return light_model_gen_level_get(model, lightness);
}
-int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness)
+int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness)
{
return light_model_gen_level_set(model, lightness);
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h
index f3b1f7cb7..574db5484 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/light_model.h
@@ -9,11 +9,11 @@
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
#include "../include/mesh/mesh.h"
-int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state);
-int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state);
-int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level);
-int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level);
-int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness);
-int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness);
+int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state);
+int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state);
+int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level);
+int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level);
+int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness);
+int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness);
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c
index 5bb64b97d..cf0841507 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.c
@@ -21,6 +21,7 @@
#include "adv.h"
#include "net.h"
#include "transport.h"
+#include "heartbeat.h"
#include "access.h"
#include "beacon.h"
#include "foundation.h"
@@ -44,27 +45,33 @@
#define POLL_RETRY_TIMEOUT K_MSEC(100)
-#define REQ_RETRY_DURATION(lpn) (4 * (LPN_RECV_DELAY + (lpn)->adv_duration + \
- (lpn)->recv_win + POLL_RETRY_TIMEOUT))
+#define REQ_RETRY_DURATION(lpn) (LPN_RECV_DELAY + (lpn)->adv_duration + \
+ (lpn)->recv_win + POLL_RETRY_TIMEOUT)
#define POLL_TIMEOUT_INIT (MYNEWT_VAL(BLE_MESH_LPN_INIT_POLL_TIMEOUT) * 100)
-#define POLL_TIMEOUT_MAX(lpn) ((MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT) * 100) - \
- REQ_RETRY_DURATION(lpn))
-#define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 4)
-#define CLEAR_ATTEMPTS 2
+#define POLL_TIMEOUT (MYNEWT_VAL(BLE_MESH_LPN_RECV_DELAY) * 100)
+
+#define REQ_ATTEMPTS_MAX 6
+#define REQ_ATTEMPTS(lpn) MIN(REQ_ATTEMPTS_MAX, \
+ POLL_TIMEOUT / REQ_RETRY_DURATION(lpn))
+
+#define POLL_TIMEOUT_MAX(lpn) (POLL_TIMEOUT - \
+ (REQ_ATTEMPTS(lpn) * REQ_RETRY_DURATION(lpn)))
+
+#define CLEAR_ATTEMPTS 3
#define LPN_CRITERIA ((MYNEWT_VAL(BLE_MESH_LPN_MIN_QUEUE_SIZE)) | \
(MYNEWT_VAL(BLE_MESH_LPN_RSSI_FACTOR) << 3) | \
(MYNEWT_VAL(BLE_MESH_LPN_RECV_WIN_FACTOR) << 5))
-#define POLL_TO(to) { (u8_t)((to) >> 16), (u8_t)((to) >> 8), (u8_t)(to) }
+#define POLL_TO(to) { (uint8_t)((to) >> 16), (uint8_t)((to) >> 8), (uint8_t)(to) }
#define LPN_POLL_TO POLL_TO(MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT))
/* 2 transmissions, 20ms interval */
#define POLL_XMIT BT_MESH_TRANSMIT(1, 20)
-static void (*lpn_cb)(u16_t friend_addr, bool established);
+static void (*lpn_cb)(uint16_t friend_addr, bool established);
#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG
static const char *state2str(int state)
@@ -147,10 +154,7 @@ static void friend_clear_sent(int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- /* We're switching away from Low Power behavior, so permanently
- * enable scanning.
- */
- bt_mesh_scan_enable();
+ /* Scanning will enable if lpn state still enabled */
lpn->req_attempts++;
@@ -172,31 +176,30 @@ static const struct bt_mesh_send_cb clear_sent_cb = {
static int send_friend_clear(void)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = bt_mesh.lpn.sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = bt_mesh.lpn.frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = bt_mesh.lpn.sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = bt_mesh_net_transmit_get(),
};
struct bt_mesh_ctl_friend_clear req = {
.lpn_addr = sys_cpu_to_be16(tx.src),
- .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter),
+ .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.lpn_counter),
};
BT_DBG("");
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req,
- sizeof(req), NULL, &clear_sent_cb, NULL);
+ sizeof(req), &clear_sent_cb, NULL);
}
static void clear_friendship(bool force, bool disable)
{
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
BT_DBG("force %u disable %u", force, disable);
@@ -212,8 +215,6 @@ static void clear_friendship(bool force, bool disable)
k_delayed_work_cancel(&lpn->timer);
- friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd);
-
if (lpn->clear_success) {
lpn->old_friend = BT_MESH_ADDR_UNASSIGNED;
} else {
@@ -233,6 +234,7 @@ static void clear_friendship(bool force, bool disable)
lpn->sent_req = 0;
lpn->established = 0;
lpn->clear_success = 0;
+ lpn->sub = NULL;
group_zero(lpn->added);
group_zero(lpn->pending);
@@ -244,9 +246,7 @@ static void clear_friendship(bool force, bool disable)
*/
lpn->groups_changed = 1;
- if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
- bt_mesh_heartbeat_send();
- }
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
if (disable) {
lpn_set_state(BT_MESH_LPN_DISABLED);
@@ -257,7 +257,7 @@ static void clear_friendship(bool force, bool disable)
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
}
-static void friend_req_sent(u16_t duration, int err, void *user_data)
+static void friend_req_sent(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
@@ -286,33 +286,43 @@ static int send_friend_req(struct bt_mesh_lpn *lpn)
{
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = BT_MESH_ADDR_FRIENDS,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
};
+
+ lpn->lpn_counter++;
+
struct bt_mesh_ctl_friend_req req = {
.criteria = LPN_CRITERIA,
.recv_delay = LPN_RECV_DELAY,
.poll_to = LPN_POLL_TO,
- .prev_addr = lpn->old_friend,
+ .prev_addr = sys_cpu_to_be16(lpn->old_friend),
.num_elem = comp->elem_count,
- .lpn_counter = sys_cpu_to_be16(lpn->counter),
+ .lpn_counter = sys_cpu_to_be16(lpn->lpn_counter),
};
BT_DBG("");
+ lpn->sub = bt_mesh_subnet_next(NULL);
+ if (!lpn->sub) {
+ BT_ERR("No subnets, can't start LPN mode");
+ return -ENOENT;
+ }
+
+ ctx.net_idx = lpn->sub->net_idx;
+ tx.sub = lpn->sub;
+
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req,
- sizeof(req), NULL, &friend_req_sent_cb, NULL);
+ sizeof(req), &friend_req_sent_cb, NULL);
}
-static void req_sent(u16_t duration, int err, void *user_data)
+static void req_sent(uint16_t duration, int err, void *user_data)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
@@ -339,6 +349,7 @@ static void req_sent(u16_t duration, int err, void *user_data)
k_delayed_work_submit(&lpn->timer,
LPN_RECV_DELAY - SCAN_LATENCY);
} else {
+ lpn_set_state(BT_MESH_LPN_WAIT_UPDATE);
k_delayed_work_submit(&lpn->timer,
LPN_RECV_DELAY + duration +
lpn->recv_win);
@@ -352,20 +363,20 @@ static const struct bt_mesh_send_cb req_sent_cb = {
static int send_friend_poll(void)
{
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = bt_mesh.lpn.sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = bt_mesh.lpn.frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = bt_mesh.lpn.sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
.friend_cred = true,
};
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u8_t fsn = lpn->fsn;
+ uint8_t fsn = lpn->fsn;
int err;
BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req);
@@ -379,7 +390,7 @@ static int send_friend_poll(void)
}
err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1,
- NULL, &req_sent_cb, NULL);
+ &req_sent_cb, NULL);
if (err == 0) {
lpn->pending_poll = 0;
lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL;
@@ -479,14 +490,22 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx)
send_friend_poll();
}
+static int friend_cred_create(struct bt_mesh_net_cred *cred,
+ const uint8_t key[16])
+{
+ struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+
+ return bt_mesh_friend_cred_create(cred, bt_mesh_primary_addr(),
+ lpn->frnd, lpn->lpn_counter,
+ lpn->frnd_counter, key);
+}
+
int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
struct os_mbuf *buf)
{
struct bt_mesh_ctl_friend_offer *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- struct bt_mesh_subnet *sub = rx->sub;
- struct friend_cred *cred;
- u16_t frnd_counter;
+ uint16_t frnd_counter;
int err;
if (buf->om_len < sizeof(*msg)) {
@@ -510,16 +529,24 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi,
frnd_counter);
+ lpn->frnd_counter = frnd_counter;
lpn->frnd = rx->ctx.addr;
- cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter);
- if (!cred) {
- lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
- return -ENOMEM;
+ /* Create friend credentials for each of the valid keys in the
+ * friendship subnet:
+ */
+ for (int i = 0; i < ARRAY_SIZE(lpn->cred); i++) {
+ if (!lpn->sub->keys[i].valid) {
+ continue;
+ }
+
+ err = friend_cred_create(&lpn->cred[i], lpn->sub->keys[i].net);
+ if (err) {
+ lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
+ return err;
+ }
}
-
/* TODO: Add offer acceptance criteria check */
-
k_delayed_work_cancel(&lpn->timer);
lpn->recv_win = msg->recv_win;
@@ -527,15 +554,13 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx,
err = send_friend_poll();
if (err) {
- friend_cred_clear(cred);
+ lpn->sub = NULL;
lpn->frnd = BT_MESH_ADDR_UNASSIGNED;
lpn->recv_win = 0;
lpn->queue_size = 0;
return err;
}
- lpn->counter++;
-
return 0;
}
@@ -544,7 +569,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
{
struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u16_t addr, counter;
+ uint16_t addr, counter;
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Clear Confirm");
@@ -561,7 +586,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter);
- if (addr != bt_mesh_primary_addr() || counter != lpn->counter) {
+ if (addr != bt_mesh_primary_addr() || counter != lpn->lpn_counter) {
BT_WARN("Invalid parameters in Friend Clear Confirm");
return 0;
}
@@ -572,10 +597,10 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx,
return 0;
}
-static void lpn_group_add(u16_t group)
+static void lpn_group_add(uint16_t group)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
- u16_t *free_slot = NULL;
+ uint16_t *free_slot = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) {
@@ -598,7 +623,7 @@ static void lpn_group_add(u16_t group)
lpn->groups_changed = 1;
}
-static void lpn_group_del(u16_t group)
+static void lpn_group_del(uint16_t group)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
int i;
@@ -629,18 +654,18 @@ static inline int group_popcount(atomic_t *target)
#endif
}
-static bool sub_update(u8_t op)
+static bool sub_update(uint8_t op)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
int added_count = group_popcount(lpn->added);
struct bt_mesh_msg_ctx ctx = {
- .net_idx = bt_mesh.sub[0].net_idx,
+ .net_idx = lpn->sub->net_idx,
.app_idx = BT_MESH_KEY_UNUSED,
.addr = lpn->frnd,
.send_ttl = 0,
};
struct bt_mesh_net_tx tx = {
- .sub = &bt_mesh.sub[0],
+ .sub = lpn->sub,
.ctx = &ctx,
.src = bt_mesh_primary_addr(),
.xmit = POLL_XMIT,
@@ -690,8 +715,8 @@ static bool sub_update(u8_t op)
req.xact = lpn->xact_next++;
- if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, NULL,
- &req_sent_cb, NULL) < 0) {
+ if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2,
+ &req_sent_cb, NULL) < 0) {
group_zero(lpn->pending);
return false;
}
@@ -713,7 +738,7 @@ static void update_timeout(struct bt_mesh_lpn *lpn)
bt_mesh_scan_disable();
}
- if (lpn->req_attempts < 6) {
+ if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
BT_WARN("Retrying first Friend Poll");
lpn->sent_req = 0;
if (send_friend_poll() == 0) {
@@ -761,14 +786,14 @@ static void lpn_timeout(struct ble_npl_event *work)
if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) {
bt_mesh_scan_disable();
}
- lpn->counter++;
+ lpn->lpn_counter++;
lpn_set_state(BT_MESH_LPN_ENABLED);
lpn->sent_req = 0U;
k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT);
break;
case BT_MESH_LPN_ESTABLISHED:
if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) {
- u8_t req = lpn->sent_req;
+ uint8_t req = lpn->sent_req;
lpn->sent_req = 0;
@@ -802,7 +827,7 @@ static void lpn_timeout(struct ble_npl_event *work)
}
}
-void bt_mesh_lpn_group_add(u16_t group)
+void bt_mesh_lpn_group_add(uint16_t group)
{
BT_DBG("group 0x%04x", group);
@@ -815,7 +840,7 @@ void bt_mesh_lpn_group_add(u16_t group)
sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD);
}
-void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
+void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count)
{
int i;
@@ -833,7 +858,7 @@ void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count)
sub_update(TRANS_CTL_OP_FRIEND_SUB_REM);
}
-static s32_t poll_timeout(struct bt_mesh_lpn *lpn)
+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()) {
@@ -910,7 +935,9 @@ int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx,
}
if (!lpn->sent_req) {
- k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
+ int32_t timeout = poll_timeout(lpn);
+
+ k_delayed_work_submit(&lpn->timer, K_MSEC(timeout));
}
return 0;
@@ -922,7 +949,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
struct bt_mesh_ctl_friend_update *msg = (void *)buf->om_data;
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
struct bt_mesh_subnet *sub = rx->sub;
- u32_t iv_index;
+ uint32_t iv_index;
if (buf->om_len < sizeof(*msg)) {
BT_WARN("Too short Friend Update");
@@ -946,8 +973,6 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
}
if (!lpn->established) {
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
-
/* This is normally checked on the transport layer, however
* in this state we're also still accepting master
* credentials so we need to ensure the right ones (Friend
@@ -962,9 +987,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
BT_INFO("Friendship established with 0x%04x", lpn->frnd);
- if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) {
- bt_mesh_heartbeat_send();
- }
+ bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER);
if (lpn_cb) {
lpn_cb(lpn->frnd, true);
@@ -982,11 +1005,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
BT_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags,
(unsigned) iv_index, msg->md);
- if (bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags),
- rx->new_key)) {
- bt_mesh_net_beacon_update(sub);
- }
-
+ bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags), rx->new_key);
bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(msg->flags));
if (lpn->groups_changed) {
@@ -1004,7 +1023,9 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx,
}
if (!lpn->sent_req) {
- k_delayed_work_submit(&lpn->timer, poll_timeout(lpn));
+ int32_t timeout = poll_timeout(lpn);
+
+ k_delayed_work_submit(&lpn->timer, K_MSEC(timeout));
}
return 0;
@@ -1021,17 +1042,41 @@ int bt_mesh_lpn_poll(void)
return send_friend_poll();
}
-void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established))
+void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established))
{
lpn_cb = cb;
}
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ switch (evt) {
+ case BT_MESH_KEY_DELETED:
+ if (sub == bt_mesh.lpn.sub) {
+ BT_DBG("NetKey deleted");
+ clear_friendship(true, false);
+ }
+ break;
+ case BT_MESH_KEY_UPDATED:
+ BT_DBG("NetKey updated");
+ friend_cred_create(&bt_mesh.lpn.cred[1], sub->keys[1].net);
+ break;
+ default:
+ break;
+ }
+}
+
int bt_mesh_lpn_init(void)
{
struct bt_mesh_lpn *lpn = &bt_mesh.lpn;
+ if (!bt_mesh_subnet_cb_list[2]) {
+ bt_mesh_subnet_cb_list[2] = subnet_evt;
+ }
+
BT_DBG("");
+ lpn->groups_changed = 0;
+
k_delayed_work_init(&lpn->timer, lpn_timeout);
if (lpn->state == BT_MESH_LPN_ENABLED) {
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h
index e53c81d3d..34f339052 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/lpn.h
@@ -28,7 +28,7 @@ static inline bool bt_mesh_lpn_established(void)
#endif
}
-static inline bool bt_mesh_lpn_match(u16_t addr)
+static inline bool bt_mesh_lpn_match(uint16_t addr)
{
#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
if (bt_mesh_lpn_established()) {
@@ -58,8 +58,8 @@ static inline bool bt_mesh_lpn_timer(void)
void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx);
-void bt_mesh_lpn_group_add(u16_t group);
-void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count);
+void bt_mesh_lpn_group_add(uint16_t group);
+void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count);
void bt_mesh_lpn_disable(bool force);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c
index 7ad1264ae..c896f0157 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh.c
@@ -20,7 +20,12 @@
#include "adv.h"
#include "prov.h"
+#include "provisioner.h"
#include "net.h"
+#include "subnet.h"
+#include "app_keys.h"
+#include "rpl.h"
+#include "cfg.h"
#include "beacon.h"
#include "lpn.h"
#include "friend.h"
@@ -28,16 +33,18 @@
#include "access.h"
#include "foundation.h"
#include "proxy.h"
+#include "heartbeat.h"
#include "shell.h"
#include "mesh_priv.h"
#include "settings.h"
-u8_t g_mesh_addr_type;
+
+uint8_t g_mesh_addr_type;
static struct ble_gap_event_listener mesh_event_listener;
-int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
- u8_t flags, u32_t iv_index, u16_t addr,
- const u8_t dev_key[16])
+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;
@@ -60,6 +67,53 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
pb_gatt_enabled = false;
}
+ /*
+ * FIXME:
+ * Should net_key and iv_index be over-ridden?
+ */
+ if (IS_ENABLED(BLE_MESH_CDB)) {
+ 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");
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -EINVAL;
+ }
+
+ if (!bt_mesh_cdb_subnet_get(net_idx)) {
+ BT_ERR("No subnet with idx %d", net_idx);
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -ENOENT;
+ }
+
+ prov = bt_mesh_prov_get();
+ node = bt_mesh_cdb_node_alloc(prov->uuid, addr,
+ comp->elem_count, net_idx);
+ if (node == NULL) {
+ BT_ERR("Failed to allocate database node");
+ atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
+ return -ENOMEM;
+ }
+
+ addr = node->addr;
+ iv_index = bt_mesh_cdb.iv_index;
+ memcpy(node->dev_key, dev_key, 16);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+ }
+
err = bt_mesh_net_create(net_idx, flags, net_key, iv_index);
if (err) {
atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID);
@@ -77,20 +131,18 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx,
memcpy(bt_mesh.dev_key, dev_key, 16);
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- BT_DBG("Storing network information persistently");
- bt_mesh_store_net();
- bt_mesh_store_subnet(&bt_mesh.sub[0]);
- bt_mesh_store_iv(false);
+ if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
+ IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
+ bt_mesh_lpn_group_add(BT_MESH_ADDR_ALL_NODES);
}
- bt_mesh_net_start();
+ bt_mesh_start();
return 0;
}
-int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration)
+int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
{
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
return -EINVAL;
@@ -124,25 +176,30 @@ void bt_mesh_reset(void)
bt_mesh_cfg_reset();
- bt_mesh_rx_reset();
- bt_mesh_tx_reset();
+ bt_mesh_trans_reset();
+ bt_mesh_app_keys_reset();
+ bt_mesh_net_keys_reset();
+
+ bt_mesh_net_loopback_clear(BT_MESH_KEY_ANY);
if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) {
+ if (IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) {
+ uint16_t group = BT_MESH_ADDR_ALL_NODES;
+
+ bt_mesh_lpn_group_del(&group, 1);
+ }
+
bt_mesh_lpn_disable(true);
}
if ((MYNEWT_VAL(BLE_MESH_FRIEND))) {
- bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY);
+ bt_mesh_friends_clear();
}
if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
bt_mesh_proxy_gatt_disable();
}
- if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) {
- bt_mesh_proxy_prov_enable();
- }
-
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_clear_net();
}
@@ -164,55 +221,6 @@ bool bt_mesh_is_provisioned(void)
return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID);
}
-int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
-{
- if (bt_mesh_is_provisioned()) {
- return -EALREADY;
- }
-
- char uuid_buf[BLE_UUID_STR_LEN];
- const struct bt_mesh_prov *prov = bt_mesh_prov_get();
- ble_uuid_t *uuid = BLE_UUID128_DECLARE();
-
- memcpy(BLE_UUID128(uuid)->value, prov->uuid, 16);
- BT_INFO("Device UUID: %s", ble_uuid_to_str(uuid, uuid_buf));
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
- (bearers & BT_MESH_PROV_ADV)) {
- /* Make sure we're scanning for provisioning inviations */
- bt_mesh_scan_enable();
- /* Enable unprovisioned beacon sending */
- bt_mesh_beacon_enable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
- (bearers & BT_MESH_PROV_GATT)) {
- bt_mesh_proxy_prov_enable();
- bt_mesh_adv_update();
- }
-
- return 0;
-}
-
-int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
-{
- if (bt_mesh_is_provisioned()) {
- return -EALREADY;
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
- (bearers & BT_MESH_PROV_ADV)) {
- bt_mesh_beacon_disable();
- bt_mesh_scan_disable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
- (bearers & BT_MESH_PROV_GATT)) {
- bt_mesh_proxy_prov_disable(true);
- }
-
- return 0;
-}
static int bt_mesh_gap_event(struct ble_gap_event *event, void *arg)
{
@@ -253,9 +261,9 @@ int bt_mesh_suspend(void)
return err;
}
- bt_mesh_hb_pub_disable();
+ bt_mesh_hb_suspend();
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+ if (bt_mesh_beacon_enabled()) {
bt_mesh_beacon_disable();
}
@@ -268,7 +276,7 @@ static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
bool vnd, bool primary, void *user_data)
{
if (mod->pub && mod->pub->update) {
- s32_t period_ms = bt_mesh_model_pub_period_get(mod);
+ int32_t period_ms = bt_mesh_model_pub_period_get(mod);
if (period_ms) {
k_delayed_work_submit(&mod->pub->timer, period_ms);
@@ -295,7 +303,9 @@ int bt_mesh_resume(void)
return err;
}
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
+ bt_mesh_hb_resume();
+
+ if (bt_mesh_beacon_enabled()) {
bt_mesh_beacon_enable();
}
@@ -319,6 +329,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) {
@@ -326,39 +340,66 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov,
}
#endif
-#if (MYNEWT_VAL(BLE_MESH_PROXY))
- bt_mesh_proxy_init();
-#endif
-
-#if (MYNEWT_VAL(BLE_MESH_PROV))
- /* Need this to proper link.rx.buf allocation */
- bt_mesh_prov_reset_link();
-#endif
-
+ bt_mesh_cfg_init();
bt_mesh_net_init();
bt_mesh_trans_init();
+ bt_mesh_hb_init();
bt_mesh_beacon_init();
bt_mesh_adv_init();
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- /* Make sure we're scanning for provisioning inviations */
- bt_mesh_scan_enable();
- /* Enable unprovisioned beacon sending */
-
- bt_mesh_beacon_enable();
-#endif
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- bt_mesh_proxy_prov_enable();
-#endif
-
- ble_gap_event_listener_register(&mesh_event_listener,
- bt_mesh_gap_event, NULL);
-
#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
bt_mesh_settings_init();
#endif
+ ble_gap_event_listener_register(&mesh_event_listener,
+ bt_mesh_gap_event, NULL);
+
+ return 0;
+}
+
+static void model_start(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
+ bool vnd, bool primary, void *user_data)
+{
+ if (mod->cb && mod->cb->start) {
+ mod->cb->start(mod);
+ }
+}
+
+int bt_mesh_start(void)
+{
+ if (bt_mesh_beacon_enabled()) {
+ bt_mesh_beacon_enable();
+ } else {
+ 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();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
+ bt_mesh_lpn_init();
+ } else {
+ bt_mesh_scan_enable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ bt_mesh_friend_init();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
+ struct bt_mesh_subnet *sub = bt_mesh_subnet_next(NULL);
+ uint16_t addr = bt_mesh_primary_addr();
+
+ bt_mesh_prov_complete(sub->net_idx, addr);
+ }
+
+ bt_mesh_hb_start();
+
+ bt_mesh_model_foreach(model_start, NULL);
+
return 0;
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh_priv.h
index f09bb2309..213f54377 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh_priv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/mesh_priv.h
@@ -8,14 +8,28 @@
#ifndef __MESH_PRIV_H
#define __MESH_PRIV_H
+#include
+#include
+
#define BT_MESH_KEY_PRIMARY 0x0000
#define BT_MESH_KEY_ANY 0xffff
-#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
-#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
-#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
-#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
+enum bt_mesh_key_evt {
+ BT_MESH_KEY_ADDED, /* New key added */
+ BT_MESH_KEY_DELETED, /* Existing key deleted */
+ BT_MESH_KEY_UPDATED, /* KR phase 1, second key added */
+ BT_MESH_KEY_SWAPPED, /* KR phase 2, now sending on second key */
+ BT_MESH_KEY_REVOKED, /* KR phase 3, old key removed */
+};
+
+/** Appkey callback. Instantiate with @ref BT_MESH_APP_KEY_CB */
+struct bt_mesh_app_key_cb {
+ void (*evt_handler)(uint16_t app_idx, uint16_t net_idx,
+ enum bt_mesh_key_evt evt);
+};
+
struct bt_mesh_net;
+int bt_mesh_start(void);
#define OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01)
#define OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c
index c8b10df0c..41b03320d 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_cli.c
@@ -13,19 +13,19 @@
#include "../include/mesh/model_cli.h"
#include "mesh_priv.h"
-static s32_t msg_timeout = K_SECONDS(5);
+static int32_t msg_timeout = K_SECONDS(5);
static struct bt_mesh_gen_model_cli *gen_onoff_cli;
static struct bt_mesh_gen_model_cli *gen_level_cli;
-static u8_t transaction_id = 0;
+static uint8_t transaction_id = 0;
struct gen_onoff_param {
- u8_t *state;
+ uint8_t *state;
};
struct gen_level_param {
- s16_t *level;
+ int16_t *level;
};
static void gen_onoff_status(struct bt_mesh_model *model,
@@ -34,7 +34,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_model_cli *cli = model->user_data;
struct gen_onoff_param *param;
- u8_t state;
+ uint8_t state;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -64,7 +64,7 @@ static void gen_level_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_model_cli *cli = model->user_data;
struct gen_level_param *param;
- s16_t level;
+ int16_t level;
BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s",
@@ -140,7 +140,7 @@ const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb = {
.init = level_cli_init,
};
-static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
+static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, uint32_t op)
{
int err;
@@ -157,8 +157,8 @@ static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op)
return err;
}
-int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t *state)
+int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -186,8 +186,8 @@ done:
return err;
}
-int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- u8_t val, u8_t *state)
+int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ uint8_t val, uint8_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -229,8 +229,8 @@ done:
return err;
}
-int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx,
- s16_t *level)
+int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t *level)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4);
struct bt_mesh_msg_ctx ctx = {
@@ -258,8 +258,8 @@ done:
return err;
}
-int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx,
- s16_t val, s16_t *state)
+int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx,
+ int16_t val, int16_t *state)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4);
struct bt_mesh_msg_ctx ctx = {
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c
index e7bbf38d0..db7407a38 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/model_srv.c
@@ -22,7 +22,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(3);
- u8_t *state;
+ uint8_t *state;
bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_STATUS);
state = net_buf_simple_add(msg, 1);
@@ -53,7 +53,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model,
struct os_mbuf *buf)
{
struct bt_mesh_gen_onoff_srv *cb = model->user_data;
- u8_t state;
+ uint8_t state;
state = buf->om_data[0];
@@ -79,7 +79,7 @@ static void gen_level_status(struct bt_mesh_model *model,
{
struct bt_mesh_gen_level_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
- s16_t *level;
+ int16_t *level;
bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_STATUS);
level = net_buf_simple_add(msg, 2);
@@ -109,9 +109,9 @@ static void 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;
- s16_t level;
+ int16_t level;
- level = (s16_t) net_buf_simple_pull_le16(buf);
+ level = (int16_t) net_buf_simple_pull_le16(buf);
BT_DBG("level: %d", level);
if (cb && cb->set) {
@@ -132,7 +132,7 @@ static void light_lightness_status(struct bt_mesh_model *model,
{
struct bt_mesh_light_lightness_srv *cb = model->user_data;
struct os_mbuf *msg = NET_BUF_SIMPLE(4);
- s16_t *lightness;
+ int16_t *lightness;
bt_mesh_model_msg_init(msg, OP_LIGHT_LIGHTNESS_STATUS);
lightness = net_buf_simple_add(msg, 2);
@@ -162,9 +162,9 @@ static void 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;
- s16_t lightness;
+ int16_t lightness;
- lightness = (s16_t) net_buf_simple_pull_le16(buf);
+ lightness = (int16_t) net_buf_simple_pull_le16(buf);
BT_DBG("lightness: %d", lightness);
if (cb && cb->set) {
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c
index b8e48d6ed..11728cf06 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.c
@@ -22,6 +22,7 @@
#include "adv.h"
#include "mesh_priv.h"
#include "net.h"
+#include "rpl.h"
#include "lpn.h"
#include "friend.h"
#include "proxy.h"
@@ -31,6 +32,9 @@
#include "beacon.h"
#include "settings.h"
#include "prov.h"
+#include "cfg.h"
+#include "../include/mesh/glue.h"
+#include "../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
@@ -40,6 +44,10 @@
*/
#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))
+
/* Seq limit after IV Update is triggered */
#define IV_UPDATE_SEQ_LIMIT 8000000
@@ -47,54 +55,34 @@
#define NID(pdu) ((pdu)[0] & 0x7f)
#define CTL(pdu) ((pdu)[1] >> 7)
#define TTL(pdu) ((pdu)[1] & 0x7f)
-#define SEQ(pdu) (((u32_t)(pdu)[2] << 16) | \
- ((u32_t)(pdu)[3] << 8) | (u32_t)(pdu)[4]);
+#define SEQ(pdu) (sys_get_be24(&pdu[2]))
#define SRC(pdu) (sys_get_be16(&(pdu)[5]))
#define DST(pdu) (sys_get_be16(&(pdu)[7]))
-/* Determine how many friendship credentials we need */
-#if (MYNEWT_VAL(BLE_MESH_FRIEND))
-#define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT)
-#elif (MYNEWT_VAL(BLE_MESH_LOW_POWER))
-#define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)
-#else
-#define FRIEND_CRED_COUNT 0
-#endif
-
-static struct friend_cred friend_cred[FRIEND_CRED_COUNT];
-
-static u64_t msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
-static u16_t msg_cache_next;
+static struct {
+ uint32_t src : 15, /* MSb of source is always 0 */
+ seq : 17;
+} msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
+static uint16_t msg_cache_next;
/* Singleton network context (the implementation only supports one) */
struct bt_mesh_net bt_mesh = {
.local_queue = STAILQ_HEAD_INITIALIZER(bt_mesh.local_queue),
- .sub = {
- [0 ... (MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
- .app_keys = {
- [0 ... (MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT) - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- .nodes = {
- [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = {
- .net_idx = BT_MESH_KEY_UNUSED,
- }
- },
-#endif
};
-static u32_t dup_cache[4];
+static struct os_mbuf_pool loopback_os_mbuf_pool;
+static struct os_mempool loopback_buf_mempool;
+os_membuf_t loopback_mbuf_membuf[
+ OS_MEMPOOL_SIZE(LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE,
+ MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS))];
+
+static uint32_t dup_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)];
static int dup_cache_next;
static bool check_dup(struct os_mbuf *data)
{
- const u8_t *tail = net_buf_simple_tail(data);
- u32_t val;
+ const uint8_t *tail = net_buf_simple_tail(data);
+ uint32_t val;
int i;
val = sys_get_be32(tail - 4) ^ sys_get_be32(tail - 8);
@@ -111,364 +99,52 @@ static bool check_dup(struct os_mbuf *data)
return false;
}
-static u64_t msg_hash(struct bt_mesh_net_rx *rx, struct os_mbuf *pdu)
+static bool msg_cache_match(struct os_mbuf *pdu)
{
- u32_t hash1, hash2;
-
- /* Three least significant bytes of IVI + first byte of SEQ */
- hash1 = (BT_MESH_NET_IVI_RX(rx) << 8) | pdu->om_data[2];
-
- /* Two last bytes of SEQ + SRC */
- memcpy(&hash2, &pdu->om_data[3], 4);
-
- return (u64_t)hash1 << 32 | (u64_t)hash2;
-}
-
-static bool msg_cache_match(struct bt_mesh_net_rx *rx,
- struct os_mbuf *pdu)
-{
- u64_t hash = msg_hash(rx, pdu);
- u16_t i;
+ uint16_t i;
for (i = 0; i < ARRAY_SIZE(msg_cache); i++) {
- if (msg_cache[i] == hash) {
+ if (msg_cache[i].src == SRC(pdu->om_data) &&
+ msg_cache[i].seq == (SEQ(pdu->om_data) & BIT_MASK(17))) {
return true;
}
}
- /* Add to the cache */
- rx->msg_cache_idx = msg_cache_next++;
- msg_cache[rx->msg_cache_idx] = hash;
- msg_cache_next %= ARRAY_SIZE(msg_cache);
-
return false;
}
-struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx)
+static void msg_cache_add(struct bt_mesh_net_rx *rx)
{
- int i;
-
- if (net_idx == BT_MESH_KEY_ANY) {
- return &bt_mesh.sub[0];
- }
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == net_idx) {
- return &bt_mesh.sub[i];
- }
- }
-
- return NULL;
+ /* Add to the cache */
+ rx->msg_cache_idx = msg_cache_next++;
+ msg_cache[rx->msg_cache_idx].src = rx->ctx.addr;
+ msg_cache[rx->msg_cache_idx].seq = rx->seq;
+ msg_cache_next %= ARRAY_SIZE(msg_cache);
}
-int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
- const u8_t key[16])
+int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
+ uint32_t iv_index)
{
- u8_t p[] = { 0 };
- u8_t nid;
int err;
- err = bt_mesh_k2(key, p, sizeof(p), &nid, keys->enc, keys->privacy);
- if (err) {
- BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
- return err;
- }
-
- memcpy(keys->net, key, 16);
-
- keys->nid = nid;
-
- BT_DBG("NID 0x%02x EncKey %s", keys->nid, bt_hex(keys->enc, 16));
- BT_DBG("PrivacyKey %s", bt_hex(keys->privacy, 16));
-
- err = bt_mesh_k3(key, keys->net_id);
- if (err) {
- BT_ERR("Unable to generate Net ID");
- return err;
- }
-
- BT_DBG("NetID %s", bt_hex(keys->net_id, 8));
-
-#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
- err = bt_mesh_identity_key(key, keys->identity);
- if (err) {
- BT_ERR("Unable to generate IdentityKey");
- return err;
- }
-
- BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16));
-#endif /* GATT_PROXY */
-
- err = bt_mesh_beacon_key(key, keys->beacon);
- if (err) {
- BT_ERR("Unable to generate beacon key");
- return err;
- }
-
- BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16));
-
- return 0;
-}
-
-int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16])
-{
- u16_t lpn_addr, frnd_addr;
- int err;
- u8_t p[9];
-
-#if (MYNEWT_VAL(BLE_MESH_LOW_POWER))
- if (cred->addr == bt_mesh.lpn.frnd) {
- lpn_addr = bt_mesh_primary_addr();
- frnd_addr = cred->addr;
- } else {
- lpn_addr = cred->addr;
- frnd_addr = bt_mesh_primary_addr();
- }
-#else
- lpn_addr = cred->addr;
- frnd_addr = bt_mesh_primary_addr();
-#endif
-
- BT_DBG("LPNAddress 0x%04x FriendAddress 0x%04x", lpn_addr, frnd_addr);
- BT_DBG("LPNCounter 0x%04x FriendCounter 0x%04x", cred->lpn_counter,
- cred->frnd_counter);
-
- p[0] = 0x01;
- sys_put_be16(lpn_addr, p + 1);
- sys_put_be16(frnd_addr, p + 3);
- sys_put_be16(cred->lpn_counter, p + 5);
- sys_put_be16(cred->frnd_counter, p + 7);
-
- err = bt_mesh_k2(net_key, p, sizeof(p), &cred->cred[idx].nid,
- cred->cred[idx].enc, cred->cred[idx].privacy);
- if (err) {
- BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
- return err;
- }
-
- BT_DBG("Friend NID 0x%02x EncKey %s", cred->cred[idx].nid,
- bt_hex(cred->cred[idx].enc, 16));
- BT_DBG("Friend PrivacyKey %s", bt_hex(cred->cred[idx].privacy, 16));
-
- return 0;
-}
-
-void friend_cred_refresh(u16_t net_idx)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr != BT_MESH_ADDR_UNASSIGNED &&
- cred->net_idx == net_idx) {
- memcpy(&cred->cred[0], &cred->cred[1],
- sizeof(cred->cred[0]));
- }
- }
-}
-
-int friend_cred_update(struct bt_mesh_subnet *sub)
-{
- int err, i;
-
- BT_DBG("net_idx 0x%04x", sub->net_idx);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr == BT_MESH_ADDR_UNASSIGNED ||
- cred->net_idx != sub->net_idx) {
- continue;
- }
-
- err = friend_cred_set(cred, 1, sub->keys[1].net);
- if (err) {
- return err;
- }
- }
-
- return 0;
-}
-
-struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
- u16_t lpn_counter, u16_t frnd_counter)
-{
- struct friend_cred *cred;
- int i, err;
-
- BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
-
- for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) ||
- (friend_cred[i].addr == addr &&
- friend_cred[i].net_idx == sub->net_idx)) {
- cred = &friend_cred[i];
- break;
- }
- }
-
- if (!cred) {
- BT_WARN("No free friend credential slots");
- return NULL;
- }
-
- cred->net_idx = sub->net_idx;
- cred->addr = addr;
- cred->lpn_counter = lpn_counter;
- cred->frnd_counter = frnd_counter;
-
- err = friend_cred_set(cred, 0, sub->keys[0].net);
- if (err) {
- friend_cred_clear(cred);
- return NULL;
- }
-
- if (sub->kr_flag) {
- err = friend_cred_set(cred, 1, sub->keys[1].net);
- if (err) {
- friend_cred_clear(cred);
- return NULL;
- }
- }
-
- return cred;
-}
-
-void friend_cred_clear(struct friend_cred *cred)
-{
- cred->net_idx = BT_MESH_KEY_UNUSED;
- cred->addr = BT_MESH_ADDR_UNASSIGNED;
- cred->lpn_counter = 0;
- cred->frnd_counter = 0;
- memset(cred->cred, 0, sizeof(cred->cred));
-}
-
-int friend_cred_del(u16_t net_idx, u16_t addr)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->addr == addr && cred->net_idx == net_idx) {
- friend_cred_clear(cred);
- return 0;
- }
- }
-
- return -ENOENT;
-}
-
-int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
- const u8_t **enc, const u8_t **priv)
-{
- int i;
-
- BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->net_idx != sub->net_idx) {
- continue;
- }
-
- if (addr != BT_MESH_ADDR_UNASSIGNED && cred->addr != addr) {
- continue;
- }
-
- if (nid) {
- *nid = cred->cred[sub->kr_flag].nid;
- }
-
- if (enc) {
- *enc = cred->cred[sub->kr_flag].enc;
- }
-
- if (priv) {
- *priv = cred->cred[sub->kr_flag].privacy;
- }
-
- return 0;
- }
-
- return -ENOENT;
-}
-
-u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
-{
- u8_t flags = 0x00;
-
- if (sub && sub->kr_flag) {
- flags |= BT_MESH_NET_FLAG_KR;
- }
-
- if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
- flags |= BT_MESH_NET_FLAG_IVU;
- }
-
- return flags;
-}
-
-int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub)
-{
- u8_t flags = bt_mesh_net_flags(sub);
- struct bt_mesh_subnet_keys *keys;
-
- if (sub->kr_flag) {
- BT_DBG("NetIndex %u Using new key", sub->net_idx);
- keys = &sub->keys[1];
- } else {
- BT_DBG("NetIndex %u Using current key", sub->net_idx);
- keys = &sub->keys[0];
- }
-
- BT_DBG("flags 0x%02x, IVI 0x%08x", flags, (unsigned) bt_mesh.iv_index);
-
- return bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id,
- bt_mesh.iv_index, sub->auth);
-}
-
-int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
- u32_t iv_index)
-{
- struct bt_mesh_subnet *sub;
- int err;
-
- BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags,
- (unsigned) iv_index);
+ BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags, iv_index);
BT_DBG("NetKey %s", bt_hex(key, 16));
+ if (BT_MESH_KEY_REFRESH(flags)) {
+ err = bt_mesh_subnet_set(idx, BT_MESH_KR_PHASE_2, NULL, key);
+ } else {
+ err = bt_mesh_subnet_set(idx, BT_MESH_KR_NORMAL, key, NULL);
+ }
+
+ if (err) {
+ BT_ERR("Failed creating subnet");
+ return err;
+ }
+
(void)memset(msg_cache, 0, sizeof(msg_cache));
msg_cache_next = 0U;
- sub = &bt_mesh.sub[0];
-
- sub->kr_flag = BT_MESH_KEY_REFRESH(flags);
- if (sub->kr_flag) {
- err = bt_mesh_net_keys_create(&sub->keys[1], key);
- if (err) {
- return -EIO;
- }
-
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- } else {
- err = bt_mesh_net_keys_create(&sub->keys[0], key);
- if (err) {
- return -EIO;
- }
- }
-
- sub->net_idx = idx;
-
- if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
bt_mesh.iv_index = iv_index;
atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS,
BT_MESH_IV_UPDATE(flags));
@@ -479,96 +155,16 @@ int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
*/
bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS;
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
+ 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);
+ }
return 0;
}
-void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub)
-{
- int i;
-
- BT_DBG("idx 0x%04x", sub->net_idx);
-
- memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0]));
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != sub->net_idx || !key->updated) {
- continue;
- }
-
- memcpy(&key->keys[0], &key->keys[1], sizeof(key->keys[0]));
- key->updated = false;
- }
-}
-
-bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key)
-{
- if (new_kr != sub->kr_flag && sub->kr_phase == BT_MESH_KR_NORMAL) {
- BT_WARN("KR change in normal operation. Are we blacklisted?");
- return false;
- }
-
- sub->kr_flag = new_kr;
-
- if (sub->kr_flag) {
- if (sub->kr_phase == BT_MESH_KR_PHASE_1) {
- BT_DBG("Phase 1 -> Phase 2");
- sub->kr_phase = BT_MESH_KR_PHASE_2;
- return true;
- }
- } else {
- switch (sub->kr_phase) {
- case BT_MESH_KR_PHASE_1:
- if (!new_key) {
- /* Ignore */
- break;
- }
- /* Upon receiving a Secure Network beacon with the KR flag set
- * to 0 using the new NetKey in Phase 1, the node shall
- * immediately transition to Phase 3, which effectively skips
- * Phase 2.
- *
- */
- /* falls through */
- case BT_MESH_KR_PHASE_2:
- BT_DBG("KR Phase 0x%02x -> Normal", sub->kr_phase);
- bt_mesh_net_revoke_keys(sub);
- if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) ||
- (MYNEWT_VAL(BLE_MESH_FRIEND))) {
- friend_cred_refresh(sub->net_idx);
- }
- sub->kr_phase = BT_MESH_KR_NORMAL;
- return true;
- }
- }
-
- return false;
-}
-
-void bt_mesh_rpl_reset(void)
-{
- int i;
-
- /* Discard "old old" IV Index entries from RPL and flag
- * any other ones (which are valid) as old.
- */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
- if (rpl->src) {
- if (rpl->old_iv) {
- memset(rpl, 0, sizeof(*rpl));
- } else {
- rpl->old_iv = true;
- }
- }
- }
-}
-
#if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST)
void bt_mesh_iv_update_test(bool enable)
{
@@ -590,29 +186,12 @@ bool bt_mesh_iv_update(void)
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
}
- bt_mesh_net_sec_update(NULL);
-
return atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
}
#endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */
-/* Used for sending immediate beacons to Friend queues and GATT clients */
-void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub)
+bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update)
{
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_sec_update(sub ? sub->net_idx : BT_MESH_KEY_ANY);
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
- bt_mesh_proxy_beacon_send(sub);
- }
-}
-
-bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update)
-{
- int i;
-
if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
/* We're currently in IV Update mode */
@@ -646,7 +225,7 @@ bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update)
if (iv_index > bt_mesh.iv_index + 1) {
BT_WARN("Performing IV Index Recovery");
- memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
+ bt_mesh_rpl_clear();
bt_mesh.iv_index = iv_index;
bt_mesh.seq = 0;
goto do_update;
@@ -696,10 +275,20 @@ do_update:
k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT);
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_net_beacon_update(&bt_mesh.sub[i]);
- }
+ /* Notify other modules */
+ if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
+ bt_mesh_friend_sec_update(BT_MESH_KEY_ANY);
+ }
+
+ 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);
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
@@ -709,9 +298,9 @@ do_update:
return true;
}
-u32_t bt_mesh_next_seq(void)
+uint32_t bt_mesh_next_seq(void)
{
- u32_t seq = bt_mesh.seq++;
+ uint32_t seq = bt_mesh.seq++;
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_mesh_store_seq();
@@ -722,89 +311,63 @@ u32_t bt_mesh_next_seq(void)
bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY)) {
bt_mesh_beacon_ivu_initiator(true);
bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true);
- bt_mesh_net_sec_update(NULL);
}
return seq;
}
-int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
- bool new_key, const struct bt_mesh_send_cb *cb,
- void *cb_data)
-{
- const u8_t *enc, *priv;
- u32_t seq;
- u16_t dst;
- int err;
-
- BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key,
- buf->om_len);
-
- enc = sub->keys[new_key].enc;
- priv = sub->keys[new_key].privacy;
-
- err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
- if (err) {
- BT_ERR("deobfuscate failed (err %d)", err);
- return err;
- }
-
- err = bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
- if (err) {
- BT_ERR("decrypt failed (err %d)", err);
- return err;
- }
-
- seq = bt_mesh_next_seq();
- buf->om_data[2] = seq >> 16;
- buf->om_data[3] = seq >> 8;
- buf->om_data[4] = seq;
-
- /* Get destination, in case it's a proxy client */
- dst = DST(buf->om_data);
-
- err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, false);
- if (err) {
- BT_ERR("encrypt failed (err %d)", err);
- return err;
- }
-
- err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
- if (err) {
- BT_ERR("obfuscate failed (err %d)", err);
- return err;
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- bt_mesh_proxy_relay(buf, dst)) {
- send_cb_finalize(cb, cb_data);
- } else {
- bt_mesh_adv_send(buf, cb, cb_data);
- }
-
- return 0;
-}
-
static void bt_mesh_net_local(struct ble_npl_event *work)
{
struct os_mbuf *buf;
while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
- BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
- bt_mesh_net_recv(buf, 0, BT_MESH_NET_IF_LOCAL);
+ struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf);
+ struct bt_mesh_net_rx rx = {
+ .ctx = {
+ .net_idx = sub->net_idx,
+ /* Initialize AppIdx to a sane value */
+ .app_idx = BT_MESH_KEY_UNUSED,
+ .recv_ttl = TTL(buf->om_data),
+ /* TTL=1 only goes to local IF */
+ .send_ttl = 1U,
+ .addr = SRC(buf->om_data),
+ .recv_dst = DST(buf->om_data),
+ .recv_rssi = 0,
+ },
+ .net_if = BT_MESH_NET_IF_LOCAL,
+ .sub = sub,
+ .old_iv = (IVI(buf->om_data) != (bt_mesh.iv_index & 0x01)),
+ .ctl = CTL(buf->om_data),
+ .seq = SEQ(buf->om_data),
+ .new_key = SUBNET_KEY_TX_IDX(sub),
+ .local_match = 1U,
+ .friend_match = 0U,
+ };
+
+ BT_DBG("src: 0x%04x dst: 0x%04x seq 0x%06x sub %p", rx.ctx.addr,
+ rx.ctx.addr, rx.seq, sub);
+
+ (void) bt_mesh_trans_recv(buf, &rx);
net_buf_unref(buf);
}
}
-int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
- bool proxy)
+static const struct bt_mesh_net_cred *net_tx_cred_get(struct bt_mesh_net_tx *tx)
+{
+#if defined(BLE_MESH_LOW_POWER)
+ if (tx->friend_cred && bt_mesh_lpn_established()) {
+ return &bt_mesh.lpn.cred[SUBNET_KEY_TX_IDX(tx->sub)];
+ }
+#endif
+
+ tx->friend_cred = 0U;
+ return &tx->sub->keys[SUBNET_KEY_TX_IDX(tx->sub)].msg;
+}
+
+static int net_header_encode(struct bt_mesh_net_tx *tx, uint8_t nid,
+ struct os_mbuf *buf)
{
const bool ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED);
- u32_t seq_val;
- u8_t nid;
- const u8_t *enc, *priv;
- u8_t *seq;
- int err;
if (ctl && net_buf_simple_tailroom(buf) < 8) {
BT_ERR("Insufficient MIC space for CTL PDU");
@@ -820,11 +383,7 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
net_buf_simple_push_be16(buf, tx->ctx->addr);
net_buf_simple_push_be16(buf, tx->src);
- seq = net_buf_simple_push(buf, 3);
- seq_val = bt_mesh_next_seq();
- seq[0] = seq_val >> 16;
- seq[1] = seq_val >> 8;
- seq[2] = seq_val;
+ net_buf_simple_push_be24(buf, bt_mesh_next_seq());
if (ctl) {
net_buf_simple_push_u8(buf, tx->ctx->send_ttl | 0x80);
@@ -832,37 +391,68 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
net_buf_simple_push_u8(buf, tx->ctx->send_ttl);
}
- if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && tx->friend_cred) {
- if (friend_cred_get(tx->sub, BT_MESH_ADDR_UNASSIGNED,
- &nid, &enc, &priv)) {
- BT_WARN("Falling back to master credentials");
-
- tx->friend_cred = 0;
-
- nid = tx->sub->keys[tx->sub->kr_flag].nid;
- enc = tx->sub->keys[tx->sub->kr_flag].enc;
- priv = tx->sub->keys[tx->sub->kr_flag].privacy;
- }
- } else {
- tx->friend_cred = 0;
- nid = tx->sub->keys[tx->sub->kr_flag].nid;
- enc = tx->sub->keys[tx->sub->kr_flag].enc;
- priv = tx->sub->keys[tx->sub->kr_flag].privacy;
- }
-
net_buf_simple_push_u8(buf, (nid | (BT_MESH_NET_IVI_TX & 1) << 7));
- err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, proxy);
+ return 0;
+}
+
+static int net_encrypt(struct os_mbuf *buf,
+ const struct bt_mesh_net_cred *cred, uint32_t iv_index,
+ bool proxy)
+{
+ int err;
+
+ err = bt_mesh_net_encrypt(cred->enc, buf, iv_index, proxy);
if (err) {
return err;
}
- return bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv);
+ return bt_mesh_net_obfuscate(buf->om_data, iv_index, cred->privacy);
+}
+
+int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
+ bool proxy)
+{
+ const struct bt_mesh_net_cred *cred;
+ int err;
+
+ cred = net_tx_cred_get(tx);
+ err = net_header_encode(tx, cred->nid, buf);
+ if (err) {
+ return err;
+ }
+
+ return net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, proxy);
+}
+
+static int loopback(const struct bt_mesh_net_tx *tx, const uint8_t *data,
+ size_t len)
+{
+ struct os_mbuf *buf;
+
+ buf = os_mbuf_get_pkthdr(&loopback_os_mbuf_pool, 0);
+ if (!buf) {
+ BT_WARN("Unable to allocate loopback");
+ return -ENOMEM;
+ }
+
+ BT_DBG("");
+
+ LOOPBACK_BUF_SUB(buf) = tx->sub;
+
+ net_buf_add_mem(buf, data, len);
+
+ net_buf_slist_put(&bt_mesh.local_queue, buf);
+
+ k_work_submit(&bt_mesh.local_work);
+
+ return 0;
}
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
+ const struct bt_mesh_net_cred *cred;
int err;
BT_DBG("src 0x%04x dst 0x%04x len %u headroom %zu tailroom %zu",
@@ -871,11 +461,8 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
BT_DBG("Payload len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
BT_DBG("Seq 0x%06x", bt_mesh.seq);
- if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
- tx->ctx->send_ttl = bt_mesh_default_ttl_get();
- }
-
- err = bt_mesh_net_encode(tx, buf, false);
+ cred = net_tx_cred_get(tx);
+ err = net_header_encode(tx, cred->nid, buf);
if (err) {
goto done;
}
@@ -883,225 +470,118 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
BT_DBG("encoded %u bytes: %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- /* Deliver to GATT Proxy Clients if necessary. Mesh spec 3.4.5.2:
- * "The output filter of the interface connected to advertising or
- * GATT bearers shall drop all messages with TTL value set to 1."
- */
- if (MYNEWT_VAL(BLE_MESH_GATT_PROXY) &&
- tx->ctx->send_ttl != 1) {
- if (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;
- }
- }
-
/* Deliver to local network interface if necessary */
if (bt_mesh_fixed_group_match(tx->ctx->addr) ||
bt_mesh_elem_find(tx->ctx->addr)) {
- if (cb && cb->start) {
- cb->start(0, 0, cb_data);
+ err = loopback(tx, buf->om_data, buf->om_len);
+
+ /* Local unicast messages should not go out to network */
+ if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) ||
+ tx->ctx->send_ttl == 1U) {
+ if (!err) {
+ send_cb_finalize(cb, cb_data);
+ }
+
+ goto done;
}
- net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf));
- if (cb && cb->end) {
- cb->end(0, cb_data);
- }
- k_work_submit(&bt_mesh.local_work);
- } else if (tx->ctx->send_ttl != 1) {
- /* Deliver to to the advertising network interface. Mesh spec
- * 3.4.5.2: "The output filter of the interface connected to
- * advertising or GATT bearers shall drop all messages with
- * TTL value set to 1."
- */
- bt_mesh_adv_send(buf, cb, cb_data);
}
+ /* Mesh spec 3.4.5.2: "The output filter of the interface connected to
+ * advertising or GATT bearers shall drop all messages with TTL value
+ * set to 1." If a TTL=1 packet wasn't for a local interface, it is
+ * invalid.
+ */
+ if (tx->ctx->send_ttl == 1U) {
+ err = -EINVAL;
+ goto done;
+ }
+
+ err = net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, false);
+ if (err) {
+ goto done;
+ }
+
+ /* 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;
+ }
+
+ bt_mesh_adv_send(buf, cb, cb_data);
done:
net_buf_unref(buf);
return err;
}
-static bool auth_match(struct bt_mesh_subnet_keys *keys,
- const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8])
+void bt_mesh_net_loopback_clear(uint16_t net_idx)
{
- u8_t net_auth[8];
+ struct net_buf_slist_t new_list;
+ struct os_mbuf *buf;
- if (memcmp(net_id, keys->net_id, 8)) {
+ BT_DBG("0x%04x", net_idx);
+
+ net_buf_slist_init(&new_list);
+
+ while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) {
+ struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf);
+
+ if (net_idx == BT_MESH_KEY_ANY || net_idx == sub->net_idx) {
+ BT_DBG("Dropped 0x%06x", SEQ(buf->om_data));
+ net_buf_unref(buf);
+ } else {
+ net_buf_slist_put(&new_list, buf);
+ }
+ }
+
+ bt_mesh.local_queue = new_list;
+}
+
+static bool net_decrypt(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+ struct os_mbuf *out,
+ const struct bt_mesh_net_cred *cred)
+{
+ bool proxy = (rx->net_if == BT_MESH_NET_IF_PROXY_CFG);
+
+ if (NID(in->om_data) != cred->nid) {
return false;
}
- bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, iv_index,
- net_auth);
+ BT_DBG("NID 0x%02x", NID(in->om_data));
+ BT_DBG("IVI %u net->iv_index 0x%08x", IVI(in->om_data), bt_mesh.iv_index);
- if (memcmp(auth, net_auth, 8)) {
- BT_WARN("Authentication Value %s != %s",
- bt_hex(auth, 8), bt_hex(net_auth, 8));
+ rx->old_iv = (IVI(in->om_data) != (bt_mesh.iv_index & 0x01));
+ net_buf_simple_reset(out);
+ net_buf_simple_add_mem(out, in->om_data, in->om_len);
+
+ if (bt_mesh_net_obfuscate(out->om_data, BT_MESH_NET_IVI_RX(rx),
+ cred->privacy)) {
return false;
}
- return true;
-}
-
-struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8],
- bool *new_key)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (auth_match(&sub->keys[0], net_id, flags, iv_index, auth)) {
- *new_key = false;
- return sub;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
-
- if (auth_match(&sub->keys[1], net_id, flags, iv_index, auth)) {
- *new_key = true;
- return sub;
- }
- }
-
- return NULL;
-}
-
-static int net_decrypt(struct bt_mesh_subnet *sub, const u8_t *enc,
- const u8_t *priv, const u8_t *data,
- size_t data_len, struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
- BT_DBG("IVI %u net->iv_index 0x%08x", IVI(data),
- (unsigned) bt_mesh.iv_index);
-
- rx->old_iv = (IVI(data) != (bt_mesh.iv_index & 0x01));
-
- net_buf_simple_init(buf, 0);
- memcpy(net_buf_simple_add(buf, data_len), data, data_len);
-
- if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) {
- return -ENOENT;
- }
-
- if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(rx, buf)) {
- BT_WARN("Duplicate found in Network Message Cache");
- return -EALREADY;
- }
-
- rx->ctx.addr = SRC(buf->om_data);
+ rx->ctx.addr = SRC(out->om_data);
if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr)) {
- BT_WARN("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr);
- return -EINVAL;
+ BT_DBG("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr);
+ return false;
+ }
+
+ if (bt_mesh_elem_find(rx->ctx.addr)) {
+ BT_DBG("Dropping locally originated packet");
+ return false;
+ }
+
+ if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(out)) {
+ BT_DBG("Duplicate found in Network Message Cache");
+ return false;
}
BT_DBG("src 0x%04x", rx->ctx.addr);
-
- if ((MYNEWT_VAL(BLE_MESH_PROXY)) &&
- rx->net_if == BT_MESH_NET_IF_PROXY_CFG) {
- return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx),
- true);
- }
-
- return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false);
-}
-
-static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data,
- size_t data_len, struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- int i;
-
- BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx);
-
- for (i = 0; i < ARRAY_SIZE(friend_cred); i++) {
- struct friend_cred *cred = &friend_cred[i];
-
- if (cred->net_idx != sub->net_idx) {
- continue;
- }
-
- if (NID(data) == cred->cred[0].nid &&
- !net_decrypt(sub, cred->cred[0].enc, cred->cred[0].privacy,
- data, data_len, rx, buf)) {
- return 0;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
-
- if (NID(data) == cred->cred[1].nid &&
- !net_decrypt(sub, cred->cred[1].enc, cred->cred[1].privacy,
- data, data_len, rx, buf)) {
- rx->new_key = 1;
- return 0;
- }
- }
-
- return -ENOENT;
-}
-
-static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
- struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
-{
- struct bt_mesh_subnet *sub;
- unsigned int i;
-
- BT_DBG("");
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- sub = &bt_mesh.sub[i];
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if ((IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) ||
- IS_ENABLED(CONFIG_BT_MESH_FRIEND)) &&
- !friend_decrypt(sub, data, data_len, rx, buf)) {
- rx->friend_cred = 1U;
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
-
- if (NID(data) == sub->keys[0].nid &&
- !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy,
- data, data_len, rx, buf)) {
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
-
- if (sub->kr_phase == BT_MESH_KR_NORMAL) {
- continue;
- }
-
- if (NID(data) == sub->keys[1].nid &&
- !net_decrypt(sub, sub->keys[1].enc, sub->keys[1].privacy,
- data, data_len, rx, buf)) {
- rx->new_key = 1;
- rx->ctx.net_idx = sub->net_idx;
- rx->sub = sub;
- return true;
- }
- }
-
- return false;
+ return bt_mesh_net_decrypt(cred->enc, out, BT_MESH_NET_IVI_RX(rx),
+ proxy) == 0;
}
/* Relaying from advertising to the advertising bearer should only happen
@@ -1112,8 +592,6 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len,
static bool relay_to_adv(enum bt_mesh_net_if net_if)
{
switch (net_if) {
- case BT_MESH_NET_IF_LOCAL:
- return true;
case BT_MESH_NET_IF_ADV:
return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED);
case BT_MESH_NET_IF_PROXY:
@@ -1126,27 +604,16 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if)
static void bt_mesh_net_relay(struct os_mbuf *sbuf,
struct bt_mesh_net_rx *rx)
{
- const u8_t *enc, *priv;
+ const struct bt_mesh_net_cred *cred;
struct os_mbuf *buf;
- u8_t nid, transmit;
+ uint8_t transmit;
- if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
- /* Locally originated PDUs with TTL=1 will only be delivered
- * to local elements as per Mesh Profile 1.0 section 3.4.5.2:
- * "The output filter of the interface connected to
- * advertising or GATT bearers shall drop all messages with
- * TTL value set to 1."
- */
- if (rx->ctx.recv_ttl == 1) {
- return;
- }
- } else {
- if (rx->ctx.recv_ttl <= 1) {
- return;
- }
+ if (rx->ctx.recv_ttl <= 1U) {
+ return;
}
if (rx->net_if == BT_MESH_NET_IF_ADV &&
+ !rx->friend_cred &&
bt_mesh_relay_get() != BT_MESH_RELAY_ENABLED &&
bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_ENABLED) {
return;
@@ -1159,7 +626,7 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf,
* Anything else (like GATT to adv, or locally originated packets)
* use the Network Transmit state.
*/
- if (rx->net_if == BT_MESH_NET_IF_ADV) {
+ if (rx->net_if == BT_MESH_NET_IF_ADV && !rx->friend_cred) {
transmit = bt_mesh_relay_retransmit_get();
} else {
transmit = bt_mesh_net_transmit_get();
@@ -1171,57 +638,45 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf,
return;
}
- /* Only decrement TTL for non-locally originated packets */
- if (rx->net_if != BT_MESH_NET_IF_LOCAL) {
- /* Leave CTL bit intact */
- sbuf->om_data[1] &= 0x80;
- sbuf->om_data[1] |= rx->ctx.recv_ttl - 1;
- }
+ /* Leave CTL bit intact */
+ sbuf->om_data[1] &= 0x80;
+ sbuf->om_data[1] |= rx->ctx.recv_ttl - 1U;
net_buf_add_mem(buf, sbuf->om_data, sbuf->om_len);
- enc = rx->sub->keys[rx->sub->kr_flag].enc;
- priv = rx->sub->keys[rx->sub->kr_flag].privacy;
- nid = rx->sub->keys[rx->sub->kr_flag].nid;
+ cred = &rx->sub->keys[SUBNET_KEY_TX_IDX(rx->sub)].msg;
BT_DBG("Relaying packet. TTL is now %u", TTL(buf->om_data));
/* Update NID if RX or RX was with friend credentials */
if (rx->friend_cred) {
buf->om_data[0] &= 0x80; /* Clear everything except IVI */
- buf->om_data[0] |= nid;
+ buf->om_data[0] |= cred->nid;
}
/* We re-encrypt and obfuscate using the received IVI rather than
* the normal TX IVI (which may be different) since the transport
* layer nonce includes the IVI.
*/
- if (bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false)) {
+ if (net_encrypt(buf, cred, BT_MESH_NET_IVI_RX(rx), false)) {
BT_ERR("Re-encrypting failed");
goto done;
}
- if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) {
- BT_ERR("Re-obfuscating failed");
- goto done;
- }
-
BT_DBG("encoded %u bytes: %s", buf->om_len,
bt_hex(buf->om_data, buf->om_len));
- /* Sending to the GATT bearer should only happen if GATT Proxy
- * is enabled or the message originates from the local node.
+ /* When the Friend node relays message for lpn, the message will be
+ * retransmitted using the managed master security credentials and
+ * the Network PDU shall be retransmitted to all network interfaces.
*/
if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) &&
- (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED ||
- rx->net_if == BT_MESH_NET_IF_LOCAL)) {
- if (bt_mesh_proxy_relay(buf, rx->ctx.recv_dst) &&
- BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) {
- goto done;
- }
+ (rx->friend_cred ||
+ bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED)) {
+ bt_mesh_proxy_relay(buf, rx->ctx.recv_dst);
}
- if (relay_to_adv(rx->net_if)) {
+ if (relay_to_adv(rx->net_if) || rx->friend_cred) {
bt_mesh_adv_send(buf, NULL, NULL);
}
@@ -1240,26 +695,26 @@ void bt_mesh_net_header_parse(struct os_mbuf *buf,
rx->ctx.recv_dst = DST(buf->om_data);
}
-int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
- struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
+int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if,
+ struct bt_mesh_net_rx *rx, struct os_mbuf *out)
{
- if (data->om_len < BT_MESH_NET_MIN_PDU_LEN) {
- BT_WARN("Dropping too short mesh packet (len %u)", data->om_len);
- BT_WARN("%s", bt_hex(data->om_data, data->om_len));
+ if (in->om_len < BT_MESH_NET_MIN_PDU_LEN) {
+ BT_WARN("Dropping too short mesh packet (len %u)", in->om_len);
+ BT_WARN("%s", bt_hex(in->om_data, in->om_len));
return -EINVAL;
}
- if (net_if == BT_MESH_NET_IF_ADV && check_dup(data)) {
- BT_DBG("duplicate packet; dropping %u bytes: %s", data->om_len,
- bt_hex(data->om_data, data->om_len));
+ 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));
return -EINVAL;
}
- BT_DBG("%u bytes: %s", data->om_len, bt_hex(data->om_data, data->om_len));
+ BT_DBG("%u bytes: %s", in->om_len, bt_hex(in->om_data, in->om_len));
rx->net_if = net_if;
- if (!net_find_and_decrypt(data->om_data, data->om_len, rx, buf)) {
+ if (!bt_mesh_net_cred_find(rx, in, out, net_decrypt)) {
BT_DBG("Unable to find matching net for packet");
return -ENOENT;
}
@@ -1267,7 +722,7 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
/* Initialize AppIdx to a sane value */
rx->ctx.app_idx = BT_MESH_KEY_UNUSED;
- rx->ctx.recv_ttl = TTL(buf->om_data);
+ rx->ctx.recv_ttl = TTL(out->om_data);
/* Default to responding with TTL 0 for non-routed messages */
if (rx->ctx.recv_ttl == 0) {
@@ -1276,12 +731,12 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
rx->ctx.send_ttl = BT_MESH_TTL_DEFAULT;
}
- rx->ctl = CTL(buf->om_data);
- rx->seq = SEQ(buf->om_data);
- rx->ctx.recv_dst = DST(buf->om_data);
+ rx->ctl = CTL(out->om_data);
+ rx->seq = SEQ(out->om_data);
+ rx->ctx.recv_dst = DST(out->om_data);
- BT_DBG("Decryption successful. Payload len %u: %s", buf->om_len,
- bt_hex(buf->om_data, buf->om_len));
+ BT_DBG("Decryption successful. Payload len %u: %s", out->om_len,
+ bt_hex(out->om_data, out->om_len));
if (net_if != BT_MESH_NET_IF_PROXY_CFG &&
rx->ctx.recv_dst == BT_MESH_ADDR_UNASSIGNED) {
@@ -1289,24 +744,16 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
return -EBADMSG;
}
- if (BT_MESH_ADDR_IS_RFU(rx->ctx.recv_dst)) {
- BT_ERR("Destination address is RFU; dropping packet");
- return -EBADMSG;
- }
-
- if (net_if != BT_MESH_NET_IF_LOCAL && bt_mesh_elem_find(rx->ctx.addr)) {
- BT_DBG("Dropping locally originated packet");
- return -EBADMSG;
- }
-
BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->ctx.recv_dst,
rx->ctx.recv_ttl);
- BT_DBG("PDU: %s", bt_hex(buf->om_data, buf->om_len));
+ BT_DBG("PDU: %s", bt_hex(out->om_data, out->om_len));
+
+ msg_cache_add(rx);
return 0;
}
-void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
+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);
@@ -1350,7 +797,7 @@ void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
*/
if (bt_mesh_trans_recv(buf, &rx) == -EAGAIN) {
BT_WARN("Removing rejected message from Network Message Cache");
- msg_cache[rx.msg_cache_idx] = 0ULL;
+ msg_cache[rx.msg_cache_idx].src = BT_MESH_ADDR_UNASSIGNED;
/* Rewind the next index now that we're not using this entry */
msg_cache_next = rx.msg_cache_idx;
}
@@ -1370,7 +817,8 @@ done:
static void ivu_refresh(struct ble_npl_event *work)
{
- bt_mesh.ivu_duration += BT_MESH_IVU_HOURS;
+ bt_mesh.ivu_duration = MIN(UINT8_MAX,
+ bt_mesh.ivu_duration + BT_MESH_IVU_HOURS);
BT_DBG("%s for %u hour%s",
atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ?
@@ -1394,43 +842,23 @@ static void ivu_refresh(struct ble_npl_event *work)
}
}
-void bt_mesh_net_start(void)
-{
- if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) {
- bt_mesh_beacon_enable();
- } else {
- 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();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
- bt_mesh_lpn_init();
- } else {
- bt_mesh_scan_enable();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- bt_mesh_friend_init();
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROV)) {
- u16_t net_idx = bt_mesh.sub[0].net_idx;
- u16_t addr = bt_mesh_primary_addr();
-
- bt_mesh_prov_complete(net_idx, addr);
- }
-}
-
void bt_mesh_net_init(void)
{
+ int rc;
+
k_delayed_work_init(&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);
+
+ rc = os_mempool_init(&loopback_buf_mempool, MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS),
+ LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE,
+ &loopback_mbuf_membuf[0], "loopback_buf_pool");
+ 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));
+ assert(rc == 0);
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h
index 1a7e3aa7d..91656f645 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/net.h
@@ -9,13 +9,7 @@
#ifndef __NET_H__
#define __NET_H__
-#define BT_MESH_NET_FLAG_KR BIT(0)
-#define BT_MESH_NET_FLAG_IVU BIT(1)
-
-#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
+#include "subnet.h"
#define BT_MESH_IV_UPDATE(flags) ((flags >> 1) & 0x01)
#define BT_MESH_KEY_REFRESH(flags) (flags & 0x01)
@@ -31,64 +25,13 @@
CONFIG_BT_MESH_IVU_DIVIDER)
#define BT_MESH_IVU_TIMEOUT K_HOURS(BT_MESH_IVU_HOURS)
-struct bt_mesh_app_key {
- u16_t net_idx;
- u16_t app_idx;
- bool updated;
- struct bt_mesh_app_keys {
- u8_t id;
- u8_t val[16];
- } keys[2];
-};
+struct bt_mesh_net_cred;
struct bt_mesh_node {
- u16_t addr;
- u16_t net_idx;
- u8_t dev_key[16];
- u8_t num_elem;
-};
-
-struct bt_mesh_subnet {
- u32_t beacon_sent; /* Timestamp of last sent beacon */
- u8_t beacons_last; /* Number of beacons during last
- * observation window
- */
- u8_t beacons_cur; /* Number of beaconds observed during
- * currently ongoing window.
- */
-
- u8_t beacon_cache[21]; /* Cached last authenticated beacon */
-
- u16_t net_idx; /* NetKeyIndex */
-
- bool kr_flag; /* Key Refresh Flag */
- u8_t kr_phase; /* Key Refresh Phase */
-
- u8_t node_id; /* Node Identity State */
- u32_t node_id_start; /* Node Identity started timestamp */
-
- u8_t auth[8]; /* Beacon Authentication Value */
-
- struct bt_mesh_subnet_keys {
- u8_t net[16]; /* NetKey */
- u8_t nid; /* NID */
- u8_t enc[16]; /* EncKey */
- u8_t net_id[8]; /* Network ID */
-#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
- u8_t identity[16]; /* IdentityKey */
-#endif
- u8_t privacy[16]; /* PrivacyKey */
- u8_t beacon[16]; /* BeaconKey */
- } keys[2];
-};
-
-struct bt_mesh_rpl {
- u16_t src;
- bool old_iv;
-#if (MYNEWT_VAL(BLE_MESH_SETTINGS))
- bool store;
-#endif
- u32_t seq;
+ uint16_t addr;
+ uint16_t net_idx;
+ uint8_t dev_key[16];
+ uint8_t num_elem;
};
#if MYNEWT_VAL(BLE_MESH_FRIEND)
@@ -100,23 +43,23 @@ struct bt_mesh_rpl {
#endif
struct bt_mesh_friend {
- u16_t lpn;
- u8_t recv_delay;
- u8_t fsn:1,
+ uint16_t lpn;
+ uint8_t recv_delay;
+ uint8_t fsn:1,
send_last:1,
pending_req:1,
- sec_update:1,
pending_buf:1,
- valid:1,
established:1;
- s32_t poll_to;
- u8_t num_elem;
- u16_t lpn_counter;
- u16_t counter;
+ int32_t poll_to;
+ uint8_t num_elem;
+ uint16_t lpn_counter;
+ uint16_t counter;
- u16_t net_idx;
+ struct bt_mesh_subnet *subnet;
- u16_t sub_list[FRIEND_SUB_LIST_SIZE];
+ struct bt_mesh_net_cred cred[2];
+
+ uint16_t sub_list[FRIEND_SUB_LIST_SIZE];
struct k_delayed_work timer;
@@ -127,19 +70,19 @@ struct bt_mesh_friend {
* the current number of segments, in the queue. This is
* used for Friend Queue free space calculations.
*/
- u8_t seg_count;
+ uint8_t seg_count;
} seg[FRIEND_SEG_RX];
struct os_mbuf *last;
struct net_buf_slist_t queue;
- u32_t queue_size;
+ uint32_t queue_size;
/* Friend Clear Procedure */
struct {
- u32_t start; /* Clear Procedure start */
- u16_t frnd; /* Previous Friend's address */
- u16_t repeat_sec; /* Repeat timeout in seconds */
+ 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 */
} clear;
};
@@ -165,23 +108,23 @@ struct bt_mesh_lpn {
} state;
/* Transaction Number (used for subscription list) */
- u8_t xact_next;
- u8_t xact_pending;
- u8_t sent_req;
+ uint8_t xact_next;
+ uint8_t xact_pending;
+ uint8_t sent_req;
/* Address of our Friend when we're a LPN. Unassigned if we don't
* have a friend yet.
*/
- u16_t frnd;
+ uint16_t frnd;
/* Value from the friend offer */
- u8_t recv_win;
+ uint8_t recv_win;
- u8_t req_attempts; /* Number of Request attempts */
+ uint8_t req_attempts; /* Number of Request attempts */
- s32_t poll_timeout;
+ int32_t poll_timeout;
- u8_t groups_changed:1, /* Friend Subscription List needs updating */
+ uint8_t groups_changed:1, /* Friend Subscription List needs updating */
pending_poll:1, /* Poll to be sent after subscription */
disable:1, /* Disable LPN after clearing */
fsn:1, /* Friend Sequence Number */
@@ -189,22 +132,29 @@ struct bt_mesh_lpn {
clear_success:1; /* Friend Clear Confirm received */
/* Friend Queue Size */
- u8_t queue_size;
+ uint8_t queue_size;
+
+ /* FriendCounter */
+ uint16_t frnd_counter;
/* LPNCounter */
- u16_t counter;
+ uint16_t lpn_counter;
/* Previous Friend of this LPN */
- u16_t old_friend;
+ uint16_t old_friend;
/* Duration reported for last advertising packet */
- u16_t adv_duration;
+ uint16_t adv_duration;
/* Next LPN related action timer */
struct k_delayed_work timer;
/* Subscribed groups */
- u16_t groups[LPN_GROUPS];
+ uint16_t groups[LPN_GROUPS];
+
+ struct bt_mesh_subnet *sub;
+
+ struct bt_mesh_net_cred cred[2];
/* Bit fields for tracking which groups the Friend knows about */
ATOMIC_DEFINE(added, LPN_GROUPS);
@@ -231,15 +181,20 @@ enum {
BT_MESH_CFG_PENDING,
BT_MESH_MOD_PENDING,
BT_MESH_VA_PENDING,
- BT_MESH_NODES_PENDING,
+
+ /* Feature flags */
+ BT_MESH_RELAY,
+ BT_MESH_BEACON,
+ BT_MESH_GATT_PROXY,
+ BT_MESH_FRIEND,
/* Don't touch - intentionally last */
BT_MESH_FLAG_COUNT,
};
struct bt_mesh_net {
- u32_t iv_index; /* Current IV Index */
- u32_t seq; /* Next outgoing sequence number (24 bits) */
+ uint32_t iv_index; /* Current IV Index */
+ uint32_t seq; /* Next outgoing sequence number (24 bits) */
ATOMIC_DEFINE(flags, BT_MESH_FLAG_COUNT);
@@ -257,22 +212,16 @@ struct bt_mesh_net {
#endif
/* Number of hours in current IV Update state */
- u8_t ivu_duration;
+ uint8_t ivu_duration;
+
+ uint8_t net_xmit;
+ uint8_t relay_xmit;
+ uint8_t default_ttl;
/* Timer to track duration in current IV Update state */
struct k_delayed_work ivu_timer;
- u8_t dev_key[16];
-
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- struct bt_mesh_node nodes[MYNEWT_VAL(BLE_MESH_NODE_COUNT)];
-#endif
-
- struct bt_mesh_app_key app_keys[MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)];
-
- struct bt_mesh_subnet sub[MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)];
-
- struct bt_mesh_rpl rpl[MYNEWT_VAL(BLE_MESH_CRPL)];
+ uint8_t dev_key[16];
};
/* Network interface */
@@ -287,24 +236,24 @@ enum bt_mesh_net_if {
struct bt_mesh_net_rx {
struct bt_mesh_subnet *sub;
struct bt_mesh_msg_ctx ctx;
- u32_t seq; /* Sequence Number */
- u8_t old_iv:1, /* iv_index - 1 was used */
+ uint32_t seq; /* Sequence Number */
+ uint8_t old_iv:1, /* iv_index - 1 was used */
new_key:1, /* Data was encrypted with updated key */
friend_cred:1, /* Data was encrypted with friend cred */
ctl:1, /* Network Control */
net_if:2, /* Network interface */
local_match:1, /* Matched a local element */
friend_match:1; /* Matched an LPN we're friends for */
- u16_t msg_cache_idx; /* Index of entry in message cache */
+ uint16_t msg_cache_idx; /* Index of entry in message cache */
};
/* Encoding context for Network/Transport data */
struct bt_mesh_net_tx {
struct bt_mesh_subnet *sub;
struct bt_mesh_msg_ctx *ctx;
- u16_t src;
- u8_t xmit;
- u8_t friend_cred:1,
+ uint16_t src;
+ uint8_t xmit;
+ uint8_t friend_cred:1,
aszmic:1,
aid:6;
};
@@ -318,80 +267,36 @@ extern struct bt_mesh_net bt_mesh;
#define BT_MESH_NET_HDR_LEN 9
-int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys,
- const u8_t key[16]);
+static inline void *net_buf_user_data(const struct os_mbuf *buf)
+{
+ return (void *)buf->om_data;
+}
-int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16],
- u32_t iv_index);
+int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16],
+ uint32_t iv_index);
-u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
-
-bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key);
-
-void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub);
-
-int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub);
-
-void bt_mesh_rpl_reset(void);
-
-bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update);
-
-void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub);
-
-struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx);
-
-struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags,
- u32_t iv_index, const u8_t auth[8],
- bool *new_key);
+bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update);
int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
bool proxy);
+int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if,
+ struct bt_mesh_net_rx *rx, struct os_mbuf *out);
+
int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf,
const struct bt_mesh_send_cb *cb, void *cb_data);
-int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf,
- bool new_key, const struct bt_mesh_send_cb *cb,
- void *cb_data);
-
-int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if,
- struct bt_mesh_net_rx *rx, struct os_mbuf *buf);
-
-void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi,
+void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi,
enum bt_mesh_net_if net_if);
-u32_t bt_mesh_next_seq(void);
+void bt_mesh_net_loopback_clear(uint16_t net_idx);
-void bt_mesh_net_start(void);
+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);
-/* Friendship Credential Management */
-struct friend_cred {
- u16_t net_idx;
- u16_t addr;
-
- u16_t lpn_counter;
- u16_t frnd_counter;
-
- struct {
- u8_t nid; /* NID */
- u8_t enc[16]; /* EncKey */
- u8_t privacy[16]; /* PrivacyKey */
- } cred[2];
-};
-
-int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid,
- const u8_t **enc, const u8_t **priv);
-int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]);
-void friend_cred_refresh(u16_t net_idx);
-int friend_cred_update(struct bt_mesh_subnet *sub);
-struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr,
- u16_t lpn_counter, u16_t frnd_counter);
-void friend_cred_clear(struct friend_cred *cred);
-int friend_cred_del(u16_t net_idx, u16_t addr);
static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb,
void *cb_data)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c
index de41f40d0..199550d99 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/nodes.c
@@ -161,4 +161,4 @@ void bt_mesh_node_del(struct bt_mesh_node *node, bool store)
}
#endif
-#endif
+#endif /* MYNEWT_VAL(BLE_MESH) */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/pb_adv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/pb_adv.c
new file mode 100644
index 000000000..9b20475a5
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/pb_adv.c
@@ -0,0 +1,891 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#if MYNEWT_VAL(BLE_MESH)
+
+#include
+#include
+#include "../include/mesh/mesh.h"
+#include
+#include "net.h"
+#include "prov.h"
+#include "adv.h"
+#include "crypto.h"
+#include "beacon.h"
+#include "prov.h"
+#include "../include/mesh/glue.h"
+
+#define GPCF(gpc) (gpc & 0x03)
+#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
+#define GPC_ACK 0x01
+#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02)
+#define GPC_CTL(op) (((op) << 2) | 0x03)
+
+#define START_PAYLOAD_MAX 20
+#define CONT_PAYLOAD_MAX 23
+
+#define START_LAST_SEG(gpc) (gpc >> 2)
+#define CONT_SEG_INDEX(gpc) (gpc >> 2)
+
+#define BEARER_CTL(gpc) (gpc >> 2)
+#define LINK_OPEN 0x00
+#define LINK_ACK 0x01
+#define LINK_CLOSE 0x02
+
+#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)])
+#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
+
+#define XACT_ID_MAX 0x7f
+#define XACT_ID_NVAL 0xff
+#define SEG_NVAL 0xff
+
+#define RETRANSMIT_TIMEOUT K_MSEC(MYNEWT_VAL(BLE_MESH_PB_ADV_RETRANS_TIMEOUT))
+#define BUF_TIMEOUT K_MSEC(400)
+#define CLOSING_TIMEOUT K_SECONDS(3)
+#define TRANSACTION_TIMEOUT K_SECONDS(30)
+
+/* 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
+
+enum {
+ ADV_LINK_ACTIVE, /* Link has been opened */
+ ADV_LINK_ACK_RECVD, /* Ack for link has been received */
+ ADV_LINK_CLOSING, /* Link is closing down */
+ ADV_LINK_INVALID, /* Error occurred during provisioning */
+ ADV_ACK_PENDING, /* An acknowledgment is being sent */
+ ADV_PROVISIONER, /* The link was opened as provisioner */
+
+ ADV_NUM_FLAGS,
+};
+
+struct pb_adv {
+ uint32_t id; /* Link ID */
+
+ ATOMIC_DEFINE(flags, ADV_NUM_FLAGS);
+
+ const struct prov_bearer_cb *cb;
+ void *cb_data;
+
+ struct {
+ uint8_t id; /* Most recent transaction ID */
+ 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 {
+ /* Start timestamp of the transaction */
+ int64_t start;
+
+ /* Transaction id */
+ uint8_t id;
+
+ /* Current ack id */
+ uint8_t pending_ack;
+
+ /* Pending outgoing buffer(s) */
+ struct os_mbuf *buf[3];
+
+ prov_bearer_send_complete_t cb;
+
+ void *cb_data;
+
+ /* Retransmit timer */
+ struct k_delayed_work retransmit;
+ } tx;
+
+ /* Protocol timeout */
+ struct k_delayed_work prot_timer;
+};
+
+struct prov_rx {
+ uint32_t link_id;
+ uint8_t xact_id;
+ uint8_t gpc;
+};
+
+static struct os_mbuf *rx_buf;
+static struct pb_adv link;
+
+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 buf_sent(int err, void *user_data)
+{
+ BT_DBG("buf_send");
+
+ if (!link.tx.buf[0]) {
+ return;
+ }
+
+ BT_DBG("submit retransmit");
+ k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
+}
+
+static struct bt_mesh_send_cb buf_sent_cb = {
+ .end = buf_sent,
+};
+
+static uint8_t last_seg(uint8_t len)
+{
+ if (len <= START_PAYLOAD_MAX) {
+ return 0;
+ }
+
+ len -= START_PAYLOAD_MAX;
+
+ return 1 + (len / CONT_PAYLOAD_MAX);
+}
+
+static void free_segments(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
+ struct os_mbuf *buf = link.tx.buf[i];
+
+ if (!buf) {
+ break;
+ }
+
+ link.tx.buf[i] = NULL;
+ /* Mark as canceled */
+ BT_MESH_ADV(buf)->busy = 0U;
+ net_buf_unref(buf);
+ }
+}
+
+static uint8_t next_transaction_id(uint8_t id)
+{
+ return (((id + 1) & XACT_ID_MAX) | (id & (XACT_ID_MAX+1)));
+}
+
+static void prov_clear_tx(void)
+{
+ BT_DBG("");
+
+ k_delayed_work_cancel(&link.tx.retransmit);
+
+ free_segments();
+}
+
+static void reset_adv_link(void)
+{
+ BT_DBG("");
+ prov_clear_tx();
+
+ k_delayed_work_cancel(&link.prot_timer);
+
+ if (atomic_test_bit(link.flags, ADV_PROVISIONER)) {
+ /* Clear everything except the retransmit and protocol timer
+ * delayed work objects.
+ */
+ (void)memset(&link, 0, offsetof(struct pb_adv, tx.retransmit));
+ link.rx.id = XACT_ID_NVAL;
+ } else {
+ /* Accept another provisioning attempt */
+ link.id = 0;
+ atomic_clear(link.flags);
+ link.rx.id = XACT_ID_MAX;
+ link.tx.id = XACT_ID_NVAL;
+ }
+ link.tx.pending_ack = XACT_ID_NVAL;
+ if (!rx_buf) {
+ rx_buf = NET_BUF_SIMPLE(65);
+ }
+ link.rx.buf = rx_buf;
+ net_buf_simple_reset(link.rx.buf);
+}
+
+static void close_link(enum prov_bearer_link_status reason)
+{
+ const struct prov_bearer_cb *cb = link.cb;
+ void *cb_data = link.cb_data;
+
+ reset_adv_link();
+ cb->link_closed(&pb_adv, cb_data, reason);
+}
+
+static struct os_mbuf *adv_buf_create(uint8_t retransmits)
+{
+ struct os_mbuf *buf;
+
+ buf = bt_mesh_adv_create(BT_MESH_ADV_PROV,
+ BT_MESH_TRANSMIT(retransmits, 20),
+ BUF_TIMEOUT);
+ if (!buf) {
+ BT_ERR("Out of provisioning buffers");
+ return NULL;
+ }
+
+ return buf;
+}
+
+static void ack_complete(uint16_t duration, int err, void *user_data)
+{
+ BT_DBG("xact 0x%x complete", (uint8_t)link.tx.pending_ack);
+ atomic_clear_bit(link.flags, ADV_ACK_PENDING);
+}
+
+static bool ack_pending(void)
+{
+ return atomic_test_bit(link.flags, ADV_ACK_PENDING);
+}
+
+static void prov_failed(uint8_t err)
+{
+ BT_DBG("%u", err);
+ link.cb->error(&pb_adv, link.cb_data, err);
+ atomic_set_bit(link.flags, ADV_LINK_INVALID);
+}
+
+static void prov_msg_recv(void)
+{
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
+ BT_ERR("Incorrect FCS");
+ return;
+ }
+
+ gen_prov_ack_send(link.rx.id);
+
+ if (atomic_test_bit(link.flags, ADV_LINK_INVALID)) {
+ BT_WARN("Unexpected msg 0x%02x on invalidated link",
+ link.rx.buf->om_data[0]);
+ prov_failed(PROV_ERR_UNEXP_PDU);
+ return;
+ }
+
+ link.cb->recv(&pb_adv, link.cb_data, link.rx.buf);
+}
+
+static void protocol_timeout(struct ble_npl_event *work)
+{
+ BT_DBG("");
+
+ link.rx.seg = 0U;
+ close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
+}
+/*******************************************************************************
+ * Generic provisioning
+ ******************************************************************************/
+
+static void gen_prov_ack_send(uint8_t xact_id)
+{
+ static const struct bt_mesh_send_cb cb = {
+ .start = ack_complete,
+ };
+ const struct bt_mesh_send_cb *complete;
+ struct os_mbuf *buf;
+ bool pending = atomic_test_and_set_bit(link.flags, ADV_ACK_PENDING);
+
+ BT_DBG("xact_id 0x%x", xact_id);
+
+ if (pending && link.tx.pending_ack == xact_id) {
+ BT_DBG("Not sending duplicate ack");
+ return;
+ }
+
+ buf = adv_buf_create(RETRANSMITS_ACK);
+ if (!buf) {
+ atomic_clear_bit(link.flags, ADV_ACK_PENDING);
+ return;
+ }
+
+ if (pending) {
+ complete = NULL;
+ } else {
+ link.tx.pending_ack = xact_id;
+ complete = &cb;
+ }
+
+ net_buf_add_be32(buf, link.id);
+ net_buf_add_u8(buf, xact_id);
+ net_buf_add_u8(buf, GPC_ACK);
+
+ bt_mesh_adv_send(buf, complete, NULL);
+ net_buf_unref(buf);
+}
+
+static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t seg = CONT_SEG_INDEX(rx->gpc);
+
+ BT_DBG("len %u, seg_index %u", buf->om_len, seg);
+
+ if (!link.rx.seg && link.rx.id == rx->xact_id) {
+ if (!ack_pending()) {
+ BT_DBG("Resending ack");
+ gen_prov_ack_send(rx->xact_id);
+ }
+
+ return;
+ }
+
+ if (!link.rx.seg &&
+ next_transaction_id(link.rx.id) == rx->xact_id) {
+ BT_DBG("Start segment lost");
+
+ link.rx.id = rx->xact_id;
+
+ net_buf_simple_reset(link.rx.buf);
+ link.rx.seg = SEG_NVAL;
+ link.rx.last_seg = SEG_NVAL;
+
+ prov_clear_tx();
+ } else if (rx->xact_id != link.rx.id) {
+ BT_WARN("Data for unknown transaction (0x%x != 0x%x)",
+ rx->xact_id, link.rx.id);
+ return;
+ }
+
+ if (seg > link.rx.last_seg) {
+ BT_ERR("Invalid segment index %u", seg);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (!(link.rx.seg & BIT(seg))) {
+ BT_DBG("Ignoring already received segment");
+ return;
+ }
+
+ memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len);
+ XACT_SEG_RECV(seg);
+
+ if (seg == link.rx.last_seg && !(link.rx.seg & BIT(0))) {
+ uint8_t expect_len;
+
+ expect_len = (link.rx.buf->om_len - 20U -
+ ((link.rx.last_seg - 1) * 23U));
+ if (expect_len != buf->om_len) {
+ BT_ERR("Incorrect last seg len: %u != %u", expect_len,
+ buf->om_len);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+ }
+
+ if (!link.rx.seg) {
+ prov_msg_recv();
+ }
+}
+
+static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (!link.tx.buf[0]) {
+ return;
+ }
+
+ if (rx->xact_id == link.tx.id) {
+ /* Don't clear resending of link_close messages */
+ if (!atomic_test_bit(link.flags, ADV_LINK_CLOSING)) {
+ prov_clear_tx();
+ }
+
+ if (link.tx.cb) {
+ link.tx.cb(0, link.tx.cb_data);
+ }
+ }
+}
+
+static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ uint8_t seg = SEG_NVAL;
+
+ if (rx->xact_id == link.rx.id) {
+ if (!link.rx.seg) {
+ if (!ack_pending()) {
+ BT_DBG("Resending ack");
+ gen_prov_ack_send(rx->xact_id);
+ }
+
+ return;
+ }
+
+ if (!(link.rx.seg & BIT(0))) {
+ BT_DBG("Ignoring duplicate segment");
+ return;
+ }
+ } else if (rx->xact_id != next_transaction_id(link.rx.id)) {
+ BT_WARN("Unexpected xact 0x%x, expected 0x%x", rx->xact_id,
+ next_transaction_id(link.rx.id));
+ return;
+ }
+
+ net_buf_simple_reset(link.rx.buf);
+ link.rx.buf->om_len = net_buf_simple_pull_be16(buf);
+ link.rx.id = rx->xact_id;
+ link.rx.fcs = net_buf_simple_pull_u8(buf);
+
+ BT_DBG("%p len %u last_seg %u total_len %u fcs 0x%02x", link.rx.buf, buf->om_len,
+ START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs);
+
+ if (link.rx.buf->om_len < 1) {
+ BT_ERR("Ignoring zero-length provisioning PDU");
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20U) {
+ BT_ERR("Too small total length for multi-segment PDU");
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ prov_clear_tx();
+
+ link.rx.last_seg = START_LAST_SEG(rx->gpc);
+ if ((link.rx.seg & BIT(0)) &&
+ (find_msb_set((~link.rx.seg) & SEG_NVAL) - 1 > link.rx.last_seg)) {
+ BT_ERR("Invalid segment index %u", seg);
+ prov_failed(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (link.rx.seg) {
+ seg = link.rx.seg;
+ }
+
+ link.rx.seg = seg & ((1 << (START_LAST_SEG(rx->gpc) + 1)) - 1);
+ memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len);
+ XACT_SEG_RECV(0);
+
+ if (!link.rx.seg) {
+ prov_msg_recv();
+ }
+}
+
+static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len);
+
+ switch (BEARER_CTL(rx->gpc)) {
+ case LINK_OPEN:
+ link_open(rx, buf);
+ break;
+ case LINK_ACK:
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return;
+ }
+
+ link_ack(rx, buf);
+ break;
+ case LINK_CLOSE:
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return;
+ }
+
+ link_close(rx, buf);
+ break;
+ default:
+ BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
+
+ if (IS_ENABLED(CONFIG_BT_TESTING)) {
+ bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc));
+ }
+
+ return;
+ }
+}
+
+static const struct {
+ void (*func)(struct prov_rx *rx, struct os_mbuf *buf);
+ bool require_link;
+ uint8_t min_len;
+} gen_prov[] = {
+ { gen_prov_start, true, 3 },
+ { gen_prov_ack, true, 0 },
+ { gen_prov_cont, true, 0 },
+ { gen_prov_ctl, false, 0 },
+};
+
+static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) {
+ BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
+ return;
+ }
+
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE) &&
+ gen_prov[GPCF(rx->gpc)].require_link) {
+ BT_DBG("Ignoring message that requires active link");
+ return;
+ }
+
+ gen_prov[GPCF(rx->gpc)].func(rx, buf);
+}
+
+/*******************************************************************************
+ * TX
+ ******************************************************************************/
+
+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];
+
+ if (!buf) {
+ break;
+ }
+
+ 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);
+ }
+ }
+}
+
+static void prov_retransmit(struct ble_npl_event *work)
+{
+ int32_t timeout_ms;
+ int i;
+
+ BT_DBG("");
+
+ if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ BT_WARN("Link not active");
+ 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");
+ close_link(PROV_BEARER_LINK_STATUS_TIMEOUT);
+ }
+
+ 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);
+ }
+ }
+}
+
+static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len,
+ bool reliable)
+{
+ struct os_mbuf *buf;
+
+ BT_DBG("op 0x%02x data_len %u", op, data_len);
+
+ prov_clear_tx();
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ buf = adv_buf_create(reliable ? RETRANSMITS_RELIABLE :
+ RETRANSMITS_UNRELIABLE);
+ if (!buf) {
+ return -ENOBUFS;
+ }
+
+ net_buf_add_be32(buf, link.id);
+ /* Transaction ID, always 0 for Bearer messages */
+ net_buf_add_u8(buf, 0x00);
+ net_buf_add_u8(buf, GPC_CTL(op));
+ net_buf_add_mem(buf, data, data_len);
+
+ if (reliable) {
+ link.tx.buf[0] = buf;
+ send_reliable();
+ } else {
+ bt_mesh_adv_send(buf, &buf_sent_cb, NULL);
+ net_buf_unref(buf);
+ }
+
+ return 0;
+}
+
+static int prov_send_adv(struct os_mbuf *msg,
+ prov_bearer_send_complete_t cb, void *cb_data)
+{
+ struct os_mbuf *start, *buf;
+ uint8_t seg_len, seg_id;
+
+ prov_clear_tx();
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ start = adv_buf_create(RETRANSMITS_RELIABLE);
+ if (!start) {
+ return -ENOBUFS;
+ }
+
+ link.tx.id = next_transaction_id(link.tx.id);
+ net_buf_add_be32(start, link.id);
+ net_buf_add_u8(start, link.tx.id);
+
+ net_buf_add_u8(start, GPC_START(last_seg(msg->om_len)));
+ net_buf_add_be16(start, msg->om_len);
+ net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len));
+
+ link.tx.buf[0] = start;
+ link.tx.cb = cb;
+ link.tx.cb_data = cb_data;
+
+ BT_DBG("xact_id: 0x%x len: %u", link.tx.id, msg->om_len);
+
+ seg_len = MIN(msg->om_len, START_PAYLOAD_MAX);
+ BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len));
+ net_buf_add_mem(start, msg->om_data, seg_len);
+ net_buf_simple_pull_mem(msg, seg_len);
+
+ buf = start;
+ for (seg_id = 1U; msg->om_len > 0; seg_id++) {
+ if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
+ BT_ERR("Too big message");
+ free_segments();
+ return -E2BIG;
+ }
+
+ buf = adv_buf_create(RETRANSMITS_RELIABLE);
+ if (!buf) {
+ free_segments();
+ return -ENOBUFS;
+ }
+
+ link.tx.buf[seg_id] = buf;
+
+ seg_len = MIN(msg->om_len, CONT_PAYLOAD_MAX);
+
+ BT_DBG("seg %u len %u: %s", seg_id, seg_len,
+ bt_hex(msg->om_data, seg_len));
+
+ net_buf_add_be32(buf, link.id);
+ net_buf_add_u8(buf, link.tx.id);
+ net_buf_add_u8(buf, GPC_CONT(seg_id));
+ net_buf_add_mem(buf, msg->om_data, seg_len);
+ net_buf_simple_pull_mem(msg, seg_len);
+ }
+
+ send_reliable();
+
+ return 0;
+}
+
+/*******************************************************************************
+ * Link management rx
+ ******************************************************************************/
+
+static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (buf->om_len < 16) {
+ BT_ERR("Too short bearer open message (len %u)", buf->om_len);
+ return;
+ }
+
+ 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 {
+ BT_DBG("Ignoring bearer open: link already active");
+ }
+
+ return;
+ }
+
+ if (memcmp(buf->om_data, bt_mesh_prov_get()->uuid, 16)) {
+ BT_DBG("Bearer open message not for us");
+ return;
+ }
+
+ link.id = rx->link_id;
+ atomic_set_bit(link.flags, ADV_LINK_ACTIVE);
+ net_buf_simple_reset(link.rx.buf);
+
+ bearer_ctl_send(LINK_ACK, NULL, 0, false);
+
+ link.cb->link_opened(&pb_adv, link.cb_data);
+}
+
+static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (atomic_test_bit(link.flags, ADV_PROVISIONER)) {
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACK_RECVD)) {
+ return;
+ }
+
+ prov_clear_tx();
+
+ link.cb->link_opened(&pb_adv, link.cb_data);
+ }
+}
+
+static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
+{
+ BT_DBG("len %u", buf->om_len);
+
+ if (buf->om_len != 1) {
+ return;
+ }
+
+ close_link(net_buf_simple_pull_u8(buf));
+}
+
+/*******************************************************************************
+ * Higher level functionality
+ ******************************************************************************/
+
+void bt_mesh_pb_adv_recv(struct os_mbuf *buf)
+{
+ struct prov_rx rx;
+
+ if (!link.cb) {
+ return;
+ }
+
+ if (buf->om_len < 6) {
+ BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
+ return;
+ }
+
+ rx.link_id = net_buf_simple_pull_be32(buf);
+ rx.xact_id = net_buf_simple_pull_u8(buf);
+ rx.gpc = net_buf_simple_pull_u8(buf);
+
+ if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE) && link.id != rx.link_id) {
+ return;
+ }
+
+ BT_DBG("link_id 0x%08x xact_id 0x%x", rx.link_id, rx.xact_id);
+
+ gen_prov_recv(&rx, buf);
+}
+
+static int prov_link_open(const uint8_t uuid[16], int32_t timeout,
+ const struct prov_bearer_cb *cb, void *cb_data)
+{
+ BT_DBG("uuid %s", bt_hex(uuid, 16));
+
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ atomic_set_bit(link.flags, ADV_PROVISIONER);
+
+ bt_rand(&link.id, sizeof(link.id));
+ link.tx.id = XACT_ID_MAX;
+ link.rx.id = XACT_ID_NVAL;
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ net_buf_simple_reset(link.rx.buf);
+
+ bearer_ctl_send(LINK_OPEN, uuid, 16, true);
+
+ return 0;
+}
+
+static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data)
+{
+ if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ link.rx.id = XACT_ID_MAX;
+ link.tx.id = XACT_ID_NVAL;
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ /* Make sure we're scanning for provisioning inviations */
+ bt_mesh_scan_enable();
+ /* Enable unprovisioned beacon sending */
+ bt_mesh_beacon_enable();
+
+ return 0;
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+ if (atomic_test_and_set_bit(link.flags, ADV_LINK_CLOSING)) {
+ return;
+ }
+
+ bearer_ctl_send(LINK_CLOSE, &status, 1, true);
+}
+
+void pb_adv_init(void)
+{
+ k_delayed_work_init(&link.prot_timer, protocol_timeout);
+ k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
+
+ if (!rx_buf) {
+ rx_buf = NET_BUF_SIMPLE(65);
+ }
+ link.rx.buf = rx_buf;
+ net_buf_simple_reset(link.rx.buf);
+}
+
+void pb_adv_reset(void)
+{
+ reset_adv_link();
+}
+
+const struct prov_bearer pb_adv = {
+ .type = BT_MESH_PROV_ADV,
+ .link_open = prov_link_open,
+ .link_accept = prov_link_accept,
+ .link_close = prov_link_close,
+ .send = prov_send_adv,
+ .clear_tx = prov_clear_tx,
+};
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/pb_gatt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/pb_gatt.c
new file mode 100644
index 000000000..2b28c91f4
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/pb_gatt.c
@@ -0,0 +1,163 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_MESH)
+
+#include "../include/mesh/mesh.h"
+#include "prov.h"
+#include "net.h"
+#include "proxy.h"
+#include "adv.h"
+#include "prov.h"
+
+struct prov_link {
+ uint16_t conn_handle;
+ const struct prov_bearer_cb *cb;
+ void *cb_data;
+ struct {
+ uint8_t id; /* Transaction ID */
+ uint8_t prev_id; /* Previous Transaction ID */
+ 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_delayed_work prot_timer;
+};
+
+static struct prov_link link;
+
+static void reset_state(void)
+{
+ link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
+
+ k_delayed_work_cancel(&link.prot_timer);
+
+ link.rx.buf = bt_mesh_proxy_get_buf();
+}
+
+static void link_closed(enum prov_bearer_link_status status)
+{
+ const struct prov_bearer_cb *cb = link.cb;
+
+ void *cb_data = link.cb_data;
+
+ reset_state();
+
+ cb->link_closed(&pb_gatt, cb_data, status);
+}
+
+static void protocol_timeout(struct ble_npl_event *work)
+{
+ BT_DBG("Protocol timeout");
+
+ link_closed(PROV_BEARER_LINK_STATUS_TIMEOUT);
+}
+
+int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf)
+{
+ BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
+
+ if (link.conn_handle != conn_handle || !link.cb) {
+ BT_WARN("Data for unexpected connection");
+ return -ENOTCONN;
+ }
+
+ if (buf->om_len < 1) {
+ BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
+ return -EINVAL;
+ }
+
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ link.cb->recv(&pb_gatt, link.cb_data, buf);
+
+ return 0;
+}
+
+int bt_mesh_pb_gatt_open(uint16_t conn_handle)
+{
+ BT_DBG("conn %p", conn_handle);
+
+ if (link.conn_handle) {
+ return -EBUSY;
+ }
+
+ link.conn_handle = conn_handle;
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ link.cb->link_opened(&pb_gatt, link.cb_data);
+
+ return 0;
+}
+
+int bt_mesh_pb_gatt_close(uint16_t conn_handle)
+{
+ BT_DBG("conn %p", conn_handle);
+
+ if (link.conn_handle != conn_handle) {
+ BT_DBG("Not connected");
+ return -ENOTCONN;
+ }
+
+ link.cb->link_closed(&pb_gatt, link.cb_data,
+ PROV_BEARER_LINK_STATUS_SUCCESS);
+
+ reset_state();
+
+ return 0;
+}
+
+static int link_accept(const struct prov_bearer_cb *cb, void *cb_data)
+{
+ bt_mesh_proxy_prov_enable();
+ bt_mesh_adv_update();
+
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ return 0;
+}
+
+static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb,
+ void *cb_data)
+{
+ if (!link.conn_handle) {
+ return -ENOTCONN;
+ }
+
+ k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, buf);
+}
+
+static void clear_tx(void)
+{
+ /* No action */
+}
+
+void pb_gatt_init(void)
+{
+ k_delayed_work_init(&link.prot_timer, protocol_timeout);
+}
+
+void pb_gatt_reset(void)
+{
+ reset_state();
+}
+const struct prov_bearer pb_gatt = {
+ .type = BT_MESH_PROV_GATT,
+ .link_accept = link_accept,
+ .send = buf_send,
+ .clear_tx = clear_tx,
+};
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c
index f8f22fa7e..25e34ed75 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.c
@@ -11,8 +11,6 @@
#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
-#if MYNEWT_VAL(BLE_MESH_PROV)
-
#include
#include "../include/mesh/mesh.h"
@@ -20,700 +18,51 @@
#include "crypto.h"
#include "atomic.h"
-#include "adv.h"
#include "net.h"
#include "access.h"
#include "foundation.h"
-#include "proxy.h"
#include "prov.h"
-#include "testing.h"
-#include "settings.h"
-#include "nodes.h"
-/* 3 transmissions, 20ms interval */
-#define PROV_XMIT BT_MESH_TRANSMIT(2, 20)
+struct bt_mesh_prov_link bt_mesh_prov_link;
+const struct bt_mesh_prov *bt_mesh_prov;
-#define AUTH_METHOD_NO_OOB 0x00
-#define AUTH_METHOD_STATIC 0x01
-#define AUTH_METHOD_OUTPUT 0x02
-#define AUTH_METHOD_INPUT 0x03
-
-#define OUTPUT_OOB_BLINK 0x00
-#define OUTPUT_OOB_BEEP 0x01
-#define OUTPUT_OOB_VIBRATE 0x02
-#define OUTPUT_OOB_NUMBER 0x03
-#define OUTPUT_OOB_STRING 0x04
-
-#define INPUT_OOB_PUSH 0x00
-#define INPUT_OOB_TWIST 0x01
-#define INPUT_OOB_NUMBER 0x02
-#define INPUT_OOB_STRING 0x03
-
-#define PUB_KEY_NO_OOB 0x00
-#define PUB_KEY_OOB 0x01
-
-#define PROV_ERR_NONE 0x00
-#define PROV_ERR_NVAL_PDU 0x01
-#define PROV_ERR_NVAL_FMT 0x02
-#define PROV_ERR_UNEXP_PDU 0x03
-#define PROV_ERR_CFM_FAILED 0x04
-#define PROV_ERR_RESOURCES 0x05
-#define PROV_ERR_DECRYPT 0x06
-#define PROV_ERR_UNEXP_ERR 0x07
-#define PROV_ERR_ADDR 0x08
-
-#define PROV_INVITE 0x00
-#define PROV_CAPABILITIES 0x01
-#define PROV_START 0x02
-#define PROV_PUB_KEY 0x03
-#define PROV_INPUT_COMPLETE 0x04
-#define PROV_CONFIRM 0x05
-#define PROV_RANDOM 0x06
-#define PROV_DATA 0x07
-#define PROV_COMPLETE 0x08
-#define PROV_FAILED 0x09
-
-#define PROV_NO_PDU 0xff
-
-#define PROV_ALG_P256 0x00
-
-#define GPCF(gpc) (gpc & 0x03)
-#define GPC_START(last_seg) (((last_seg) << 2) | 0x00)
-#define GPC_ACK 0x01
-#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02)
-#define GPC_CTL(op) (((op) << 2) | 0x03)
-
-#define START_PAYLOAD_MAX 20
-#define CONT_PAYLOAD_MAX 23
-
-#define START_LAST_SEG(gpc) (gpc >> 2)
-#define CONT_SEG_INDEX(gpc) (gpc >> 2)
-
-#define BEARER_CTL(gpc) (gpc >> 2)
-#define LINK_OPEN 0x00
-#define LINK_ACK 0x01
-#define LINK_CLOSE 0x02
-
-#define CLOSE_REASON_SUCCESS 0x00
-#define CLOSE_REASON_TIMEOUT 0x01
-#define CLOSE_REASON_FAILED 0x02
-
-#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)])
-#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
-
-#define XACT_NVAL 0xff
-
-enum {
- WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
- LINK_ACTIVE, /* Link has been opened */
- LINK_ACK_RECVD, /* Ack for link has been received */
- LINK_CLOSING, /* Link is closing down */
- SEND_PUB_KEY, /* Waiting to send PubKey */
- WAIT_NUMBER, /* Waiting for number input from user */
- WAIT_STRING, /* Waiting for string input from user */
- NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */
- LINK_INVALID, /* Error occurred during provisioning */
- PROVISIONER, /* The link was opened as provisioner */
-
- NUM_FLAGS,
-};
-
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-#define PROVISIONER_LINK 1
-#else
-#define PROVISIONER_LINK 0
-#endif
-
-struct provisioner_link {
- struct bt_mesh_node *node;
- u16_t addr;
- u16_t net_idx;
- u8_t attention_duration;
-};
-
-struct prov_link {
- ATOMIC_DEFINE(flags, NUM_FLAGS);
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- uint16_t conn_handle; /* GATT connection */
-#endif
- struct provisioner_link provisioner[PROVISIONER_LINK];
-
- u8_t dhkey[32]; /* Calculated DHKey */
- u8_t expect; /* Next expected PDU */
-
- u8_t oob_method;
- u8_t oob_action;
- u8_t oob_size;
-
- u8_t conf[16]; /* Remote Confirmation */
- u8_t rand[16]; /* Local Random */
- u8_t auth[16]; /* Authentication Value */
-
- u8_t conf_salt[16]; /* ConfirmationSalt */
- u8_t conf_key[16]; /* ConfirmationKey */
- u8_t conf_inputs[145]; /* ConfirmationInputs */
- u8_t prov_salt[16]; /* Provisioning Salt */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- u32_t id; /* Link ID */
-
- struct {
- u8_t id; /* Transaction ID */
- u8_t prev_id; /* Previous Transaction ID */
- u8_t seg; /* Bit-field of unreceived segments */
- u8_t last_seg; /* Last segment (to check length) */
- u8_t fcs; /* Expected FCS value */
- struct os_mbuf *buf;
- } rx;
-
- struct {
- /* Start timestamp of the transaction */
- s64_t start;
-
- /* Transaction id*/
- u8_t id;
-
- /* Pending outgoing buffer(s) */
- struct os_mbuf *buf[3];
-
- /* Retransmit timer */
- struct k_delayed_work retransmit;
- } tx;
-#endif
-
- struct k_delayed_work prot_timer;
-};
-
-struct prov_rx {
- u32_t link_id;
- u8_t xact_id;
- u8_t gpc;
-};
-
-#define RETRANSMIT_TIMEOUT K_MSEC(500)
-#define BUF_TIMEOUT K_MSEC(400)
-#define CLOSING_TIMEOUT K_SECONDS(3)
-#define TRANSACTION_TIMEOUT K_SECONDS(30)
-#define PROTOCOL_TIMEOUT K_SECONDS(60)
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-#define PROV_BUF_HEADROOM 5
-#else
-#define PROV_BUF_HEADROOM 0
-static struct os_mbuf *rx_buf;
-#endif
-
-#define PROV_BUF(len) NET_BUF_SIMPLE(PROV_BUF_HEADROOM + len)
-
-static struct prov_link link;
-
-static const struct bt_mesh_prov *prov;
-
-static void pub_key_ready(const u8_t *pkey);
-
-static int reset_state(void)
+static void pub_key_ready(const uint8_t *pkey)
{
- static struct bt_pub_key_cb pub_key_cb = {
- .func = pub_key_ready,
- };
- int err;
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+ BT_DBG("Local public key ready");
+}
- k_delayed_work_cancel(&link.prot_timer);
+int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64]))
+{
+ BT_DBG("bt_mesh_prov_reset_state");
+
+ int err;
+ static struct bt_pub_key_cb pub_key_cb;
+ const size_t offset = offsetof(struct bt_mesh_prov_link, dhkey);
+
+ pub_key_cb.func = func ? func : pub_key_ready;
/* Disable Attention Timer if it was set */
- if (link.conf_inputs[0]) {
+ if (bt_mesh_prov_link.conf_inputs[0]) {
bt_mesh_attention(NULL, 0);
}
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- link.provisioner->node != NULL) {
- bt_mesh_node_del(link.provisioner->node, false);
- }
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- /* Clear everything except the retransmit and protocol timer
- * delayed work objects.
- */
- (void)memset(&link, 0, offsetof(struct prov_link, tx.retransmit));
- link.rx.prev_id = XACT_NVAL;
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.rx.buf = bt_mesh_proxy_get_buf();
-#else
- if (!rx_buf) {
- rx_buf = NET_BUF_SIMPLE(65);
- }
- net_buf_simple_init(rx_buf, 0);
- link.rx.buf = rx_buf;
-#endif /* PB_GATT */
-
-#else /* !PB_ADV */
- /* Clear everything except the protocol timer (k_delayed_work) */
- (void)memset(&link, 0, offsetof(struct prov_link, prot_timer));
-#endif /* PB_ADV */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.conn_handle = BLE_HS_CONN_HANDLE_NONE;
-#endif
+ atomic_clear(bt_mesh_prov_link.flags);
+ (void)memset((uint8_t *)&bt_mesh_prov_link + offset, 0,
+ sizeof(bt_mesh_prov_link) - offset);
err = bt_pub_key_gen(&pub_key_cb);
if (err) {
BT_ERR("Failed to generate public key (%d)", err);
return err;
}
-
return 0;
}
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-static void buf_sent(int err, void *user_data)
-{
- BT_DBG("buf_sent");
-
- if (!link.tx.buf[0]) {
- return;
- }
-
- k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT);
-}
-
-static struct bt_mesh_send_cb buf_sent_cb = {
- .end = buf_sent,
-};
-
-static void free_segments(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) {
- struct os_mbuf *buf = link.tx.buf[i];
-
- if (!buf) {
- break;
- }
-
- link.tx.buf[i] = NULL;
- /* Mark as canceled */
- BT_MESH_ADV(buf)->busy = 0;
- net_buf_unref(buf);
- }
-}
-
-static void prov_clear_tx(void)
-{
- BT_DBG("");
-
- k_delayed_work_cancel(&link.tx.retransmit);
-
- free_segments();
-}
-
-static void reset_adv_link(void)
-{
- prov_clear_tx();
-
- if (prov->link_close) {
- prov->link_close(BT_MESH_PROV_ADV);
- }
-
- reset_state();
-}
-
-static struct os_mbuf *adv_buf_create(void)
-{
- struct os_mbuf *buf;
-
- buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, PROV_XMIT, BUF_TIMEOUT);
- if (!buf) {
- BT_ERR("Out of provisioning buffers");
- assert(0);
- return NULL;
- }
-
- return buf;
-}
-
-static u8_t pending_ack = XACT_NVAL;
-
-static void ack_complete(u16_t duration, int err, void *user_data)
-{
- BT_DBG("xact %u complete", (u8_t)pending_ack);
- pending_ack = XACT_NVAL;
-}
-
-static void gen_prov_ack_send(u8_t xact_id)
-{
- static const struct bt_mesh_send_cb cb = {
- .start = ack_complete,
- };
- const struct bt_mesh_send_cb *complete;
- struct os_mbuf *buf;
-
- BT_DBG("xact_id %u", xact_id);
-
- if (pending_ack == xact_id) {
- BT_DBG("Not sending duplicate ack");
- return;
- }
-
- buf = adv_buf_create();
- if (!buf) {
- return;
- }
-
- if (pending_ack == XACT_NVAL) {
- pending_ack = xact_id;
- complete = &cb;
- } else {
- complete = NULL;
- }
-
- net_buf_add_be32(buf, link.id);
- net_buf_add_u8(buf, xact_id);
- net_buf_add_u8(buf, GPC_ACK);
-
- bt_mesh_adv_send(buf, complete, NULL);
- net_buf_unref(buf);
-}
-
-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];
-
- if (!buf) {
- break;
- }
-
- 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);
- }
- }
-}
-
-static int bearer_ctl_send(u8_t op, const void *data, u8_t data_len)
-{
- struct os_mbuf *buf;
-
- BT_DBG("op 0x%02x data_len %u", op, data_len);
-
- prov_clear_tx();
-
- buf = adv_buf_create();
- if (!buf) {
- return -ENOBUFS;
- }
-
- net_buf_add_be32(buf, link.id);
- /* Transaction ID, always 0 for Bearer messages */
- net_buf_add_u8(buf, 0x00);
- net_buf_add_u8(buf, GPC_CTL(op));
- net_buf_add_mem(buf, data, data_len);
-
- link.tx.buf[0] = buf;
- send_reliable();
-
- return 0;
-}
-
-static u8_t last_seg(u8_t len)
-{
- if (len <= START_PAYLOAD_MAX) {
- return 0;
- }
-
- len -= START_PAYLOAD_MAX;
-
- return 1 + (len / CONT_PAYLOAD_MAX);
-}
-
-static inline u8_t next_transaction_id(void)
-{
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- if (link.tx.id != 0x7F) {
- link.tx.id++;
- } else {
- link.tx.id = 0;
- }
- } else {
- if (link.tx.id != 0U && link.tx.id != 0xFF) {
- link.tx.id++;
- } else {
- link.tx.id = 0x80;
- }
- }
-
- return link.tx.id;
-}
-
-static int prov_send_adv(struct os_mbuf *msg)
-{
- struct os_mbuf *start, *buf;
- u8_t seg_len, seg_id;
- u8_t xact_id;
-
- BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len));
-
- prov_clear_tx();
-
- start = adv_buf_create();
- if (!start) {
- return -ENOBUFS;
- }
-
- xact_id = next_transaction_id();
- net_buf_add_be32(start, link.id);
- net_buf_add_u8(start, xact_id);
-
- net_buf_add_u8(start, GPC_START(last_seg(msg->om_len)));
- net_buf_add_be16(start, msg->om_len);
- net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len));
-
- link.tx.buf[0] = start;
-
- seg_len = min(msg->om_len, START_PAYLOAD_MAX);
- BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len));
- net_buf_add_mem(start, msg->om_data, seg_len);
- net_buf_simple_pull(msg, seg_len);
-
- buf = start;
- for (seg_id = 1; msg->om_len > 0; seg_id++) {
- if (seg_id >= ARRAY_SIZE(link.tx.buf)) {
- BT_ERR("Too big message");
- free_segments();
- return -E2BIG;
- }
-
- buf = adv_buf_create();
- if (!buf) {
- free_segments();
- return -ENOBUFS;
- }
-
- link.tx.buf[seg_id] = buf;
-
- seg_len = min(msg->om_len, CONT_PAYLOAD_MAX);
-
- BT_DBG("seg_id %u len %u: %s", seg_id, seg_len,
- bt_hex(msg->om_data, seg_len));
-
- net_buf_add_be32(buf, link.id);
- net_buf_add_u8(buf, xact_id);
- net_buf_add_u8(buf, GPC_CONT(seg_id));
- net_buf_add_mem(buf, msg->om_data, seg_len);
- net_buf_simple_pull(msg, seg_len);
- }
-
- send_reliable();
-
- return 0;
-}
-
-#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-static int prov_send_gatt(struct os_mbuf *msg)
-{
- if (link.conn_handle == BLE_HS_CONN_HANDLE_NONE) {
- BT_ERR("No connection handle!?");
- return -ENOTCONN;
- }
-
- return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, msg);
-}
-#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
-
-static inline int prov_send(struct os_mbuf *buf)
-{
- k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- return prov_send_gatt(buf);
- }
-#endif
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- return prov_send_adv(buf);
-#else
- return 0;
-#endif
-}
-
-static void prov_buf_init(struct os_mbuf *buf, u8_t type)
-{
- net_buf_simple_init(buf, PROV_BUF_HEADROOM);
- net_buf_simple_add_u8(buf, type);
-}
-
-static void prov_send_fail_msg(u8_t err)
-{
- struct os_mbuf *buf = PROV_BUF(2);
-
- prov_buf_init(buf, PROV_FAILED);
- net_buf_simple_add_u8(buf, err);
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send Provisioning Failed message");
- }
-
- atomic_set_bit(link.flags, LINK_INVALID);
-
- os_mbuf_free_chain(buf);
-}
-
-static void prov_invite(const u8_t *data)
-{
- struct os_mbuf *buf = PROV_BUF(12);
-
- BT_DBG("Attention Duration: %u seconds", data[0]);
-
- if (data[0]) {
- bt_mesh_attention(NULL, data[0]);
- }
-
- link.conf_inputs[0] = data[0];
-
- prov_buf_init(buf, PROV_CAPABILITIES);
-
- /* Number of Elements supported */
- net_buf_simple_add_u8(buf, bt_mesh_elem_count());
-
- /* 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);
-
- /* Static OOB Type */
- net_buf_simple_add_u8(buf, prov->static_val ? BIT(0) : 0x00);
-
- /* Output OOB Size */
- net_buf_simple_add_u8(buf, prov->output_size);
-
- /* Output OOB Action */
- net_buf_simple_add_be16(buf, prov->output_actions);
-
- /* Input OOB Size */
- net_buf_simple_add_u8(buf, prov->input_size);
-
- /* Input OOB Action */
- net_buf_simple_add_be16(buf, prov->input_actions);
-
- memcpy(&link.conf_inputs[1], &buf->om_data[1], 11);
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send capabilities");
- goto done;
- }
-
- link.expect = PROV_START;
-
-done:
- os_mbuf_free_chain(buf);
-}
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
-static void send_invite(void)
-{
- struct os_mbuf *inv = PROV_BUF(2);
-
- BT_DBG("");
-
- prov_buf_init(inv, PROV_INVITE);
- net_buf_simple_add_u8(inv, link.provisioner->attention_duration);
-
- link.conf_inputs[0] = link.provisioner->attention_duration;
-
- if (prov_send(inv)) {
- BT_ERR("Failed to send invite");
- goto done;
- }
-
- link.expect = PROV_CAPABILITIES;
-
-done:
- os_mbuf_free_chain(inv);
-}
-#endif
-
-static void send_start(void)
-{
- struct os_mbuf *start = PROV_BUF(6);
-
- BT_DBG("");
-
- prov_buf_init(start, PROV_START);
-
- net_buf_simple_add_u8(start, PROV_ALG_P256);
- net_buf_simple_add_u8(start, PUB_KEY_NO_OOB);
- net_buf_simple_add_u8(start, AUTH_METHOD_NO_OOB);
- memset(link.auth, 0, sizeof(link.auth));
-
- net_buf_simple_add_u8(start, 0); /* Auth Action */
- net_buf_simple_add_u8(start, 0); /* Auth Size */
-
- memcpy(&link.conf_inputs[12], &start->om_data[1], 5);
-
- if (prov_send(start)) {
- BT_ERR("Failed to send start");
- }
-
- os_mbuf_free_chain(start);
-}
-
-static void prov_capabilities(const u8_t *data)
-{
- u16_t algorithms, output_action, input_action;
-
- if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- return;
- }
-
- BT_DBG("Elements: %u", data[0]);
-
- algorithms = sys_get_be16(&data[1]);
- BT_DBG("Algorithms: %u", algorithms);
-
- BT_DBG("Public Key Type: 0x%02x", data[3]);
- BT_DBG("Static OOB Type: 0x%02x", data[4]);
- BT_DBG("Output OOB Size: %u", data[5]);
-
- output_action = sys_get_be16(&data[6]);
- BT_DBG("Output OOB Action: 0x%04x", output_action);
-
- BT_DBG("Input OOB Size: %u", data[8]);
-
- input_action = sys_get_be16(&data[9]);
- BT_DBG("Input OOB Action: 0x%04x", input_action);
-
- if (data[0] == 0) {
- BT_ERR("Invalid number of elements");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- link.provisioner->node = bt_mesh_node_alloc(link.provisioner->addr,
- data[0],
- link.provisioner->net_idx);
- if (link.provisioner->node == NULL) {
- prov_send_fail_msg(PROV_ERR_RESOURCES);
- return;
- }
-
- memcpy(&link.conf_inputs[1], data, 11);
-
- atomic_set_bit(link.flags, SEND_PUB_KEY);
-
- send_start();
-}
-
-static bt_mesh_output_action_t output_action(u8_t action)
+static bt_mesh_output_action_t output_action(uint8_t action)
{
switch (action) {
case OUTPUT_OOB_BLINK:
@@ -731,7 +80,7 @@ static bt_mesh_output_action_t output_action(u8_t action)
}
}
-static bt_mesh_input_action_t input_action(u8_t action)
+static bt_mesh_input_action_t input_action(uint8_t action)
{
switch (action) {
case INPUT_OOB_PUSH:
@@ -747,7 +96,7 @@ static bt_mesh_input_action_t input_action(u8_t action)
}
}
-static int prov_auth(u8_t method, u8_t action, u8_t size)
+int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size)
{
bt_mesh_output_action_t output;
bt_mesh_input_action_t input;
@@ -758,16 +107,15 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- memset(link.auth, 0, sizeof(link.auth));
+ (void)memset(bt_mesh_prov_link.auth, 0, sizeof(bt_mesh_prov_link.auth));
return 0;
case AUTH_METHOD_STATIC:
if (action || size) {
return -EINVAL;
}
- memcpy(link.auth + 16 - prov->static_val_len,
- prov->static_val, prov->static_val_len);
- memset(link.auth, 0, sizeof(link.auth) - prov->static_val_len);
+ atomic_set_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY);
+
return 0;
case AUTH_METHOD_OUTPUT:
@@ -776,19 +124,19 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- if (!(prov->output_actions & output)) {
+ if (!(bt_mesh_prov->output_actions & output)) {
return -EINVAL;
}
- if (size > prov->output_size) {
+ if (size > bt_mesh_prov->output_size) {
return -EINVAL;
}
- atomic_set_bit(link.flags, NOTIFY_INPUT_COMPLETE);
+ atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE);
if (output == BT_MESH_DISPLAY_STRING) {
unsigned char str[9];
- u8_t i;
+ uint8_t i;
bt_rand(str, size);
@@ -803,22 +151,23 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
}
str[size] = '\0';
- memcpy(link.auth, str, size);
- memset(link.auth + size, 0, sizeof(link.auth) - size);
+ memcpy(bt_mesh_prov_link.auth, str, size);
+ memset(bt_mesh_prov_link.auth + size, 0,
+ sizeof(bt_mesh_prov_link.auth) - size);
- return prov->output_string((char *)str);
+ return bt_mesh_prov->output_string((char *)str);
} else {
- u32_t div[8] = { 10, 100, 1000, 10000, 100000,
+ uint32_t div[8] = { 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000 };
- u32_t num;
+ uint32_t num;
bt_rand(&num, sizeof(num));
num %= div[size - 1];
- sys_put_be32(num, &link.auth[12]);
- memset(link.auth, 0, 12);
+ sys_put_be32(num, &bt_mesh_prov_link.auth[12]);
+ memset(bt_mesh_prov_link.auth, 0, 12);
- return prov->output_number(output, num);
+ return bt_mesh_prov->output_number(output, num);
}
case AUTH_METHOD_INPUT:
@@ -827,140 +176,38 @@ static int prov_auth(u8_t method, u8_t action, u8_t size)
return -EINVAL;
}
- if (!(prov->input_actions & input)) {
+ if (!(bt_mesh_prov->input_actions & input)) {
return -EINVAL;
}
- if (size > prov->input_size) {
+ if (size > bt_mesh_prov->input_size) {
return -EINVAL;
}
if (input == BT_MESH_ENTER_STRING) {
- atomic_set_bit(link.flags, WAIT_STRING);
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING);
} else {
- atomic_set_bit(link.flags, WAIT_NUMBER);
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER);
}
- return prov->input(input, size);
+ return bt_mesh_prov->input(input, size);
default:
return -EINVAL;
}
}
-static void prov_start(const u8_t *data)
-{
- BT_DBG("Algorithm: 0x%02x", data[0]);
- BT_DBG("Public Key: 0x%02x", data[1]);
- BT_DBG("Auth Method: 0x%02x", data[2]);
- BT_DBG("Auth Action: 0x%02x", data[3]);
- BT_DBG("Auth Size: 0x%02x", data[4]);
-
- if (data[0] != PROV_ALG_P256) {
- BT_ERR("Unknown algorithm 0x%02x", data[0]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- if (data[1] != PUB_KEY_NO_OOB) {
- BT_ERR("Invalid public key type: 0x%02x", data[1]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- memcpy(&link.conf_inputs[12], data, 5);
-
- /* TODO: reset link when auth fails? */
- link.expect = PROV_PUB_KEY;
-
- if (prov_auth(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]);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- }
-}
-
-static void send_confirm(void)
-{
- struct os_mbuf *cfm = PROV_BUF(17);
-
- BT_DBG("ConfInputs[0] %s", bt_hex(link.conf_inputs, 64));
- BT_DBG("ConfInputs[64] %s", bt_hex(&link.conf_inputs[64], 64));
- BT_DBG("ConfInputs[128] %s", bt_hex(&link.conf_inputs[128], 17));
-
- if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) {
- BT_ERR("Unable to generate confirmation salt");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("ConfirmationSalt: %s", bt_hex(link.conf_salt, 16));
-
- if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) {
- BT_ERR("Unable to generate confirmation key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("ConfirmationKey: %s", bt_hex(link.conf_key, 16));
-
- if (bt_rand(link.rand, 16)) {
- BT_ERR("Unable to generate random number");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("LocalRandom: %s", bt_hex(link.rand, 16));
-
- prov_buf_init(cfm, PROV_CONFIRM);
-
- if (bt_mesh_prov_conf(link.conf_key, link.rand, link.auth,
- net_buf_simple_add(cfm, 16))) {
- BT_ERR("Unable to generate confirmation value");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- if (prov_send(cfm)) {
- BT_ERR("Failed to send Provisioning Confirm");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_CONFIRM;
- } else {
- link.expect = PROV_RANDOM;
- }
-
-done:
- os_mbuf_free_chain(cfm);
-}
-
-static void send_input_complete(void)
-{
- struct os_mbuf *buf = PROV_BUF(1);
-
- prov_buf_init(buf, PROV_INPUT_COMPLETE);
- if (prov_send(buf)) {
- BT_ERR("Failed to send Provisioning Input Complete");
- }
- link.expect = PROV_CONFIRM;
-
- os_mbuf_free_chain(buf);
-}
-
-int bt_mesh_input_number(u32_t num)
+int bt_mesh_input_number(uint32_t num)
{
BT_DBG("%u", (unsigned) num);
- if (!atomic_test_and_clear_bit(link.flags, WAIT_NUMBER)) {
+ if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_NUMBER)) {
return -EINVAL;
}
- sys_put_be32(num, &link.auth[12]);
+ sys_put_be32(num, &bt_mesh_prov_link.auth[12]);
- send_input_complete();
+ bt_mesh_prov_link.role->input_complete();
return 0;
}
@@ -969,991 +216,145 @@ int bt_mesh_input_string(const char *str)
{
BT_DBG("%s", str);
- if (!atomic_test_and_clear_bit(link.flags, WAIT_STRING)) {
+ if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_STRING)) {
return -EINVAL;
}
- strncpy((char *)link.auth, str, prov->input_size);
+ strncpy((char *)bt_mesh_prov_link.auth, str, bt_mesh_prov->input_size);
- send_input_complete();
+ bt_mesh_prov_link.role->input_complete();
return 0;
}
-static void send_pub_key(void)
-{
- struct os_mbuf *buf = PROV_BUF(65);
- const u8_t *key;
-
- key = bt_pub_key_get();
- if (!key) {
- BT_ERR("No public key available");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Local Public Key: %s", bt_hex(key, 64));
-
- 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);
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- /* PublicKeyProvisioner */
- memcpy(&link.conf_inputs[17], &buf->om_data[1], 64);
- } else {
- /* PublicKeyRemote */
- memcpy(&link.conf_inputs[81], &buf->om_data[1], 64);
- }
-
- if (prov_send(buf)) {
- BT_ERR("Failed to send Public Key");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_PUB_KEY;
- } else {
- if (atomic_test_bit(link.flags, WAIT_NUMBER) ||
- atomic_test_bit(link.flags, WAIT_STRING)) {
- link.expect = PROV_NO_PDU; /* Wait for input */
- } else {
- link.expect = PROV_CONFIRM;
- }
- }
-
-done:
- os_mbuf_free_chain(buf);
-}
-
-static void prov_dh_key_cb(const u8_t dhkey[32])
-{
- BT_DBG("%p", dhkey);
-
- if (!dhkey) {
- BT_ERR("DHKey generation failed");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- sys_memcpy_swap(link.dhkey, dhkey, 32);
-
- BT_DBG("DHkey: %s", bt_hex(link.dhkey, 32));
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_confirm();
- } else {
- send_pub_key();
- }
-}
-
-static void prov_dh_key_gen(void)
-{
- u8_t remote_pk_le[64], *remote_pk;
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- remote_pk = &link.conf_inputs[81];
- } else {
- remote_pk = &link.conf_inputs[17];
- }
-
- /* Copy remote key in little-endian for bt_dh_key_gen().
- * 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);
-
- if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
- BT_ERR("Failed to generate DHKey");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- }
-}
-
-static void prov_pub_key(const u8_t *data)
-{
- BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- /* PublicKeyDevice */
- memcpy(&link.conf_inputs[81], data, 64);
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- prov_clear_tx();
-#endif
- } else {
- /* PublicKeyProvisioner */
- memcpy(&link.conf_inputs[17], data, 64);
-
- if (!bt_pub_key_get()) {
- /* Clear retransmit timer */
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
- prov_clear_tx();
-#endif
-
- atomic_set_bit(link.flags, WAIT_PUB_KEY);
- BT_WARN("Waiting for local public key");
- return;
- }
- }
-
- prov_dh_key_gen();
-}
-
-static void pub_key_ready(const u8_t *pkey)
-{
- if (!pkey) {
- BT_WARN("Public key not available");
- return;
- }
-
- BT_DBG("Local public key ready");
-
- if (atomic_test_and_clear_bit(link.flags, WAIT_PUB_KEY)) {
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_pub_key();
- } else {
- prov_dh_key_gen();
- }
- }
-}
-
-static void notify_input_complete(void)
-{
- if (atomic_test_and_clear_bit(link.flags, NOTIFY_INPUT_COMPLETE) &&
- prov->input_complete) {
- prov->input_complete();
- }
-}
-
-static void prov_input_complete(const u8_t *data)
-{
- BT_DBG("");
- notify_input_complete();
-}
-
-static void send_prov_data(void)
-{
- struct os_mbuf *pdu = PROV_BUF(34);
- struct bt_mesh_subnet *sub;
- u8_t session_key[16];
- u8_t nonce[13];
- int err;
-
- err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
- if (err) {
- BT_ERR("Unable to generate session key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
-
- err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
- if (err) {
- BT_ERR("Unable to generate session nonce");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Nonce: %s", bt_hex(nonce, 13));
-
- err = bt_mesh_dev_key(link.dhkey, link.prov_salt,
- link.provisioner->node->dev_key);
- if (err) {
- BT_ERR("Unable to generate device key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("DevKey: %s", bt_hex(link.provisioner->node->dev_key, 16));
-
- sub = bt_mesh_subnet_get(link.provisioner->node->net_idx);
- if (sub == NULL) {
- BT_ERR("No subnet with net_idx %u",
- link.provisioner->node->net_idx);
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- prov_buf_init(pdu, PROV_DATA);
- net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net, 16);
- net_buf_simple_add_be16(pdu, link.provisioner->node->net_idx);
- net_buf_simple_add_u8(pdu, bt_mesh_net_flags(sub));
- net_buf_simple_add_be32(pdu, bt_mesh.iv_index);
- net_buf_simple_add_be16(pdu, link.provisioner->node->addr);
- net_buf_simple_add(pdu, 8); /* For MIC */
-
- BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
- link.provisioner->node->net_idx, bt_mesh.iv_index,
- link.provisioner->node->addr);
-
- err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1],
- &pdu->om_data[1]);
- if (err) {
- BT_ERR("Unable to encrypt provisioning data");
- prov_send_fail_msg(PROV_ERR_DECRYPT);
- goto done;
- }
-
- if (prov_send(pdu)) {
- BT_ERR("Failed to send Provisioning Data");
- goto done;
- }
-
- link.expect = PROV_COMPLETE;
-
-done:
- os_mbuf_free_chain(pdu);
-}
-
-static void prov_complete(const u8_t *data)
-{
- if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- return;
- }
-
- struct bt_mesh_node *node = link.provisioner->node;
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- u8_t reason = CLOSE_REASON_SUCCESS;
-#endif
-
- BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
- bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
- node->addr);
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_node(node);
- }
-
- link.provisioner->node = NULL;
- link.expect = PROV_NO_PDU;
- atomic_set_bit(link.flags, LINK_CLOSING);
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
-#endif
-
- bt_mesh_prov_node_added(node->net_idx, node->addr, node->num_elem);
-
- /*
- * 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 instead of resetting the
- * link here.
- */
-}
-
-static void send_random(void)
-{
- struct os_mbuf *rnd = PROV_BUF(17);
-
- prov_buf_init(rnd, PROV_RANDOM);
- net_buf_simple_add_mem(rnd, link.rand, 16);
-
- if (prov_send(rnd)) {
- BT_ERR("Failed to send Provisioning Random");
- goto done;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- link.expect = PROV_RANDOM;
- } else {
- link.expect = PROV_DATA;
- }
-
-done:
- os_mbuf_free_chain(rnd);
-}
-
-static void prov_random(const u8_t *data)
-{
- u8_t conf_verify[16];
- const u8_t *prov_rand, *dev_rand;
-
- BT_DBG("Remote Random: %s", bt_hex(data, 16));
-
- if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) {
- BT_ERR("Unable to calculate confirmation verification");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- if (memcmp(conf_verify, link.conf, 16)) {
- BT_ERR("Invalid confirmation value");
- BT_DBG("Received: %s", bt_hex(link.conf, 16));
- BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
- prov_send_fail_msg(PROV_ERR_CFM_FAILED);
- return;
- }
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- prov_rand = link.rand;
- dev_rand = data;
- } else {
- prov_rand = data;
- dev_rand = link.rand;
- }
-
- if (bt_mesh_prov_salt(link.conf_salt, prov_rand, dev_rand,
- link.prov_salt)) {
- BT_ERR("Failed to generate provisioning salt");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- return;
- }
-
- BT_DBG("ProvisioningSalt: %s", bt_hex(link.prov_salt, 16));
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_bit(link.flags, PROVISIONER)) {
- send_prov_data();
- } else {
- send_random();
- }
-}
-
-static void prov_confirm(const u8_t *data)
-{
- BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
-
- memcpy(link.conf, data, 16);
-
- notify_input_complete();
-
- if (atomic_test_bit(link.flags, PROVISIONER)) {
- send_random();
- } else {
- send_confirm();
- }
-}
-
-static inline bool is_pb_gatt(void)
-{
-#if MYNEWT_VAL(BLE_MESH_PB_GATT)
- return (link.conn_handle != BLE_HS_CONN_HANDLE_NONE);
-#else
- return false;
-#endif
-}
-
-static void prov_data(const u8_t *data)
-{
- struct os_mbuf *msg = PROV_BUF(1);
- u8_t session_key[16];
- u8_t nonce[13];
- u8_t dev_key[16];
- u8_t pdu[25];
- u8_t flags;
- u32_t iv_index;
- u16_t addr;
- u16_t net_idx;
- int err;
- bool identity_enable;
-
- BT_DBG("");
-
- err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key);
- if (err) {
- BT_ERR("Unable to generate session key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
-
- err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce);
- if (err) {
- BT_ERR("Unable to generate session nonce");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("Nonce: %s", bt_hex(nonce, 13));
-
- err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
- if (err) {
- BT_ERR("Unable to decrypt provisioning data");
- prov_send_fail_msg(PROV_ERR_DECRYPT);
- goto done;
- }
-
- err = bt_mesh_dev_key(link.dhkey, link.prov_salt, dev_key);
- if (err) {
- BT_ERR("Unable to generate device key");
- prov_send_fail_msg(PROV_ERR_UNEXP_ERR);
- goto done;
- }
-
- BT_DBG("DevKey: %s", bt_hex(dev_key, 16));
-
- net_idx = sys_get_be16(&pdu[16]);
- flags = pdu[18];
- iv_index = sys_get_be32(&pdu[19]);
- addr = sys_get_be16(&pdu[23]);
-
- BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
- net_idx, (unsigned) iv_index, addr);
-
- prov_buf_init(msg, PROV_COMPLETE);
- if (prov_send(msg)) {
- BT_ERR("Failed to send Provisioning Complete");
- goto done;
- }
-
- /* Ignore any further PDUs on this link */
- link.expect = PROV_NO_PDU;
-
- /* Store info, since bt_mesh_provision() will end up clearing it */
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
- identity_enable = is_pb_gatt();
- } else {
- identity_enable = false;
- }
-
- err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
- if (err) {
- BT_ERR("Failed to provision (err %d)", err);
- goto done;
- }
-
- /* After PB-GATT provisioning we should start advertising
- * using Node Identity.
- */
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) {
- bt_mesh_proxy_identity_enable();
- }
-
-done:
- os_mbuf_free_chain(msg);
-}
-
-static void prov_failed(const u8_t *data)
-{
- BT_WARN("Error: 0x%02x", data[0]);
-}
-
-static const struct {
- void (*func)(const u8_t *data);
- u16_t len;
-} prov_handlers[] = {
- { 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 },
-};
-
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-static void prov_retransmit(struct ble_npl_event *work)
-{
- int i, timeout;
-
- BT_DBG("");
-
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- BT_WARN("Link not active");
- return;
- }
-
- if (atomic_test_bit(link.flags, LINK_CLOSING)) {
- timeout = CLOSING_TIMEOUT;
- } else {
- timeout = TRANSACTION_TIMEOUT;
- }
-
- if (k_uptime_get() - link.tx.start > timeout) {
- BT_WARN("Giving up transaction");
- reset_adv_link();
- 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);
- }
-
- }
-}
-
-static void link_open(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("link open: len %u", buf->om_len);
-
- if (buf->om_len < 16) {
- BT_ERR("Too short bearer open message (len %u)", buf->om_len);
- return;
- }
-
- if (atomic_test_bit(link.flags, LINK_ACTIVE)) {
- /* Send another link ack if the provisioner missed the last */
- if (link.id == rx->link_id && link.expect == PROV_INVITE) {
- BT_DBG("Resending link ack");
- bearer_ctl_send(LINK_ACK, NULL, 0);
- } else {
- BT_WARN("Ignoring bearer open: link already active");
- }
-
- return;
- }
-
- if (memcmp(buf->om_data, prov->uuid, 16)) {
- BT_DBG("Bearer open message not for us");
- return;
- }
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_ADV);
- }
-
- link.id = rx->link_id;
- atomic_set_bit(link.flags, LINK_ACTIVE);
- net_buf_simple_init(link.rx.buf, 0);
-
- bearer_ctl_send(LINK_ACK, NULL, 0);
-
- link.expect = PROV_INVITE;
-}
-
-static void link_ack(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("Link ack: len %u", buf->om_len);
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_bit(link.flags, PROVISIONER)) {
- if (atomic_test_and_set_bit(link.flags, LINK_ACK_RECVD)) {
- return;
- }
-
- prov_clear_tx();
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_ADV);
- }
-
- send_invite();
- }
-}
-
-static void link_close(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("Link close: len %u", buf->om_len);
-
- reset_adv_link();
-}
-
-static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len);
-
- switch (BEARER_CTL(rx->gpc)) {
- case LINK_OPEN:
- link_open(rx, buf);
- break;
- case LINK_ACK:
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- return;
- }
-
- link_ack(rx, buf);
- break;
- case LINK_CLOSE:
- if (!atomic_test_bit(link.flags, LINK_ACTIVE)) {
- return;
- }
-
- link_close(rx, buf);
- break;
- default:
- BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc));
-
- if (IS_ENABLED(CONFIG_BT_TESTING)) {
- bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc));
- }
-
- return;
- }
-}
-
-static void prov_msg_recv(void)
-{
- u8_t type = link.rx.buf->om_data[0];
-
- BT_DBG("type 0x%02x len %u", type, link.rx.buf->om_len);
-
- k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT);
-
- if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) {
- BT_ERR("Incorrect FCS");
- return;
- }
-
- gen_prov_ack_send(link.rx.id);
- link.rx.prev_id = link.rx.id;
- link.rx.id = 0;
-
- if (atomic_test_bit(link.flags, LINK_INVALID)) {
- BT_WARN("Unexpected msg 0x%02x on invalidated link", type);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return;
- }
-
- if (type != PROV_FAILED && type != link.expect) {
- BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return;
- }
-
- if (type >= ARRAY_SIZE(prov_handlers)) {
- BT_ERR("Unknown provisioning PDU type 0x%02x", type);
- prov_send_fail_msg(PROV_ERR_NVAL_PDU);
- return;
- }
-
- if (1 + prov_handlers[type].len != link.rx.buf->om_len) {
- BT_ERR("Invalid length %u for type 0x%02x",
- link.rx.buf->om_len, type);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- prov_handlers[type].func(&link.rx.buf->om_data[1]);
-}
-
-static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf)
-{
- u8_t seg = CONT_SEG_INDEX(rx->gpc);
-
- BT_DBG("len %u, seg_index %u", buf->om_len, seg);
-
- if (!link.rx.seg && link.rx.prev_id == rx->xact_id) {
- BT_WARN("Resending ack");
- gen_prov_ack_send(rx->xact_id);
- return;
- }
-
- if (rx->xact_id != link.rx.id) {
- BT_WARN("Data for unknown transaction (%u != %u)",
- rx->xact_id, link.rx.id);
- return;
- }
-
- if (seg > link.rx.last_seg) {
- BT_ERR("Invalid segment index %u", seg);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- } else if (seg == link.rx.last_seg) {
- u8_t expect_len;
-
- expect_len = (link.rx.buf->om_len - 20 -
- ((link.rx.last_seg - 1) * 23));
- if (expect_len != buf->om_len) {
- BT_ERR("Incorrect last seg len: %u != %u",
- expect_len, buf->om_len);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
- }
-
- if (!(link.rx.seg & BIT(seg))) {
- BT_WARN("Ignoring already received segment");
- return;
- }
-
- memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len);
- XACT_SEG_RECV(seg);
-
- if (!link.rx.seg) {
- prov_msg_recv();
- }
-}
-
-static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf)
-{
- BT_DBG("len %u", buf->om_len);
-
- if (!link.tx.buf[0]) {
- return;
- }
-
- if (rx->xact_id == link.tx.id) {
- /* Don't clear resending of LINK_CLOSE messages */
- if (!atomic_test_bit(link.flags, LINK_CLOSING)) {
- prov_clear_tx();
- }
-
- /* Send the PubKey when the the Start message is ACK'ed */
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_and_clear_bit(link.flags, SEND_PUB_KEY)) {
- if (!bt_pub_key_get()) {
- atomic_set_bit(link.flags, WAIT_PUB_KEY);
- BT_WARN("Waiting for local public key");
- } else {
- send_pub_key();
- }
- }
- }
-}
-
-static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf)
-{
- u16_t trailing_space = 0;
-
- if (link.rx.seg) {
- BT_WARN("Got Start while there are unreceived segments");
- return;
- }
-
- if (link.rx.prev_id == rx->xact_id) {
- BT_WARN("Resending ack");
- gen_prov_ack_send(rx->xact_id);
- return;
- }
-
- trailing_space = OS_MBUF_TRAILINGSPACE(link.rx.buf);
-
- link.rx.buf->om_len = net_buf_simple_pull_be16(buf);
- link.rx.id = rx->xact_id;
- link.rx.fcs = net_buf_simple_pull_u8(buf);
-
- BT_DBG("len %u last_seg %u total_len %u fcs 0x%02x", buf->om_len,
- START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs);
-
- if (link.rx.buf->om_len < 1) {
- BT_ERR("Ignoring zero-length provisioning PDU");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- if (link.rx.buf->om_len > trailing_space) {
- BT_ERR("Too large provisioning PDU (%u bytes)",
- link.rx.buf->om_len);
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20) {
- BT_ERR("Too small total length for multi-segment PDU");
- prov_send_fail_msg(PROV_ERR_NVAL_FMT);
- return;
- }
-
- link.rx.seg = (1 << (START_LAST_SEG(rx->gpc) + 1)) - 1;
- link.rx.last_seg = START_LAST_SEG(rx->gpc);
- memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len);
- XACT_SEG_RECV(0);
-
- if (!link.rx.seg) {
- prov_msg_recv();
- }
-}
-
-static const struct {
- void (*func)(struct prov_rx *rx, struct os_mbuf *buf);
- bool require_link;
- u8_t min_len;
-} gen_prov[] = {
- { gen_prov_start, true, 3 },
- { gen_prov_ack, true, 0 },
- { gen_prov_cont, true, 0 },
- { gen_prov_ctl, false, 0 },
-};
-
-static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf)
-{
- if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) {
- BT_ERR("Too short GPC message type %u", GPCF(rx->gpc));
- return;
- }
-
- if (!atomic_test_bit(link.flags, LINK_ACTIVE) &&
- gen_prov[GPCF(rx->gpc)].require_link) {
- BT_DBG("Ignoring message that requires active link");
- return;
- }
-
- BT_DBG("prov_action: %d", GPCF(rx->gpc));
- gen_prov[GPCF(rx->gpc)].func(rx, buf);
-}
-
-void bt_mesh_pb_adv_recv(struct os_mbuf *buf)
-{
- struct prov_rx rx;
-
- if (!bt_prov_active() && bt_mesh_is_provisioned()) {
- BT_DBG("Ignoring provisioning PDU - already provisioned");
- return;
- }
-
- if (buf->om_len < 6) {
- BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
- return;
- }
-
- rx.link_id = net_buf_simple_pull_be32(buf);
- rx.xact_id = net_buf_simple_pull_u8(buf);
- rx.gpc = net_buf_simple_pull_u8(buf);
-
- BT_DBG("link_id 0x%08x xact_id %u", (unsigned) rx.link_id, rx.xact_id);
-
- if (atomic_test_bit(link.flags, LINK_ACTIVE) && link.id != rx.link_id) {
- BT_DBG("Ignoring mesh beacon for unknown link");
- return;
- }
-
- gen_prov_recv(&rx, buf);
-}
-
-int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration)
-{
- BT_DBG("uuid %s", bt_hex(uuid, 16));
-
- if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
- return -EBUSY;
- }
-
- atomic_set_bit(link.flags, PROVISIONER);
-
- bt_rand(&link.id, sizeof(link.id));
- link.tx.id = 0x7F;
- link.provisioner->addr = addr;
- link.provisioner->net_idx = net_idx;
- link.provisioner->attention_duration = attention_duration;
-
- net_buf_simple_init(link.rx.buf, 0);
-
- bearer_ctl_send(LINK_OPEN, uuid, 16);
-
- return 0;
-}
-
-#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */
-
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf)
-{
- u8_t type;
-
- BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
-
- if (link.conn_handle != conn_handle) {
- BT_WARN("Data for unexpected connection");
- return -ENOTCONN;
- }
-
- if (buf->om_len < 1) {
- BT_WARN("Too short provisioning packet (len %u)", buf->om_len);
- return -EINVAL;
- }
-
- type = net_buf_simple_pull_u8(buf);
- if (type != PROV_FAILED && type != link.expect) {
- BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect);
- prov_send_fail_msg(PROV_ERR_UNEXP_PDU);
- return -EINVAL;
- }
-
- if (type >= ARRAY_SIZE(prov_handlers)) {
- BT_ERR("Unknown provisioning PDU type 0x%02x", type);
- return -EINVAL;
- }
-
- if (prov_handlers[type].len != buf->om_len) {
- BT_ERR("Invalid length %u for type 0x%02x", buf->om_len, type);
- return -EINVAL;
- }
-
- prov_handlers[type].func(buf->om_data);
-
- return 0;
-}
-
-int bt_mesh_pb_gatt_open(uint16_t conn_handle)
-{
- BT_DBG("conn_handle %d", conn_handle);
-
- if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) {
- BT_ERR("Link already opened?");
- return -EBUSY;
- }
-
- link.conn_handle = conn_handle;
- link.expect = PROV_INVITE;
-
- if (prov->link_open) {
- prov->link_open(BT_MESH_PROV_GATT);
- }
-
- return 0;
-}
-
-int bt_mesh_pb_gatt_close(uint16_t conn_handle)
-{
- BT_DBG("conn_handle %d", conn_handle);
-
- if (link.conn_handle != conn_handle) {
- BT_ERR("Not connected");
- return -ENOTCONN;
- }
-
- if (prov->link_close) {
- prov->link_close(BT_MESH_PROV_GATT);
- }
-
- return reset_state();
-}
-#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */
-
const struct bt_mesh_prov *bt_mesh_prov_get(void)
{
- return prov;
+ return bt_mesh_prov;
}
-bool bt_prov_active(void)
+bool bt_mesh_prov_active(void)
{
- return atomic_test_bit(link.flags, LINK_ACTIVE);
+ return atomic_test_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
}
-static void protocol_timeout(struct ble_npl_event *work)
+static void prov_recv(const struct prov_bearer *bearer, void *cb_data,
+ struct os_mbuf *buf)
{
- BT_DBG("Protocol timeout");
+ 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,
+ };
-#if MYNEWT_VAL(BLE_MESH_PB_GATT)
- if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) {
- bt_mesh_pb_gatt_close(link.conn_handle);
+ uint8_t type = buf->om_data[0];
+ BT_DBG("type 0x%02x len %u", type, buf->om_len);
+
+ 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);
return;
}
-#endif
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- u8_t reason = CLOSE_REASON_TIMEOUT;
+ if ((type != PROV_FAILED && type != bt_mesh_prov_link.expect) ||
+ !bt_mesh_prov_link.role->op[type]) {
+ BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, bt_mesh_prov_link.expect);
+ bt_mesh_prov_link.role->error(PROV_ERR_UNEXP_PDU);
+ return;
+ }
- link.rx.seg = 0U;
- bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason));
+ if (1 + op_len[type] != buf->om_len) {
+ BT_ERR("Invalid length %u for type 0x%02x", buf->om_len, type);
+ bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT);
+ return;
+ }
- reset_state();
-#endif
+ bt_mesh_prov_link.role->op[type](&buf->om_data[1]);
+}
+
+static void prov_link_opened(const struct prov_bearer *bearer, void *cb_data)
+{
+ atomic_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
+
+ BT_ERR("bt_mesh_prov->link_open");
+ if (bt_mesh_prov->link_open) {
+ bt_mesh_prov->link_open(bearer->type);
+ }
+
+ BT_ERR("bt_mesh_prov_link.bearer");
+ bt_mesh_prov_link.bearer = bearer;
+
+ BT_ERR("bt_mesh_prov_link.role->link_opened");
+ BT_ERR("%p", bt_mesh_prov_link.role);
+ BT_ERR("%p", bt_mesh_prov_link.role->link_opened);
+ if (bt_mesh_prov_link.role->link_opened) {
+ bt_mesh_prov_link.role->link_opened();
+ }
+ BT_ERR("done");
+}
+
+static void prov_link_closed(const struct prov_bearer *bearer, void *cb_data,
+ enum prov_bearer_link_status reason)
+{
+ if (bt_mesh_prov_link.role->link_closed) {
+ bt_mesh_prov_link.role->link_closed();
+ }
+
+ if (bt_mesh_prov->link_close) {
+ bt_mesh_prov->link_close(bearer->type);
+ }
+}
+
+static void prov_bearer_error(const struct prov_bearer *bearer, void *cb_data,
+ uint8_t err)
+{
+ if (bt_mesh_prov_link.role->error) {
+ bt_mesh_prov_link.role->error(err);
+ }
+}
+
+static const struct prov_bearer_cb prov_bearer_cb = {
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_bearer_error,
+ .recv = prov_recv,
+};
+
+const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void)
+{
+ return &prov_bearer_cb;
+}
+
+void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr)
+{
+ if (bt_mesh_prov->complete) {
+ bt_mesh_prov->complete(net_idx, addr);
+ }
+}
+
+void bt_mesh_prov_reset(void)
+{
+ BT_DBG("bt_mesh_prov_reset");
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+ pb_adv_reset();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+ pb_gatt_reset();
+ }
+
+ bt_mesh_prov_reset_state(NULL);
+
+ if (bt_mesh_prov->reset) {
+ bt_mesh_prov->reset();
+ }
}
int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
@@ -1963,49 +364,16 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
return -EINVAL;
}
- k_delayed_work_init(&link.prot_timer, protocol_timeout);
+ bt_mesh_prov = prov_info;
- prov = prov_info;
-
-#if MYNEWT_VAL(BLE_MESH_PB_ADV)
- k_delayed_work_init(&link.tx.retransmit, prov_retransmit);
-#endif
-
- return reset_state();
-}
-
-void bt_mesh_prov_reset_link(void)
-{
-#if (MYNEWT_VAL(BLE_MESH_PB_ADV))
-#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
- link.rx.buf = bt_mesh_proxy_get_buf();
-#else
- net_buf_simple_init(rx_buf, 0);
- link.rx.buf = rx_buf;
-#endif
-#endif
-}
-
-void bt_mesh_prov_complete(u16_t net_idx, u16_t addr)
-{
- if (prov->complete) {
- prov->complete(net_idx, addr);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) {
+ pb_adv_init();
}
-}
-
-void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
-{
- if (prov->node_added) {
- prov->node_added(net_idx, addr, num_elem);
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) {
+ pb_gatt_init();
}
+
+ return bt_mesh_prov_reset_state(NULL);
}
-void bt_mesh_prov_reset(void)
-{
- if (prov->reset) {
- prov->reset();
- }
-}
-
-#endif /* MYNEWT_VAL(BLE_MESH_PROV) */
-#endif
+#endif /* MYNEWT_VAL(BLE_MESH) */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h
index c6866c9e2..d68376000 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov.h
@@ -9,16 +9,131 @@
#ifndef __PROV_H__
#define __PROV_H__
+#include "prov_bearer.h"
#include "nimble/porting/nimble/include/os/os_mbuf.h"
#include "../include/mesh/mesh.h"
#include "nimble/nimble/host/src/ble_hs_conn_priv.h"
-int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr,
- u8_t attention_duration);
+#define PROV_ERR_NONE 0x00
+#define PROV_ERR_NVAL_PDU 0x01
+#define PROV_ERR_NVAL_FMT 0x02
+#define PROV_ERR_UNEXP_PDU 0x03
+#define PROV_ERR_CFM_FAILED 0x04
+#define PROV_ERR_RESOURCES 0x05
+#define PROV_ERR_DECRYPT 0x06
+#define PROV_ERR_UNEXP_ERR 0x07
+#define PROV_ERR_ADDR 0x08
-void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
+#define AUTH_METHOD_NO_OOB 0x00
+#define AUTH_METHOD_STATIC 0x01
+#define AUTH_METHOD_OUTPUT 0x02
+#define AUTH_METHOD_INPUT 0x03
-bool bt_prov_active(void);
+#define OUTPUT_OOB_BLINK 0x00
+#define OUTPUT_OOB_BEEP 0x01
+#define OUTPUT_OOB_VIBRATE 0x02
+#define OUTPUT_OOB_NUMBER 0x03
+#define OUTPUT_OOB_STRING 0x04
+
+#define INPUT_OOB_PUSH 0x00
+#define INPUT_OOB_TWIST 0x01
+#define INPUT_OOB_NUMBER 0x02
+#define INPUT_OOB_STRING 0x03
+
+#define PUB_KEY_NO_OOB 0x00
+#define PUB_KEY_OOB 0x01
+
+#define PROV_INVITE 0x00
+#define PROV_CAPABILITIES 0x01
+#define PROV_START 0x02
+#define PROV_PUB_KEY 0x03
+#define PROV_INPUT_COMPLETE 0x04
+#define PROV_CONFIRM 0x05
+#define PROV_RANDOM 0x06
+#define PROV_DATA 0x07
+#define PROV_COMPLETE 0x08
+#define PROV_FAILED 0x09
+
+#define PROV_NO_PDU 0xff
+
+#define PROV_ALG_P256 0x00
+
+#define PROV_BUF(len) \
+ NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + len)
+
+enum {
+ WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
+ LINK_ACTIVE, /* Link has been opened */
+ WAIT_NUMBER, /* Waiting for number input from user */
+ WAIT_STRING, /* Waiting for string input from user */
+ NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */
+ PROVISIONER, /* The link was opened as provisioner */
+ OOB_PUB_KEY, /* OOB Public key used */
+ PUB_KEY_SENT, /* Public key has been sent */
+ REMOTE_PUB_KEY, /* Remote key has been received */
+ INPUT_COMPLETE, /* Device input completed */
+ WAIT_CONFIRM, /* Wait for send confirm */
+ WAIT_AUTH, /* Wait for auth response */
+ OOB_STATIC_KEY, /* OOB Static Authentication */
+
+ NUM_FLAGS,
+};
+
+/** Provisioning role */
+struct bt_mesh_prov_role {
+ void (*link_opened)(void);
+
+ void (*link_closed)(void);
+
+ void (*error)(uint8_t reason);
+
+ void (*input_complete)(void);
+
+ void (*op[10])(const uint8_t *data);
+};
+
+struct bt_mesh_prov_link {
+ ATOMIC_DEFINE(flags, NUM_FLAGS);
+
+ const struct prov_bearer *bearer;
+ const struct bt_mesh_prov_role *role;
+
+ uint8_t oob_method; /* Authen method */
+ uint8_t oob_action; /* Authen action */
+ uint8_t oob_size; /* Authen size */
+ uint8_t auth[16]; /* Authen value */
+
+ uint8_t dhkey[32]; /* Calculated DHKey */
+ uint8_t expect; /* Next expected PDU */
+ uint8_t conf[16]; /* Remote Confirmation */
+ uint8_t rand[16]; /* Local Random */
+
+ uint8_t conf_salt[16]; /* ConfirmationSalt */
+ uint8_t conf_key[16]; /* ConfirmationKey */
+ uint8_t conf_inputs[145]; /* ConfirmationInputs */
+ uint8_t prov_salt[16]; /* Provisioning Salt */
+};
+
+extern struct bt_mesh_prov_link bt_mesh_prov_link;
+extern const struct bt_mesh_prov *bt_mesh_prov;
+
+static inline int bt_mesh_prov_send(struct os_mbuf *buf,
+ prov_bearer_send_complete_t cb)
+{
+ return bt_mesh_prov_link.bearer->send(buf, cb, NULL);
+}
+
+static inline void bt_mesh_prov_buf_init(struct os_mbuf *buf, uint8_t type)
+{
+ net_buf_reserve(buf, PROV_BEARER_BUF_HEADROOM);
+ net_buf_simple_add_u8(buf, type);
+}
+
+int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64]));
+
+bool bt_mesh_prov_active(void);
+
+int bt_mesh_prov_auth(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);
@@ -26,12 +141,14 @@ int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf);
const struct bt_mesh_prov *bt_mesh_prov_get(void);
-int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
-
void bt_mesh_prov_reset_link(void);
-void bt_mesh_prov_complete(u16_t net_idx, u16_t addr);
-void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem);
+void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr);
void bt_mesh_prov_reset(void);
+const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void);
+
+void bt_mesh_pb_adv_recv(struct os_mbuf *buf);
+
+int bt_mesh_prov_init(const struct bt_mesh_prov *prov);
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov_bearer.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov_bearer.h
new file mode 100644
index 000000000..3e5268314
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov_bearer.h
@@ -0,0 +1,116 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define PROTOCOL_TIMEOUT K_SECONDS(60)
+
+/** @def PROV_BEARER_BUF_HEADROOM
+ *
+ * @brief Required headroom for the bearer packet buffers.
+ */
+#if MYNEWT_VAL(BLE_MESH_PB_GATT)
+#define PROV_BEARER_BUF_HEADROOM 5
+#else
+#define PROV_BEARER_BUF_HEADROOM 0
+#endif
+
+enum prov_bearer_link_status {
+ PROV_BEARER_LINK_STATUS_SUCCESS,
+ PROV_BEARER_LINK_STATUS_TIMEOUT,
+ PROV_BEARER_LINK_STATUS_FAIL,
+};
+
+struct prov_bearer;
+
+/** Callbacks from bearer to host */
+struct prov_bearer_cb {
+
+ void (*link_opened)(const struct prov_bearer *bearer, void *cb_data);
+
+ void (*link_closed)(const struct prov_bearer *bearer, void *cb_data,
+ enum prov_bearer_link_status reason);
+
+ void (*error)(const struct prov_bearer *bearer, void *cb_data,
+ uint8_t err);
+
+ void (*recv)(const struct prov_bearer *bearer, void *cb_data,
+ struct os_mbuf *buf);
+};
+
+typedef void (*prov_bearer_send_complete_t)(int err, void *cb_data);
+
+/** Provisioning bearer API */
+struct prov_bearer {
+ /** Provisioning bearer type. */
+ bt_mesh_prov_bearer_t type;
+
+ /** @brief Enable link establishment as a provisionee.
+ *
+ * Prompts the bearer to make itself visible to provisioners, and
+ * start accepting link open messages.
+ *
+ * @param cb Bearer event callbacks used for the duration of the link.
+ * @param cb_data Context parameter to pass to the bearer callbacks.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*link_accept)(const struct prov_bearer_cb *cb, void *cb_data);
+
+ /** @brief Send a packet on an established link.
+ *
+ * @param buf Payload buffer. Requires @ref
+ * PROV_BEARER_BUF_HEADROOM bytes of headroom.
+ * @param cb Callback to call when sending is complete.
+ * @param cb_data Callback data.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*send)(struct os_mbuf *buf, prov_bearer_send_complete_t cb,
+ void *cb_data);
+
+ /** @brief Clear any ongoing transmissions, if possible.
+ *
+ * Bearers that don't support tx clearing must implement this callback
+ * and leave it empty.
+ */
+ void (*clear_tx)(void);
+
+ /* Only available in provisioners: */
+
+ /** @brief Open a new link as a provisioner.
+ *
+ * Only available in provisioners. Bearers that don't support the
+ * provisioner role should leave this as NULL.
+ *
+ * @param uuid UUID of the node to establish a link to.
+ * @param timeout Protocol timeout.
+ * @param cb Bearer event callbacks used for the duration of the link.
+ * @param cb_data Context parameter to pass to the bearer callbacks.
+ *
+ * @return Zero on success, or (negative) error code otherwise.
+ */
+ int (*link_open)(const uint8_t uuid[16], int32_t timeout,
+ const struct prov_bearer_cb *cb, void *cb_data);
+
+ /** @brief Close the current link.
+ *
+ * Only available in provisioners. Bearers that don't support the
+ * provisioner role should leave this as NULL.
+ *
+ * @param status Link status for the link close message.
+ */
+ void (*link_close)(enum prov_bearer_link_status status);
+};
+
+extern const struct prov_bearer pb_adv;
+extern const struct prov_bearer pb_gatt;
+
+void pb_adv_init(void);
+void pb_gatt_init(void);
+
+void pb_adv_reset(void);
+void pb_gatt_reset(void);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov_device.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov_device.c
new file mode 100644
index 000000000..95d01c415
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/prov_device.c
@@ -0,0 +1,573 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_MESH)
+
+#include "crypto.h"
+#include "adv.h"
+#include "../include/mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "prov.h"
+#include "settings.h"
+
+static void send_pub_key(void);
+static void pub_key_ready(const uint8_t *pkey);
+
+static int reset_state(void)
+{
+ return bt_mesh_prov_reset_state(pub_key_ready);
+}
+
+static void prov_send_fail_msg(uint8_t err)
+{
+ struct os_mbuf *buf = PROV_BUF(2);
+
+ BT_DBG("%u", err);
+
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ bt_mesh_prov_buf_init(buf, PROV_FAILED);
+ net_buf_simple_add_u8(buf, err);
+
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send Provisioning Failed message");
+ }
+}
+
+static void prov_fail(uint8_t reason)
+{
+ /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
+ * provisioner just closes the link when something fails, while the
+ * provisionee sends the fail message, and waits for the provisioner to
+ * close the link.
+ */
+ prov_send_fail_msg(reason);
+}
+
+static void prov_invite(const uint8_t *data)
+{
+ struct os_mbuf *buf = PROV_BUF(12);
+
+ BT_DBG("Attention Duration: %u seconds", data[0]);
+
+ if (data[0]) {
+ bt_mesh_attention(NULL, data[0]);
+ }
+
+ bt_mesh_prov_link.conf_inputs[0] = data[0];
+
+ bt_mesh_prov_buf_init(buf, PROV_CAPABILITIES);
+
+ /* Number of Elements supported */
+ net_buf_simple_add_u8(buf, bt_mesh_elem_count());
+
+ /* 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);
+
+ /* Static OOB Type */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->static_val ? BIT(0) : 0x00);
+
+ /* Output OOB Size */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->output_size);
+
+ /* Output OOB Action */
+ net_buf_simple_add_be16(buf, bt_mesh_prov->output_actions);
+
+ /* Input OOB Size */
+ net_buf_simple_add_u8(buf, bt_mesh_prov->input_size);
+
+ /* 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);
+
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send capabilities");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_START;
+}
+
+static void prov_start(const uint8_t *data)
+{
+ BT_DBG("Algorithm: 0x%02x", data[0]);
+ BT_DBG("Public Key: 0x%02x", data[1]);
+ BT_DBG("Auth Method: 0x%02x", data[2]);
+ BT_DBG("Auth Action: 0x%02x", data[3]);
+ BT_DBG("Auth Size: 0x%02x", data[4]);
+
+ if (data[0] != PROV_ALG_P256) {
+ BT_ERR("Unknown algorithm 0x%02x", data[0]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ if (data[1] != PUB_KEY_NO_OOB) {
+ BT_ERR("Invalid public key type: 0x%02x", data[1]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+
+ memcpy(&bt_mesh_prov_link.conf_inputs[12], data, 5);
+
+ bt_mesh_prov_link.expect = PROV_PUB_KEY;
+
+ if (bt_mesh_prov_auth(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]);
+ prov_fail(PROV_ERR_NVAL_FMT);
+ }
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY)) {
+ memcpy(bt_mesh_prov_link.auth + 16 - bt_mesh_prov->static_val_len,
+ bt_mesh_prov->static_val, bt_mesh_prov->static_val_len);
+ (void)memset(bt_mesh_prov_link.auth, 0,
+ sizeof(bt_mesh_prov_link.auth) - bt_mesh_prov->static_val_len);
+ }
+}
+
+static void send_confirm(void)
+{
+ struct os_mbuf *cfm = PROV_BUF(17);
+
+ 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));
+
+ if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs,
+ bt_mesh_prov_link.conf_salt)) {
+ BT_ERR("Unable to generate confirmation salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16));
+
+ if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey, bt_mesh_prov_link.conf_salt,
+ bt_mesh_prov_link.conf_key)) {
+ BT_ERR("Unable to generate confirmation key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16));
+
+ if (bt_rand(bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Unable to generate random number");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16));
+
+ bt_mesh_prov_buf_init(cfm, PROV_CONFIRM);
+
+ 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_ERR("Unable to generate confirmation value");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (bt_mesh_prov_send(cfm, NULL)) {
+ BT_ERR("Failed to send Provisioning Confirm");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_RANDOM;
+
+}
+
+static void send_input_complete(void)
+{
+ struct os_mbuf *buf = PROV_BUF(1);
+
+ bt_mesh_prov_buf_init(buf, PROV_INPUT_COMPLETE);
+ if (bt_mesh_prov_send(buf, NULL)) {
+ BT_ERR("Failed to send Provisioning Input Complete");
+ }
+ bt_mesh_prov_link.expect = PROV_CONFIRM;
+}
+
+static void public_key_sent(int err, void *cb_data)
+{
+ atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT);
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE)) {
+ send_input_complete();
+ return;
+ }
+}
+
+static void send_pub_key(void)
+{
+ struct os_mbuf *buf = PROV_BUF(65);
+ const uint8_t *key;
+
+ key = bt_pub_key_get();
+ if (!key) {
+ BT_ERR("No public key available");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Local Public Key: %s", bt_hex(key, 64));
+
+ 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);
+
+ /* PublicKeyRemote */
+ memcpy(&bt_mesh_prov_link.conf_inputs[81], &buf->om_data[1], 64);
+
+ if (bt_mesh_prov_send(buf, public_key_sent)) {
+ BT_ERR("Failed to send Public Key");
+ 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;
+ }
+}
+
+static void prov_dh_key_cb(const uint8_t dhkey[32])
+{
+ BT_DBG("%p", dhkey);
+
+ if (!dhkey) {
+ BT_ERR("DHKey generation failed");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ 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();
+}
+
+static void prov_dh_key_gen(void)
+{
+ uint8_t remote_pk_le[64], *remote_pk;
+
+ remote_pk = &bt_mesh_prov_link.conf_inputs[17];
+
+ /* Copy remote key in little-endian for bt_dh_key_gen().
+ * 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);
+
+ if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
+ BT_ERR("Failed to generate DHKey");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ }
+}
+
+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);
+
+ 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);
+ BT_WARN("Waiting for local public key");
+ return;
+ }
+
+ prov_dh_key_gen();
+}
+
+static void pub_key_ready(const uint8_t *pkey)
+{
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+
+ BT_DBG("Local public key ready");
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
+ prov_dh_key_gen();
+ }
+}
+
+static void notify_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
+ NOTIFY_INPUT_COMPLETE) &&
+ bt_mesh_prov->input_complete) {
+ bt_mesh_prov->input_complete();
+ }
+}
+
+static void send_random(void)
+{
+ struct os_mbuf *rnd = PROV_BUF(17);
+
+ bt_mesh_prov_buf_init(rnd, PROV_RANDOM);
+ net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16);
+
+ if (bt_mesh_prov_send(rnd, NULL)) {
+ BT_ERR("Failed to send Provisioning Random");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_DATA;
+}
+
+static void prov_random(const uint8_t *data)
+{
+ uint8_t conf_verify[16];
+
+ BT_DBG("Remote Random: %s", bt_hex(data, 16));
+ if (!memcmp(data, bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Random value is identical to ours, rejecting.");
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, data,
+ bt_mesh_prov_link.auth, conf_verify)) {
+ BT_ERR("Unable to calculate confirmation verification");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) {
+ BT_ERR("Invalid confirmation value");
+ BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16));
+ BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt, data,
+ bt_mesh_prov_link.rand, bt_mesh_prov_link.prov_salt)) {
+ BT_ERR("Failed to generate provisioning salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16));
+
+ send_random();
+}
+
+static void prov_confirm(const uint8_t *data)
+{
+ BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
+
+ memcpy(bt_mesh_prov_link.conf, data, 16);
+
+ notify_input_complete();
+
+ send_confirm();
+}
+
+static inline bool is_pb_gatt(void)
+{
+ return bt_mesh_prov_link.bearer &&
+ bt_mesh_prov_link.bearer->type == BT_MESH_PROV_GATT;
+}
+
+static void prov_data(const uint8_t *data)
+{
+ struct os_mbuf *msg = PROV_BUF(1);
+ uint8_t session_key[16];
+ uint8_t nonce[13];
+ uint8_t dev_key[16];
+ uint8_t pdu[25];
+ uint8_t flags;
+ uint32_t iv_index;
+ uint16_t addr;
+ uint16_t net_idx;
+ int err;
+ bool identity_enable;
+
+ BT_DBG("");
+
+ err = bt_mesh_session_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, session_key);
+ if (err) {
+ BT_ERR("Unable to generate session key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
+
+ err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, nonce);
+ if (err) {
+ BT_ERR("Unable to generate session nonce");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Nonce: %s", bt_hex(nonce, 13));
+
+ err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu);
+ if (err) {
+ BT_ERR("Unable to decrypt provisioning data");
+ prov_fail(PROV_ERR_DECRYPT);
+ return;
+ }
+
+ err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, dev_key);
+ if (err) {
+ BT_ERR("Unable to generate device key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("DevKey: %s", bt_hex(dev_key, 16));
+
+ net_idx = sys_get_be16(&pdu[16]);
+ flags = pdu[18];
+ iv_index = sys_get_be32(&pdu[19]);
+ addr = sys_get_be16(&pdu[23]);
+
+ BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x",
+ net_idx, iv_index, addr);
+
+ bt_mesh_prov_buf_init(msg, PROV_COMPLETE);
+ if (bt_mesh_prov_send(msg, NULL)) {
+ BT_ERR("Failed to send Provisioning Complete");
+ return;
+ }
+
+ /* Ignore any further PDUs on this link */
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ /* Store info, since bt_mesh_provision() will end up clearing it */
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ identity_enable = is_pb_gatt();
+ } else {
+ identity_enable = false;
+ }
+
+ err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key);
+ if (err) {
+ BT_ERR("Failed to provision (err %d)", err);
+ return;
+ }
+
+ /* After PB-GATT provisioning we should start advertising
+ * using Node Identity.
+ */
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) {
+ bt_mesh_proxy_identity_enable();
+ }
+}
+
+static void local_input_complete(void)
+{
+ if (atomic_test_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT)) {
+ send_input_complete();
+ } else {
+ atomic_set_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE);
+ }
+}
+
+static void prov_link_closed(void)
+{
+ reset_state();
+}
+
+static void prov_link_opened(void)
+{
+ bt_mesh_prov_link.expect = PROV_INVITE;
+}
+
+static const struct bt_mesh_prov_role role_device = {
+ .input_complete = local_input_complete,
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_fail,
+ .op = {
+ [PROV_INVITE] = prov_invite,
+ [PROV_START] = prov_start,
+ [PROV_PUB_KEY] = prov_pub_key,
+ [PROV_CONFIRM] = prov_confirm,
+ [PROV_RANDOM] = prov_random,
+ [PROV_DATA] = prov_data,
+ },
+};
+
+int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)
+{
+ BT_DBG("bt_mesh_prov_enable");
+
+ if (bt_mesh_is_provisioned()) {
+ return -EALREADY;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
+ (bearers & BT_MESH_PROV_ADV)) {
+ pb_adv.link_accept(bt_mesh_prov_bearer_cb_get(), NULL);
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+ (bearers & BT_MESH_PROV_GATT)) {
+ pb_gatt.link_accept(bt_mesh_prov_bearer_cb_get(), NULL);
+ }
+
+ BT_DBG("bt_mesh_prov_link.role = &role_device");
+ bt_mesh_prov_link.role = &role_device;
+
+ return 0;
+}
+
+int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)
+{
+ if (bt_mesh_is_provisioned()) {
+ return -EALREADY;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) &&
+ (bearers & BT_MESH_PROV_ADV)) {
+ bt_mesh_beacon_disable();
+ bt_mesh_scan_disable();
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) &&
+ (bearers & BT_MESH_PROV_GATT)) {
+ bt_mesh_proxy_prov_disable(true);
+ }
+
+ return 0;
+}
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/provisioner.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/provisioner.c
new file mode 100644
index 000000000..8a00087af
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/provisioner.c
@@ -0,0 +1,750 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#define MESH_LOG_MODULE BLE_MESH_PROV_LOG
+
+#if MYNEWT_VAL(BLE_MESH)
+
+#include "crypto.h"
+#include "adv.h"
+#include "../include/mesh/mesh.h"
+#include "net.h"
+#include "rpl.h"
+#include "beacon.h"
+#include "access.h"
+#include "foundation.h"
+#include "proxy.h"
+#include "prov.h"
+#include "settings.h"
+
+static struct {
+ struct bt_mesh_cdb_node *node;
+ uint16_t addr;
+ uint16_t net_idx;
+ uint8_t attention_duration;
+ uint8_t uuid[16];
+} prov_device;
+
+static void send_pub_key(void);
+static void prov_dh_key_gen(void);
+static void pub_key_ready(const uint8_t *pkey);
+
+static int reset_state(void)
+{
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ if (prov_device.node != NULL) {
+ bt_mesh_cdb_node_del(prov_device.node, false);
+ }
+#endif
+ return bt_mesh_prov_reset_state(pub_key_ready);
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+ BT_DBG("%u", status);
+ bt_mesh_prov_link.expect = PROV_NO_PDU;
+
+ bt_mesh_prov_link.bearer->link_close(status);
+}
+
+static void prov_fail(uint8_t reason)
+{
+ /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the
+ * provisioner just closes the link when something fails, while the
+ * provisionee sends the fail message, and waits for the provisioner to
+ * close the link.
+ */
+ prov_link_close(PROV_BEARER_LINK_STATUS_FAIL);
+}
+
+static void send_invite(void)
+{
+ struct os_mbuf *inv = PROV_BUF(2);
+
+ 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;
+
+ if (bt_mesh_prov_send(inv, NULL)) {
+ BT_ERR("Failed to send invite");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_CAPABILITIES;
+}
+
+static void start_sent(int err, void *cb_data)
+{
+ if (!bt_pub_key_get()) {
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
+ BT_WARN("Waiting for local public key");
+ } else {
+ send_pub_key();
+ }
+}
+
+static void send_start(void)
+{
+ BT_DBG("");
+ uint8_t method, action;
+ struct os_mbuf *start = PROV_BUF(6);
+
+ const uint8_t *data = &bt_mesh_prov_link.conf_inputs[1 + 3];
+
+ 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) {
+ net_buf_simple_add_u8(start, PUB_KEY_OOB);
+ atomic_set_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY);
+ } else {
+ 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);
+
+ 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);
+
+ if (bt_mesh_prov_auth(method, 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);
+ return;
+ }
+
+ if (bt_mesh_prov_send(start, start_sent)) {
+ BT_ERR("Failed to send Provisioning Start");
+ return;
+ }
+}
+
+static bool prov_check_method(struct bt_mesh_dev_capabilities *caps)
+{
+ if (bt_mesh_prov_link.oob_method == AUTH_METHOD_STATIC) {
+ if (!caps->static_oob) {
+ BT_WARN("Device not support OOB static authentication provisioning");
+ return false;
+ }
+ } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) {
+ if (bt_mesh_prov_link.oob_size > caps->input_size) {
+ BT_WARN("The required input length (0x%02x) "
+ "exceeds the device capacity (0x%02x)",
+ bt_mesh_prov_link.oob_size, caps->input_size);
+ return false;
+ }
+
+ if (!(BIT(bt_mesh_prov_link.oob_action) & caps->input_actions)) {
+ BT_WARN("The required input action (0x%02x) "
+ "not supported by the device (0x%02x)",
+ bt_mesh_prov_link.oob_action, caps->input_actions);
+ return false;
+ }
+
+ if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) {
+ if (!bt_mesh_prov->output_string) {
+ BT_WARN("Not support output string");
+ return false;
+ }
+ } else {
+ if (!bt_mesh_prov->output_number) {
+ BT_WARN("Not support output number");
+ return false;
+ }
+ }
+ } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) {
+ if (bt_mesh_prov_link.oob_size > caps->output_size) {
+ BT_WARN("The required output length (0x%02x) "
+ "exceeds the device capacity (0x%02x)",
+ bt_mesh_prov_link.oob_size, caps->output_size);
+ return false;
+ }
+
+ if (!(BIT(bt_mesh_prov_link.oob_action) & caps->output_actions)) {
+ BT_WARN("The required output action (0x%02x) "
+ "not supported by the device (0x%02x)",
+ bt_mesh_prov_link.oob_action, caps->output_actions);
+ return false;
+ }
+
+ if (!bt_mesh_prov->input) {
+ BT_WARN("Not support input");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void prov_capabilities(const uint8_t *data)
+{
+ struct bt_mesh_dev_capabilities caps;
+
+ caps.elem_count = data[0];
+ BT_DBG("Elements: %u", caps.elem_count);
+
+ caps.algorithms = sys_get_be16(&data[1]);
+ BT_DBG("Algorithms: %u", caps.algorithms);
+
+ caps.pub_key_type = data[3];
+ caps.static_oob = data[4];
+ caps.output_size = data[5];
+ BT_DBG("Public Key Type: 0x%02x", caps.pub_key_type);
+ 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.input_size = data[8];
+ caps.input_actions = (bt_mesh_input_action_t)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);
+
+ if (data[0] == 0) {
+ BT_ERR("Invalid number of elements");
+ prov_fail(PROV_ERR_NVAL_FMT);
+ return;
+ }
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ prov_device.node =
+ bt_mesh_cdb_node_alloc(prov_device.uuid,
+ prov_device.addr, data[0],
+ prov_device.net_idx);
+ if (prov_device.node == NULL) {
+ BT_ERR("Failed allocating node 0x%04x", prov_device.addr);
+ prov_fail(PROV_ERR_RESOURCES);
+ return;
+ }
+#endif
+ memcpy(&bt_mesh_prov_link.conf_inputs[1], data, 11);
+
+ if (bt_mesh_prov->capabilities) {
+ bt_mesh_prov->capabilities(&caps);
+ }
+
+ if (!prov_check_method(&caps)) {
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ send_start();
+}
+
+static void send_confirm(void)
+{
+ struct os_mbuf *cfm = PROV_BUF(17);
+
+ 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));
+
+ if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs,
+ bt_mesh_prov_link.conf_salt)) {
+ BT_ERR("Unable to generate confirmation salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16));
+
+ if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.conf_salt, bt_mesh_prov_link.conf_key)) {
+ BT_ERR("Unable to generate confirmation key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16));
+
+ if (bt_rand(bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Unable to generate random number");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16));
+
+ bt_mesh_prov_buf_init(cfm, PROV_CONFIRM);
+
+ 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_ERR("Unable to generate confirmation value");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (bt_mesh_prov_send(cfm, NULL)) {
+ BT_ERR("Failed to send Provisioning Confirm");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_CONFIRM;
+}
+
+static void public_key_sent(int err, void *cb_data)
+{
+ atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT);
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY) &&
+ atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) {
+ prov_dh_key_gen();
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_PUB_KEY;
+}
+
+static void send_pub_key(void)
+{
+ struct os_mbuf *buf = PROV_BUF(65);
+ const uint8_t *key;
+
+ key = bt_pub_key_get();
+ if (!key) {
+ BT_ERR("No public key available");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Local Public Key: %s", bt_hex(key, 64));
+
+ 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);
+
+ /* PublicKeyProvisioner */
+ memcpy(&bt_mesh_prov_link.conf_inputs[17], &buf->om_databuf[1], 64);
+
+ if (bt_mesh_prov_send(buf, public_key_sent)) {
+ BT_ERR("Failed to send Public Key");
+ return;
+ }
+}
+
+static void prov_dh_key_cb(const uint8_t dhkey[32])
+{
+ BT_DBG("%p", dhkey);
+
+ if (!dhkey) {
+ BT_ERR("DHKey generation failed");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32);
+
+ BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32));
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING) ||
+ atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) ||
+ atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
+ atomic_set_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM);
+ return;
+ }
+
+ send_confirm();
+}
+
+static void prov_dh_key_gen(void)
+{
+ uint8_t remote_pk_le[64], *remote_pk;
+
+ remote_pk = &bt_mesh_prov_link.conf_inputs[81];
+
+ /* Copy remote key in little-endian for bt_dh_key_gen().
+ * 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);
+
+ if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
+ BT_ERR("Failed to generate DHKey");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ }
+
+ if (atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
+ bt_mesh_prov_link.expect = PROV_INPUT_COMPLETE;
+ }
+}
+
+static void prov_pub_key(const uint8_t *data)
+{
+ BT_DBG("Remote Public Key: %s", bt_hex(data, 64));
+
+ atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY);
+
+ /* PublicKeyDevice */
+ memcpy(&bt_mesh_prov_link.conf_inputs[81], data, 64);
+ bt_mesh_prov_link.bearer->clear_tx();
+
+ prov_dh_key_gen();
+}
+
+static void pub_key_ready(const uint8_t *pkey)
+{
+ if (!pkey) {
+ BT_WARN("Public key not available");
+ return;
+ }
+
+ BT_DBG("Local public key ready");
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
+ send_pub_key();
+ }
+}
+
+static void notify_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
+ NOTIFY_INPUT_COMPLETE) &&
+ bt_mesh_prov->input_complete) {
+ bt_mesh_prov->input_complete();
+ }
+}
+
+static void prov_input_complete(const uint8_t *data)
+{
+ BT_DBG("");
+
+ notify_input_complete();
+
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) {
+ send_confirm();
+ }
+}
+
+static void send_prov_data(void)
+{
+ struct os_mbuf *pdu = PROV_BUF(34);
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ struct bt_mesh_cdb_subnet *sub;
+#endif
+ uint8_t session_key[16];
+ uint8_t nonce[13];
+ int err;
+
+ err = bt_mesh_session_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, session_key);
+ if (err) {
+ BT_ERR("Unable to generate session key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("SessionKey: %s", bt_hex(session_key, 16));
+
+ err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, nonce);
+ if (err) {
+ BT_ERR("Unable to generate session nonce");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("Nonce: %s", bt_hex(nonce, 13));
+
+ err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey,
+ bt_mesh_prov_link.prov_salt, prov_device.node->dev_key);
+ if (err) {
+ BT_ERR("Unable to generate device key");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("DevKey: %s", bt_hex(prov_device.node->dev_key, 16));
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ sub = bt_mesh_cdb_subnet_get(prov_device.node->net_idx);
+ if (sub == NULL) {
+ BT_ERR("No subnet with net_idx %u",
+ prov_device.node->net_idx);
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+#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_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);
+#endif
+ net_buf_simple_add_be16(pdu, prov_device.node->addr);
+ net_buf_simple_add(pdu, 8); /* For MIC */
+
+ BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x",
+ prov_device.node->net_idx, bt_mesh.iv_index,
+ prov_device.node->addr);
+
+ err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1],
+ &pdu->om_data[1]);
+ if (err) {
+ BT_ERR("Unable to encrypt provisioning data");
+ prov_fail(PROV_ERR_DECRYPT);
+ return;
+ }
+
+ if (bt_mesh_prov_send(pdu, NULL)) {
+ BT_ERR("Failed to send Provisioning Data");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_COMPLETE;
+}
+
+static void prov_complete(const uint8_t *data)
+{
+ struct bt_mesh_cdb_node *node = prov_device.node;
+
+ BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x",
+ bt_hex(node->dev_key, 16), node->net_idx, node->num_elem,
+ node->addr);
+
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+#endif
+
+ prov_device.node = NULL;
+ prov_link_close(PROV_BEARER_LINK_STATUS_SUCCESS);
+
+ if (bt_mesh_prov->node_added) {
+ bt_mesh_prov->node_added(node->net_idx, node->uuid, node->addr,
+ node->num_elem);
+ }
+}
+
+static void send_random(void)
+{
+ struct os_mbuf *rnd = PROV_BUF(17);
+
+ bt_mesh_prov_buf_init(rnd, PROV_RANDOM);
+ net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16);
+
+ if (bt_mesh_prov_send(rnd, NULL)) {
+ BT_ERR("Failed to send Provisioning Random");
+ return;
+ }
+
+ bt_mesh_prov_link.expect = PROV_RANDOM;
+}
+
+static void prov_random(const uint8_t *data)
+{
+ uint8_t conf_verify[16];
+
+ BT_DBG("Remote Random: %s", bt_hex(data, 16));
+ if (!memcmp(data, bt_mesh_prov_link.rand, 16)) {
+ BT_ERR("Random value is identical to ours, rejecting.");
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key,
+ data, bt_mesh_prov_link.auth, conf_verify)) {
+ BT_ERR("Unable to calculate confirmation verification");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) {
+ BT_ERR("Invalid confirmation value");
+ BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16));
+ BT_DBG("Calculated: %s", bt_hex(conf_verify, 16));
+ prov_fail(PROV_ERR_CFM_FAILED);
+ return;
+ }
+
+ if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt,
+ bt_mesh_prov_link.rand, data, bt_mesh_prov_link.prov_salt)) {
+ BT_ERR("Failed to generate provisioning salt");
+ prov_fail(PROV_ERR_UNEXP_ERR);
+ return;
+ }
+
+ BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16));
+
+ send_prov_data();
+}
+
+static void prov_confirm(const uint8_t *data)
+{
+ BT_DBG("Remote Confirm: %s", bt_hex(data, 16));
+
+ memcpy(bt_mesh_prov_link.conf, data, 16);
+
+ send_random();
+}
+
+static void prov_failed(const uint8_t *data)
+{
+ BT_WARN("Error: 0x%02x", data[0]);
+ reset_state();
+}
+
+static void local_input_complete(void)
+{
+ if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) {
+ send_confirm();
+ }
+}
+
+static void prov_link_closed(void)
+{
+ reset_state();
+}
+
+static void prov_link_opened(void)
+{
+ send_invite();
+}
+
+static const struct bt_mesh_prov_role role_provisioner = {
+ .input_complete = local_input_complete,
+ .link_opened = prov_link_opened,
+ .link_closed = prov_link_closed,
+ .error = prov_fail,
+ .op = {
+ [PROV_CAPABILITIES] = prov_capabilities,
+ [PROV_PUB_KEY] = prov_pub_key,
+ [PROV_INPUT_COMPLETE] = prov_input_complete,
+ [PROV_CONFIRM] = prov_confirm,
+ [PROV_RANDOM] = prov_random,
+ [PROV_COMPLETE] = prov_complete,
+ [PROV_FAILED] = prov_failed,
+ },
+};
+
+static void prov_set_method(uint8_t method, uint8_t action, uint8_t size)
+{
+ bt_mesh_prov_link.oob_method = method;
+ bt_mesh_prov_link.oob_action = action;
+ bt_mesh_prov_link.oob_size = size;
+}
+
+int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size)
+{
+ if (!action || !size || size > 8) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_INPUT, find_msb_set(action) - 1, size);
+ return 0;
+}
+
+int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size)
+{
+ if (!action || !size || size > 8) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_OUTPUT, find_msb_set(action) - 1, size);
+ return 0;
+}
+
+int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size)
+{
+ if (!size || !static_val || size > 16) {
+ return -EINVAL;
+ }
+
+ prov_set_method(AUTH_METHOD_STATIC, 0, 0);
+
+ memcpy(bt_mesh_prov_link.auth + 16 - size, static_val, size);
+ if (size < 16) {
+ (void)memset(bt_mesh_prov_link.auth, 0,
+ sizeof(bt_mesh_prov_link.auth) - size);
+ }
+ return 0;
+}
+
+int bt_mesh_auth_method_set_none(void)
+{
+ prov_set_method(AUTH_METHOD_NO_OOB, 0, 0);
+ return 0;
+}
+
+int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64])
+{
+ if (public_key == NULL) {
+ return -EINVAL;
+ }
+
+ if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) {
+ return -EALREADY;
+ }
+
+ /* 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);
+
+ return 0;
+}
+
+#if defined(CONFIG_BT_MESH_PB_ADV)
+int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
+{
+ int err;
+
+ if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE)) {
+ return -EBUSY;
+ }
+
+ atomic_set_bit(bt_mesh_prov_link.flags, PROVISIONER);
+ memcpy(prov_device.uuid, uuid, 16);
+ prov_device.addr = addr;
+ prov_device.net_idx = net_idx;
+ prov_device.attention_duration = attention_duration;
+ bt_mesh_prov_link.bearer = &pb_adv;
+ bt_mesh_prov_link.role = &role_provisioner;
+
+ err = bt_mesh_prov_link.bearer->link_open(prov_device.uuid, PROTOCOL_TIMEOUT,
+ bt_mesh_prov_bearer_cb_get(), NULL);
+ if (err) {
+ atomic_clear_bit(bt_mesh_prov_link.flags, LINK_ACTIVE);
+ }
+
+ return err;
+}
+#endif
+#endif /* MYNEWT_VAL(BLE_MESH) */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/provisioner.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/provisioner.h
new file mode 100644
index 000000000..ccda47efe
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/provisioner.h
@@ -0,0 +1,10 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+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
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c
index 6801791f1..d8b679302 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.c
@@ -21,6 +21,7 @@
#include "mesh_priv.h"
#include "adv.h"
#include "net.h"
+#include "rpl.h"
#include "prov.h"
#include "beacon.h"
#include "foundation.h"
@@ -30,6 +31,9 @@
#define PDU_TYPE(data) (data[0] & BIT_MASK(6))
#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."
@@ -112,14 +116,14 @@ static bool prov_fast_adv;
static struct bt_mesh_proxy_client {
uint16_t conn_handle;
- u16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
+ uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)];
enum __packed {
NONE,
WHITELIST,
BLACKLIST,
PROV,
} filter_type;
- u8_t msg_type;
+ uint8_t msg_type;
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
struct ble_npl_callout send_beacons;
#endif
@@ -129,6 +133,9 @@ 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,
@@ -197,15 +204,15 @@ static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle)
#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY))
/* Next subnet in queue to be advertised */
-static int next_idx;
+static struct bt_mesh_subnet *beacon_sub;
-static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
+static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg);
static int filter_set(struct bt_mesh_proxy_client *client,
struct os_mbuf *buf)
{
- u8_t type;
+ uint8_t type;
if (buf->om_len < 1) {
BT_WARN("Too short Filter Set message");
@@ -232,7 +239,7 @@ static int filter_set(struct bt_mesh_proxy_client *client,
return 0;
}
-static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
+static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr)
{
int i;
@@ -256,7 +263,7 @@ static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr)
}
}
-static void filter_remove(struct bt_mesh_proxy_client *client, u16_t addr)
+static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr)
{
int i;
@@ -283,7 +290,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client,
.ctx = &rx->ctx,
.src = bt_mesh_primary_addr(),
};
- u16_t filter_size;
+ uint16_t filter_size;
int i, err;
/* Configuration messages always have dst unassigned */
@@ -325,7 +332,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(29);
struct bt_mesh_net_rx rx;
- u8_t opcode;
+ uint8_t opcode;
int err;
err = bt_mesh_net_decode(client->buf, BT_MESH_NET_IF_PROXY_CFG,
@@ -335,8 +342,16 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
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(buf, BT_MESH_NET_HDR_LEN);
+ 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));
@@ -353,7 +368,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
break;
case CFG_FILTER_ADD:
while (buf->om_len >= 2) {
- u16_t addr;
+ uint16_t addr;
addr = net_buf_simple_pull_be16(buf);
filter_add(client, addr);
@@ -362,7 +377,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client)
break;
case CFG_FILTER_REMOVE:
while (buf->om_len >= 2) {
- u16_t addr;
+ uint16_t addr;
addr = net_buf_simple_pull_be16(buf);
filter_remove(client, addr);
@@ -391,21 +406,20 @@ static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub)
return rc;
}
+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);
+}
+
static void proxy_send_beacons(struct ble_npl_event *work)
{
struct bt_mesh_proxy_client *client;
- int i;
-
client = ble_npl_event_get_arg(work);
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx != BT_MESH_KEY_UNUSED) {
- beacon_send(client->conn_handle, sub);
- }
- }
+ (void)bt_mesh_subnet_find(send_beacon_cb, client);
}
static void proxy_sar_timeout(struct ble_npl_event *work)
@@ -431,12 +445,7 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
if (!sub) {
/* NULL means we send on all subnets */
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) {
- bt_mesh_proxy_beacon_send(&bt_mesh.sub[i]);
- }
- }
-
+ bt_mesh_subnet_foreach(bt_mesh_proxy_beacon_send);
return;
}
@@ -447,13 +456,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub)
}
}
-void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
+static void node_id_start(struct bt_mesh_subnet *sub)
{
sub->node_id = BT_MESH_NODE_IDENTITY_RUNNING;
sub->node_id_start = k_uptime_get_32();
+}
+void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub)
+{
+ node_id_start(sub);
/* Prioritize the recently enabled subnet */
- next_idx = sub - bt_mesh.sub;
+ beacon_sub = sub;
}
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
@@ -464,30 +477,13 @@ void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub)
int bt_mesh_proxy_identity_enable(void)
{
- int i, count = 0;
-
BT_DBG("");
if (!bt_mesh_is_provisioned()) {
return -EAGAIN;
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- if (sub->node_id == BT_MESH_NODE_IDENTITY_NOT_SUPPORTED) {
- continue;
- }
-
- bt_mesh_proxy_identity_start(sub);
- count++;
- }
-
- if (count) {
+ if (bt_mesh_subnet_foreach(node_id_start)) {
bt_mesh_adv_update();
}
@@ -530,9 +526,9 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_client *client)
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;
- const u8_t *data = ctxt->om->om_data;
- u16_t len = ctxt->om->om_len;
+ 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);
@@ -654,7 +650,9 @@ static void proxy_connected(uint16_t conn_handle)
static void proxy_disconnected(uint16_t conn_handle, int reason)
{
int i;
- bool disconnected = false;
+
+ BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason);
+ conn_count--;
for (i = 0; i < ARRAY_SIZE(clients); i++) {
struct bt_mesh_proxy_client *client = &clients[i];
@@ -667,16 +665,11 @@ static void proxy_disconnected(uint16_t conn_handle, int reason)
k_delayed_work_cancel(&client->sar_timer);
client->conn_handle = BLE_HS_CONN_HANDLE_NONE;
- conn_count--;
- disconnected = true;
break;
}
}
- if (disconnected) {
- BT_INFO("conn_handle %d reason %d", conn_handle, reason);
- bt_mesh_adv_update();
- }
+ bt_mesh_adv_update();
}
struct os_mbuf *bt_mesh_proxy_get_buf(void)
@@ -889,7 +882,7 @@ int bt_mesh_proxy_gatt_disable(void)
return 0;
}
-void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
+void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr)
{
struct bt_mesh_proxy_client *client = NULL;
int i;
@@ -913,7 +906,7 @@ void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr)
}
static bool client_filter_match(struct bt_mesh_proxy_client *client,
- u16_t addr)
+ uint16_t addr)
{
int i;
@@ -944,7 +937,7 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client,
return false;
}
-bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
+bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst)
{
bool relayed = false;
int i;
@@ -980,9 +973,25 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst)
#endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */
-static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
+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)
{
struct os_mbuf *om;
+ int err = 0;
BT_DBG("%u bytes: %s", len, bt_hex(data, len));
@@ -990,7 +999,8 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
if (gatt_svc == MESH_GATT_PROXY) {
om = ble_hs_mbuf_from_flat(data, len);
assert(om);
- ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
+ err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om);
+ notify_complete();
}
#endif
@@ -998,17 +1008,22 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len)
if (gatt_svc == MESH_GATT_PROV) {
om = ble_hs_mbuf_from_flat(data, len);
assert(om);
- ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
+ err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om);
+ notify_complete();
}
#endif
- return 0;
+ if (!err) {
+ atomic_inc(&pending_notifications);
+ }
+
+ return err;
}
-static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
+static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg)
{
- u16_t mtu;
+ 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));
@@ -1022,7 +1037,7 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type));
proxy_send(conn_handle, msg->om_data, mtu);
- net_buf_simple_pull(msg, mtu);
+ net_buf_simple_pull_mem(msg, mtu);
while (msg->om_len) {
if (msg->om_len + 1 < mtu) {
@@ -1033,13 +1048,13 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type,
net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type));
proxy_send(conn_handle, msg->om_data, mtu);
- net_buf_simple_pull(msg, mtu);
+ net_buf_simple_pull_mem(msg, mtu);
}
return 0;
}
-int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
+int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type,
struct os_mbuf *msg)
{
struct bt_mesh_proxy_client *client = find_client(conn_handle);
@@ -1058,11 +1073,14 @@ int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type,
}
#if (MYNEWT_VAL(BLE_MESH_PB_GATT))
-static u8_t prov_svc_data[20] = { 0x27, 0x18, };
+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, 0x27, 0x18),
+ 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 */
@@ -1077,23 +1095,27 @@ static const struct bt_data prov_ad[] = {
#define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BT_MESH_NODE_ID_TIMEOUT)
-static u8_t proxy_svc_data[NODE_ID_LEN] = { 0x28, 0x18, };
+static uint8_t proxy_svc_data[NODE_ID_LEN] = {
+ BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL),
+};
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, 0x28, 0x18),
+ 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),
};
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, 0x28, 0x18),
+ 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),
};
static int node_id_adv(struct bt_mesh_subnet *sub)
{
- u8_t tmp[16];
+ uint8_t tmp[16];
int err;
BT_DBG("");
@@ -1109,7 +1131,8 @@ static int node_id_adv(struct bt_mesh_subnet *sub)
memcpy(tmp + 6, proxy_svc_data + 11, 8);
sys_put_be16(bt_mesh_primary_addr(), tmp + 14);
- err = bt_encrypt_be(sub->keys[sub->kr_flag].identity, tmp, tmp);
+ err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp,
+ tmp);
if (err) {
return err;
}
@@ -1137,9 +1160,9 @@ static int net_id_adv(struct bt_mesh_subnet *sub)
proxy_svc_data[2] = ID_TYPE_NET;
BT_DBG("Advertising with NetId %s",
- bt_hex(sub->keys[sub->kr_flag].net_id, 8));
+ bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8));
- memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].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);
@@ -1160,60 +1183,75 @@ static bool advertise_subnet(struct bt_mesh_subnet *sub)
}
return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING ||
- bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED);
+ bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED);
}
static struct bt_mesh_subnet *next_sub(void)
{
- int i;
+ struct bt_mesh_subnet *sub = NULL;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub;
-
- sub = &bt_mesh.sub[(i + next_idx) % ARRAY_SIZE(bt_mesh.sub)];
- if (advertise_subnet(sub)) {
- next_idx = (next_idx + 1) % ARRAY_SIZE(bt_mesh.sub);
- return sub;
+ if (!beacon_sub) {
+ beacon_sub = bt_mesh_subnet_next(NULL);
+ if (!beacon_sub) {
+ /* No valid subnets */
+ return NULL;
}
}
+ 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;
}
-static int sub_count(void)
+static int sub_count_cb(struct bt_mesh_subnet *sub, void *cb_data)
{
- int i, count = 0;
+ int *count = cb_data;
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
-
- if (advertise_subnet(sub)) {
- count++;
- }
+ if (advertise_subnet(sub)) {
+ (*count)++;
}
+ return 0;
+}
+
+static int sub_count(void)
+{
+ int count = 0;
+
+ (void)bt_mesh_subnet_find(sub_count_cb, &count);
return count;
}
-static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
+static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
{
- s32_t remaining = K_FOREVER;
+ int32_t remaining = K_FOREVER;
int subnet_count;
BT_DBG("");
if (conn_count == CONFIG_BT_MAX_CONN) {
- BT_DBG("Connectable advertising deferred (max connections)");
- return remaining;
+ BT_DBG("Connectable advertising deferred (max connections %d)", conn_count);
+ return -ENOMEM;
}
+ sub = beacon_sub ? beacon_sub : bt_mesh_subnet_next(beacon_sub);
if (!sub) {
BT_WARN("No subnets to advertise on");
- return remaining;
+ return -ENOENT;
}
if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) {
- u32_t active = k_uptime_get_32() - sub->node_id_start;
+ uint32_t active = k_uptime_get_32() - sub->node_id_start;
if (active < NODE_ID_TIMEOUT) {
remaining = NODE_ID_TIMEOUT - active;
@@ -1233,7 +1271,7 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
subnet_count = sub_count();
BT_DBG("sub_count %u", subnet_count);
if (subnet_count > 1) {
- s32_t max_timeout;
+ int32_t max_timeout;
/* We use NODE_ID_TIMEOUT as a starting point since it may
* be less than 60 seconds. Divide this period into at least
@@ -1251,6 +1289,8 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub)
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;
}
#endif /* GATT_PROXY */
@@ -1301,7 +1341,7 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[2])
}
#endif /* PB_GATT */
-s32_t bt_mesh_proxy_adv_start(void)
+int32_t bt_mesh_proxy_adv_start(void)
{
BT_DBG("");
@@ -1363,6 +1403,19 @@ void bt_mesh_proxy_adv_stop(void)
}
}
+#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)
{
#if MYNEWT_VAL(BLE_EXT_ADV)
@@ -1479,6 +1532,12 @@ int bt_mesh_proxy_init(void)
{
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
+
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);
@@ -1498,5 +1557,15 @@ 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) */
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h
index e099947c9..3764cc3ad 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/proxy.h
@@ -15,8 +15,14 @@
#define BT_MESH_PROXY_PROV 0x03
#include "../include/mesh/mesh.h"
+#include "../include/mesh/slist.h"
-int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, struct os_mbuf *msg);
+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);
@@ -29,16 +35,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub);
struct os_mbuf *bt_mesh_proxy_get_buf(void);
-s32_t bt_mesh_proxy_adv_start(void);
+int32_t bt_mesh_proxy_adv_start(void);
void bt_mesh_proxy_adv_stop(void);
void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub);
void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub);
-bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst);
-void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr);
+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);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/rpl.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/rpl.c
new file mode 100644
index 000000000..5565ff685
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/rpl.c
@@ -0,0 +1,167 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define MESH_LOG_MODULE BLE_MESH_RPL_LOG
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#if MYNEWT_VAL(BLE_MESH)
+
+#include "nimble/porting/nimble/include/log/log.h"
+
+#include "mesh_priv.h"
+#include "adv.h"
+#include "net.h"
+#include "rpl.h"
+#include "settings.h"
+
+static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)];
+
+void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl,
+ struct bt_mesh_net_rx *rx)
+{
+ rpl->src = rx->ctx.addr;
+ rpl->seq = rx->seq;
+ rpl->old_iv = rx->old_iv;
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_rpl(rpl);
+ }
+}
+
+/* Check the Replay Protection List for a replay attempt. If non-NULL match
+ * parameter is given the RPL slot is returned but it is not immediately
+ * updated (needed for segmented messages), whereas if a NULL match is given
+ * the RPL is immediately updated (used for unsegmented messages).
+ */
+bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx,
+ struct bt_mesh_rpl **match)
+{
+ int i;
+
+ /* Don't bother checking messages from ourselves */
+ if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
+ return false;
+ }
+
+ /* The RPL is used only for the local node */
+ if (!rx->local_match) {
+ return false;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ struct bt_mesh_rpl *rpl = &replay_list[i];
+
+ /* Empty slot */
+ if (!rpl->src) {
+ if (match) {
+ *match = rpl;
+ } else {
+ bt_mesh_rpl_update(rpl, rx);
+ }
+
+ return false;
+ }
+
+ /* Existing slot for given address */
+ if (rpl->src == rx->ctx.addr) {
+ if (rx->old_iv && !rpl->old_iv) {
+ return true;
+ }
+
+ if ((!rx->old_iv && rpl->old_iv) ||
+ rpl->seq < rx->seq) {
+ if (match) {
+ *match = rpl;
+ } else {
+ bt_mesh_rpl_update(rpl, rx);
+ }
+
+ return false;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ BT_ERR("RPL is full!");
+ return true;
+}
+
+void bt_mesh_rpl_clear(void)
+{
+ BT_DBG("");
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_clear_rpl();
+ } else {
+ (void)memset(replay_list, 0, sizeof(replay_list));
+ }
+}
+
+struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ if (replay_list[i].src == src) {
+ return &replay_list[i];
+ }
+ }
+
+ return NULL;
+}
+
+struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ if (!replay_list[i].src) {
+ replay_list[i].src = src;
+ return &replay_list[i];
+ }
+ }
+
+ 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;
+
+ /* Discard "old old" IV Index entries from RPL and flag
+ * any other ones (which are valid) as old.
+ */
+ for (i = 0; i < ARRAY_SIZE(replay_list); i++) {
+ struct bt_mesh_rpl *rpl = &replay_list[i];
+
+ if (rpl->src) {
+ if (rpl->old_iv) {
+ (void)memset(rpl, 0, sizeof(*rpl));
+ } else {
+ rpl->old_iv = true;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_rpl(rpl);
+ }
+ }
+ }
+}
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/rpl.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/rpl.h
new file mode 100644
index 000000000..0592712f8
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/rpl.h
@@ -0,0 +1,30 @@
+/* Bluetooth Mesh */
+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Lingao Meng
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+struct bt_mesh_rpl {
+ uint16_t src;
+ bool old_iv;
+#if defined(CONFIG_BT_SETTINGS)
+ bool store;
+#endif
+ uint32_t seq;
+};
+
+typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl,
+ void *user_data);
+
+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
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c
index 2130e9e6c..345a7d2df 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.c
@@ -11,16 +11,23 @@
#if MYNEWT_VAL(BLE_MESH_SETTINGS)
+#include "mesh_priv.h"
#include "../include/mesh/mesh.h"
#include "../include/mesh/glue.h"
+#include "subnet.h"
+#include "app_keys.h"
#include "net.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 "nodes.h"
+#include "lpn.h"
+#include "cfg.h"
+
#include "config/config.h"
@@ -29,116 +36,152 @@
* 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.
*/
-static struct key_update {
- u16_t key_idx:12, /* AppKey or NetKey Index */
+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 */
-} key_updates[CONFIG_BT_MESH_APP_KEY_COUNT + CONFIG_BT_MESH_SUBNET_COUNT];
+};
+
+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 {
- u16_t primary_addr;
- u8_t dev_key[16];
+ uint16_t primary_addr;
+ uint8_t dev_key[16];
} __packed;
/* Sequence number storage */
struct seq_val {
- u8_t val[3];
+ uint8_t val[3];
} __packed;
/* Heartbeat Publication storage */
struct hb_pub_val {
- u16_t dst;
- u8_t period;
- u8_t ttl;
- u16_t feat;
- u16_t net_idx:12,
+ 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 {
- u8_t net_transmit;
- u8_t relay;
- u8_t relay_retransmit;
- u8_t beacon;
- u8_t gatt_proxy;
- u8_t frnd;
- u8_t default_ttl;
+ 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 {
- u32_t iv_index;
- u8_t iv_update:1,
+ uint32_t iv_index;
+ uint8_t iv_update:1,
iv_duration:7;
} __packed;
/* Replay Protection List storage */
struct rpl_val {
- u32_t seq:24,
+ uint32_t seq:24,
old_iv:1;
};
/* NetKey storage information */
struct net_key_val {
- u8_t kr_flag:1,
+ uint8_t kr_flag:1,
kr_phase:7;
- u8_t val[2][16];
+ uint8_t val[2][16];
} __packed;
/* AppKey storage information */
struct app_key_val {
- u16_t net_idx;
+ uint16_t net_idx;
bool updated;
- u8_t val[2][16];
+ uint8_t val[2][16];
} __packed;
struct mod_pub_val {
- u16_t addr;
- u16_t key;
- u8_t ttl;
- u8_t retransmit;
- u8_t period;
- u8_t period_div:4,
+ 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 {
- u16_t ref;
- u16_t addr;
- u8_t uuid[16];
+ 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 {
- u16_t net_idx;
- u8_t dev_key[16];
- u8_t num_elem;
+ 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 {
- u16_t addr;
+ uint16_t addr;
bool clear;
};
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-static struct node_update node_updates[CONFIG_BT_MESH_NODE_COUNT];
-#else
-static struct node_update node_updates[0];
+#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
-/* We need this so we don't overwrite app-hardcoded values in case FCB
- * contains a history of changes but then has a NULL at the end.
- */
-static struct {
- bool valid;
- struct cfg_val cfg;
-} stored_cfg;
+int settings_name_next(char *name, char **next)
+{
+ int rc = 0;
+
+ if (next) {
+ *next = NULL;
+ }
+
+ if (!name) {
+ return 0;
+ }
+
+ /* name might come from flash directly, in flash the name would end
+ * with '=' or '\0' depending how storage is done. Flash reading is
+ * limited to what can be read
+ */
+ while ((*name != '\0') && (*name != '=') &&
+ (*name != '/')) {
+ rc++;
+ name++;
+ }
+
+ if (*name == '/') {
+ if (next) {
+ *next = name + 1;
+ }
+ return rc;
+ }
+
+ return rc;
+}
static int net_set(int argc, char **argv, char *val)
{
@@ -233,8 +276,7 @@ static int seq_set(int argc, char **argv, char *val)
return -EINVAL;
}
- bt_mesh.seq = ((u32_t)seq.val[0] | ((u32_t)seq.val[1] << 8) |
- ((u32_t)seq.val[2] << 16));
+ 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
@@ -251,39 +293,12 @@ static int seq_set(int argc, char **argv, char *val)
return 0;
}
-static struct bt_mesh_rpl *rpl_find(u16_t src)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- if (bt_mesh.rpl[i].src == src) {
- return &bt_mesh.rpl[i];
- }
- }
-
- return NULL;
-}
-
-static struct bt_mesh_rpl *rpl_alloc(u16_t src)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- if (!bt_mesh.rpl[i].src) {
- bt_mesh.rpl[i].src = src;
- return &bt_mesh.rpl[i];
- }
- }
-
- return NULL;
-}
-
static int rpl_set(int argc, char **argv, char *val)
{
struct bt_mesh_rpl *entry;
struct rpl_val rpl;
int len, err;
- u16_t src;
+ uint16_t src;
if (argc < 1) {
BT_ERR("Invalid argc (%d)", argc);
@@ -293,7 +308,7 @@ static int rpl_set(int argc, char **argv, char *val)
BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)");
src = strtol(argv[0], NULL, 16);
- entry = rpl_find(src);
+ entry = bt_mesh_rpl_find(src);
if (!val) {
if (entry) {
@@ -306,7 +321,7 @@ static int rpl_set(int argc, char **argv, char *val)
}
if (!entry) {
- entry = rpl_alloc(src);
+ entry = bt_mesh_rpl_alloc(src);
if (!entry) {
BT_ERR("Unable to allocate RPL entry for 0x%04x", src);
return -ENOMEM;
@@ -336,26 +351,13 @@ static int rpl_set(int argc, char **argv, char *val)
static int net_key_set(int argc, char **argv, char *val)
{
- struct bt_mesh_subnet *sub;
struct net_key_val key;
- int len, i, err;
- u16_t net_idx;
+ 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);
- sub = bt_mesh_subnet_get(net_idx);
-
- if (!val) {
- if (!sub) {
- BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx);
- return -ENOENT;
- }
-
- BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx);
- bt_mesh_subnet_del(sub, false);
- return 0;
- }
len = sizeof(key);
err = settings_bytes_from_str(val, &key, &len);
@@ -369,93 +371,41 @@ static int net_key_set(int argc, char **argv, char *val)
return -EINVAL;
}
- 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.val[0], 16);
- memcpy(sub->keys[1].net, &key.val[1], 16);
-
- return 0;
- }
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) {
- sub = &bt_mesh.sub[i];
- break;
- }
- }
-
- if (!sub) {
- BT_ERR("No space to allocate a new subnet");
- return -ENOMEM;
- }
-
- sub->net_idx = net_idx;
- sub->kr_flag = key.kr_flag;
- sub->kr_phase = key.kr_phase;
- memcpy(sub->keys[0].net, &key.val[0], 16);
- memcpy(sub->keys[1].net, &key.val[1], 16);
-
BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx);
- return 0;
+ 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 bt_mesh_app_key *app;
struct app_key_val key;
- u16_t app_idx;
- int len, err;
+ 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 (!val) {
- BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx);
-
- app = bt_mesh_app_key_find(app_idx);
- if (app) {
- bt_mesh_app_key_del(app, false);
- }
-
+ if (!len_rd) {
return 0;
}
- len = sizeof(key);
- err = settings_bytes_from_str(val, &key, &len);
+ err = settings_bytes_from_str(val, &key, &len_rd);
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;
+ 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;
}
- app = bt_mesh_app_key_find(app_idx);
- if (!app) {
- app = bt_mesh_app_key_alloc(app_idx);
- }
-
- if (!app) {
- BT_ERR("No space for a new app key");
- return -ENOMEM;
- }
-
- app->net_idx = key.net_idx;
- app->app_idx = app_idx;
- app->updated = key.updated;
- memcpy(app->keys[0].val, key.val[0], 16);
- memcpy(app->keys[1].val, key.val[1], 16);
-
- bt_mesh_app_id(app->keys[0].val, &app->keys[0].id);
- bt_mesh_app_id(app->keys[1].val, &app->keys[1].id);
-
BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx);
return 0;
@@ -463,27 +413,12 @@ static int app_key_set(int argc, char **argv, char *val)
static int hb_pub_set(int argc, char **argv, char *val)
{
- struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get();
+ struct bt_mesh_hb_pub pub;
struct hb_pub_val hb_val;
int len, err;
BT_DBG("val %s", val ? val : "(null)");
- if (!pub) {
- return -ENOENT;
- }
-
- if (!val) {
- pub->dst = BT_MESH_ADDR_UNASSIGNED;
- pub->count = 0;
- pub->ttl = 0;
- pub->period = 0;
- pub->feat = 0;
-
- BT_DBG("Cleared heartbeat publication");
- return 0;
- }
-
len = sizeof(hb_val);
err = settings_bytes_from_str(val, &hb_val, &len);
if (err) {
@@ -497,18 +432,20 @@ static int hb_pub_set(int argc, char **argv, char *val)
return -EINVAL;
}
- pub->dst = hb_val.dst;
- pub->period = hb_val.period;
- pub->ttl = hb_val.ttl;
- pub->feat = hb_val.feat;
- pub->net_idx = hb_val.net_idx;
+ 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;
+ pub.count = 0xffff;
} else {
- pub->count = 0;
+ pub.count = 0;
}
+ (void)bt_mesh_hb_pub_set(&pub);
+
BT_DBG("Restored heartbeat publication");
return 0;
@@ -516,35 +453,36 @@ static int hb_pub_set(int argc, char **argv, char *val)
static int cfg_set(int argc, char **argv, char *val)
{
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
+ struct cfg_val cfg;
int len, err;
BT_DBG("val %s", val ? val : "(null)");
- if (!cfg) {
- return -ENOENT;
- }
-
if (!val) {
- stored_cfg.valid = false;
BT_DBG("Cleared configuration state");
return 0;
}
- len = sizeof(stored_cfg.cfg);
- err = settings_bytes_from_str(val, &stored_cfg.cfg, &len);
+ 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(stored_cfg.cfg)) {
+ if (len != sizeof(cfg)) {
BT_ERR("Unexpected value length (%d != %zu)", len,
- sizeof(stored_cfg.cfg));
+ sizeof(cfg));
return -EINVAL;
}
- stored_cfg.valid = true;
+ 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;
@@ -648,11 +586,25 @@ static int mod_set_pub(struct bt_mesh_model *mod, char *val)
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;
- u8_t elem_idx, mod_idx;
- u16_t mod_key;
+ uint8_t elem_idx, mod_idx;
+ uint16_t mod_key;
if (argc < 2) {
BT_ERR("Too small argc (%d)", argc);
@@ -686,11 +638,7 @@ static int mod_set(bool vnd, int argc, char **argv, char *val)
}
if (!strcmp(argv[1], "data")) {
- mod->flags |= BT_MESH_MOD_DATA_PRESENT;
-
- if (mod->cb && mod->cb->settings_set) {
- return mod->cb->settings_set(mod, val);
- }
+ return mod_data_set(mod, argv[1], val);
}
BT_WARN("Unknown module key %s", argv[1]);
@@ -711,8 +659,8 @@ static int vnd_mod_set(int argc, char **argv, char *val)
static int va_set(int argc, char **argv, char *val)
{
struct va_val va;
- struct label *lab;
- u16_t index;
+ struct bt_mesh_va *lab;
+ uint16_t index;
int len, err;
if (argc < 1) {
@@ -743,7 +691,7 @@ static int va_set(int argc, char **argv, char *val)
return 0;
}
- lab = get_label(index);
+ lab = bt_mesh_va_get(index);
if (lab == NULL) {
BT_WARN("Out of labels buffers");
return -ENOBUFS;
@@ -760,12 +708,35 @@ static int va_set(int argc, char **argv, char *val)
}
#endif
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
-static int node_set(int argc, char **argv, char *str)
+#if MYNEWT_VAL(BLE_MESH_CDB)
+static int cdb_net_set(int argc, char *val)
{
- struct bt_mesh_node *node;
+ 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;
- u16_t addr;
+ uint16_t addr;
int len, err;
if (argc < 1) {
@@ -773,15 +744,16 @@ static int node_set(int argc, char **argv, char *str)
return -ENOENT;
}
- addr = strtol(argv[0], NULL, 16);
+ addr = strtol(str, NULL, 16);
+ len = sizeof(str);
- if (str == NULL) {
+ if (argc < 1) {
BT_DBG("val (null)");
BT_DBG("Deleting node 0x%04x", addr);
- node = bt_mesh_node_find(addr);
+ node = bt_mesh_cdb_node_get(addr);
if (node) {
- bt_mesh_node_del(node, false);
+ bt_mesh_cdb_node_del(node, false);
}
return 0;
@@ -798,9 +770,10 @@ static int node_set(int argc, char **argv, char *str)
return -EINVAL;
}
- node = bt_mesh_node_find(addr);
+ node = bt_mesh_cdb_node_get(addr);
if (!node) {
- node = bt_mesh_node_alloc(addr, val.num_elem, val.net_idx);
+ node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem,
+ val.net_idx);
}
if (!node) {
@@ -808,12 +781,163 @@ static int node_set(int argc, char **argv, char *str)
return -ENOMEM;
}
- memcpy(node->dev_key, &val.dev_key, 16);
+ 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_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);
+
+ 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_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);
+
+ 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 {
@@ -833,8 +957,8 @@ const struct mesh_setting {
#if CONFIG_BT_MESH_LABEL_COUNT > 0
{ "Va", va_set },
#endif
-#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
- { "Node", node_set },
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ { "cdb", cdb_set },
#endif
};
@@ -863,43 +987,12 @@ static int mesh_set(int argc, char **argv, char *val)
return -ENOENT;
}
-static int subnet_init(struct bt_mesh_subnet *sub)
-{
- int err;
-
- err = bt_mesh_net_keys_create(&sub->keys[0], sub->keys[0].net);
- if (err) {
- BT_ERR("Unable to generate keys for subnet");
- return -EIO;
- }
-
- if (sub->kr_phase != BT_MESH_KR_NORMAL) {
- err = bt_mesh_net_keys_create(&sub->keys[1], sub->keys[1].net);
- if (err) {
- BT_ERR("Unable to generate keys for subnet");
- memset(&sub->keys[0], 0, sizeof(sub->keys[0]));
- return -EIO;
- }
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
- sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
- } else {
- sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
- }
-
- /* Make sure we have valid beacon data to be sent */
- bt_mesh_net_beacon_update(sub);
-
- return 0;
-}
-
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) {
- s32_t ms = bt_mesh_model_pub_period_get(mod);
+ int32_t ms = bt_mesh_model_pub_period_get(mod);
if (ms) {
BT_DBG("Starting publish timer (period %u ms)",
(unsigned) ms);
@@ -907,20 +1000,20 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem,
}
}
- if (mod->cb && mod->cb->settings_commit) {
- mod->cb->settings_commit(mod);
+ 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)
{
- struct bt_mesh_hb_pub *hb_pub;
- struct bt_mesh_cfg_srv *cfg;
- int i;
-
- BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx);
-
- if (bt_mesh.sub[0].net_idx == BT_MESH_KEY_UNUSED) {
+ if (!bt_mesh_subnet_next(NULL)) {
/* Nothing to do since we're not yet provisioned */
return 0;
}
@@ -929,47 +1022,15 @@ static int mesh_commit(void)
bt_mesh_proxy_prov_disable(true);
}
- for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) {
- struct bt_mesh_subnet *sub = &bt_mesh.sub[i];
- int err;
-
- if (sub->net_idx == BT_MESH_KEY_UNUSED) {
- continue;
- }
-
- err = subnet_init(sub);
- if (err) {
- BT_ERR("Failed to init subnet 0x%03x", sub->net_idx);
- }
- }
-
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);
- hb_pub = bt_mesh_hb_pub_get();
- if (hb_pub && hb_pub->dst != BT_MESH_ADDR_UNASSIGNED &&
- hb_pub->count && hb_pub->period) {
- BT_DBG("Starting heartbeat publication");
- k_work_submit(&hb_pub->timer.work);
- }
-
- cfg = bt_mesh_cfg_get();
- if (cfg && stored_cfg.valid) {
- cfg->net_transmit = stored_cfg.cfg.net_transmit;
- cfg->relay = stored_cfg.cfg.relay;
- cfg->relay_retransmit = stored_cfg.cfg.relay_retransmit;
- cfg->beacon = stored_cfg.cfg.beacon;
- cfg->gatt_proxy = stored_cfg.cfg.gatt_proxy;
- cfg->frnd = stored_cfg.cfg.frnd;
- cfg->default_ttl = stored_cfg.cfg.default_ttl;
- }
-
atomic_set_bit(bt_mesh.flags, BT_MESH_VALID);
- bt_mesh_net_start();
+ bt_mesh_start();
return 0;
}
@@ -983,12 +1044,11 @@ static int mesh_commit(void)
#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) | \
- BIT(BT_MESH_NODES_PENDING))
+ BIT(BT_MESH_MOD_PENDING))
static void schedule_store(int flag)
{
- s32_t timeout, remaining;
+ int32_t timeout, remaining;
atomic_set_bit(bt_mesh.flags, flag);
@@ -1114,9 +1174,7 @@ static void store_pending_seq(void)
char *str;
int err;
- seq.val[0] = bt_mesh.seq;
- seq.val[1] = bt_mesh.seq >> 8;
- seq.val[2] = bt_mesh.seq >> 16;
+ sys_put_le24(bt_mesh.seq, seq.val);
str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf));
if (!str) {
@@ -1174,69 +1232,54 @@ static void store_rpl(struct bt_mesh_rpl *entry)
}
}
-static void clear_rpl(void)
+static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{
- int i, err;
+ int err;
+ char path[18];
- BT_DBG("");
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
- char path[18];
-
- if (!rpl->src) {
- continue;
- }
-
- 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");
- }
-
- memset(rpl, 0, sizeof(*rpl));
+ 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(void)
+static void store_pending_rpl(struct bt_mesh_rpl *rpl, void *user_data)
{
- int i;
-
BT_DBG("");
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
- if (rpl->store) {
- rpl->store = false;
- store_rpl(rpl);
- }
+ 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 = bt_mesh_hb_pub_get();
+ struct bt_mesh_hb_pub pub;
struct hb_pub_val val;
char *str;
int err;
- if (!pub) {
- return;
- }
-
- if (pub->dst == BT_MESH_ADDR_UNASSIGNED) {
+ 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 = pub->period;
- val.ttl = pub->ttl;
- val.feat = pub->feat;
- val.net_idx = pub->net_idx;
+ 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));
@@ -1259,22 +1302,17 @@ static void store_pending_hb_pub(void)
static void store_pending_cfg(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct cfg_val))];
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
struct cfg_val val;
char *str;
int err;
- if (!cfg) {
- return;
- }
-
- val.net_transmit = cfg->net_transmit;
- val.relay = cfg->relay;
- val.relay_retransmit = cfg->relay_retransmit;
- val.beacon = cfg->beacon;
- val.gatt_proxy = cfg->gatt_proxy;
- val.frnd = cfg->frnd;
- val.default_ttl = cfg->default_ttl;
+ 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) {
@@ -1303,7 +1341,7 @@ static void clear_cfg(void)
}
}
-static void clear_app_key(u16_t app_idx)
+static void clear_app_key(uint16_t app_idx)
{
char path[20];
int err;
@@ -1319,7 +1357,7 @@ static void clear_app_key(u16_t app_idx)
}
}
-static void clear_net_key(u16_t net_idx)
+static void clear_net_key(uint16_t net_idx)
{
char path[20];
int err;
@@ -1335,31 +1373,36 @@ static void clear_net_key(u16_t net_idx)
}
}
-static void store_net_key(struct bt_mesh_subnet *sub)
+static void store_subnet(uint16_t net_idx)
{
- char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))];
+ 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;
- BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx,
- bt_hex(sub->keys[0].net, 16));
+ 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 = sub->kr_flag;
+ 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 NetKey as value");
+ BT_ERR("Unable to encode AppKey as value");
return;
}
- snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", sub->net_idx);
-
- BT_DBG("Saving NetKey %s as value %s", path, str);
err = settings_save_one(path, str);
if (err) {
BT_ERR("Failed to store NetKey");
@@ -1368,16 +1411,26 @@ static void store_net_key(struct bt_mesh_subnet *sub)
}
}
-static void store_app_key(struct bt_mesh_app_key *app)
+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;
- key.net_idx = app->net_idx;
- key.updated = app->updated;
+ 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);
@@ -1416,47 +1469,72 @@ static void store_pending_keys(void)
clear_net_key(update->key_idx);
}
} else {
- if (update->app_key) {
- struct bt_mesh_app_key *key;
-
- key = bt_mesh_app_key_find(update->key_idx);
- if (key) {
- store_app_key(key);
- } else {
- BT_WARN("AppKeyIndex 0x%03x not found",
- update->key_idx);
- }
-
- } else {
- struct bt_mesh_subnet *sub;
-
- sub = bt_mesh_subnet_get(update->key_idx);
- if (sub) {
- store_net_key(sub);
- } else {
- BT_WARN("NetKeyIndex 0x%03x not found",
- update->key_idx);
- }
- }
+ store_subnet(update->key_idx);
}
update->valid = 0;
}
}
-static void store_node(struct bt_mesh_node *node)
+#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[20];
+ 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/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) {
@@ -1473,14 +1551,14 @@ static void store_node(struct bt_mesh_node *node)
}
}
-static void clear_node(u16_t addr)
+static void clear_cdb_node(uint16_t addr)
{
- char path[20];
+ char path[30];
int err;
BT_DBG("Node 0x%04x", addr);
- snprintk(path, sizeof(path), "bt_mesh/Node/%x", 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);
@@ -1489,25 +1567,27 @@ static void clear_node(u16_t addr)
}
}
-static void store_pending_nodes(void)
+static void store_pending_cdb_nodes(void)
{
int i;
- for (i = 0; i < ARRAY_SIZE(node_updates); ++i) {
- struct node_update *update = &node_updates[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;
}
- if (update->clear) {
- clear_node(update->addr);
- } else {
- struct bt_mesh_node *node;
+ BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear);
- node = bt_mesh_node_find(update->addr);
+ 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_node(node);
+ store_cdb_node(node);
} else {
BT_WARN("Node 0x%04x not found", update->addr);
}
@@ -1517,8 +1597,139 @@ static void store_pending_nodes(void)
}
}
-static struct node_update *node_update_find(u16_t addr,
- struct node_update **free_slot)
+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 = sub->kr_flag;
+ 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;
@@ -1526,8 +1737,8 @@ static struct node_update *node_update_find(u16_t addr,
match = NULL;
*free_slot = NULL;
- for (i = 0; i < ARRAY_SIZE(node_updates); i++) {
- struct node_update *update = &node_updates[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) {
*free_slot = update;
@@ -1541,11 +1752,12 @@ static struct node_update *node_update_find(u16_t addr,
return match;
}
+#endif
static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
const char *key, char *path, size_t path_len)
{
- u16_t mod_key = (((u16_t)mod->elem_idx << 8) | mod->mod_idx);
+ 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);
@@ -1556,7 +1768,7 @@ static void encode_mod_path(struct bt_mesh_model *mod, bool vnd,
static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
{
- u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
+ uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
char buf[BT_SETTINGS_SIZE(sizeof(keys))];
char path[20];
int i, count, err;
@@ -1592,7 +1804,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd)
static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd)
{
- u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
+ uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
char buf[BT_SETTINGS_SIZE(sizeof(groups))];
char path[20];
int i, count, err;
@@ -1692,19 +1904,20 @@ static void store_pending_mod(struct bt_mesh_model *mod,
static void store_pending_va(void)
{
char buf[BT_SETTINGS_SIZE(sizeof(struct va_val))];
- struct label *lab;
+ struct bt_mesh_va *lab;
struct va_val va;
char path[18];
char *val;
- u16_t i;
+ uint16_t i;
int err = 0;
- for (i = 0; (lab = get_label(i)) != NULL; i++) {
- if (!atomic_test_and_clear_bit(lab->flags,
- BT_MESH_VA_CHANGED)) {
+ 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)) {
@@ -1740,9 +1953,9 @@ static void store_pending(struct ble_npl_event *work)
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) {
if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
- store_pending_rpl();
+ bt_mesh_rpl_foreach(store_pending_rpl, NULL);
} else {
- clear_rpl();
+ bt_mesh_rpl_foreach(clear_rpl, NULL);
}
}
@@ -1790,10 +2003,29 @@ static void store_pending(struct ble_npl_event *work)
store_pending_va();
}
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) &&
- atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NODES_PENDING)) {
- store_pending_nodes();
+#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)
@@ -1802,7 +2034,7 @@ void bt_mesh_store_rpl(struct bt_mesh_rpl *entry)
schedule_store(BT_MESH_RPL_PENDING);
}
-static struct key_update *key_update_find(bool app_key, u16_t key_idx,
+static struct key_update *key_update_find(bool app_key, uint16_t key_idx,
struct key_update **free_slot)
{
struct key_update *match;
@@ -1831,13 +2063,13 @@ static struct key_update *key_update_find(bool app_key, u16_t key_idx,
return match;
}
-void bt_mesh_store_subnet(struct bt_mesh_subnet *sub)
+void bt_mesh_store_subnet(uint16_t net_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
- update = key_update_find(false, sub->net_idx, &free_slot);
+ update = key_update_find(false, net_idx, &free_slot);
if (update) {
update->clear = 0;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1845,25 +2077,25 @@ void bt_mesh_store_subnet(struct bt_mesh_subnet *sub)
}
if (!free_slot) {
- store_net_key(sub);
+ store_subnet(net_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = sub->net_idx;
+ 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(struct bt_mesh_app_key *key)
+void bt_mesh_store_app_key(uint16_t app_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+ BT_DBG("AppKeyIndex 0x%03x", app_idx);
- update = key_update_find(true, key->app_idx, &free_slot);
+ update = key_update_find(true, app_idx, &free_slot);
if (update) {
update->clear = 0;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1871,12 +2103,12 @@ void bt_mesh_store_app_key(struct bt_mesh_app_key *key)
}
if (!free_slot) {
- store_app_key(key);
+ store_app(app_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = key->app_idx;
+ free_slot->key_idx = app_idx;
free_slot->app_key = 1;
free_slot->clear = 0;
@@ -1900,13 +2132,13 @@ void bt_mesh_clear_net(void)
schedule_store(BT_MESH_CFG_PENDING);
}
-void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub)
+void bt_mesh_clear_subnet(uint16_t net_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("NetKeyIndex 0x%03x", sub->net_idx);
+ BT_DBG("NetKeyIndex 0x%03x", net_idx);
- update = key_update_find(false, sub->net_idx, &free_slot);
+ update = key_update_find(false, net_idx, &free_slot);
if (update) {
update->clear = 1;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1914,25 +2146,25 @@ void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub)
}
if (!free_slot) {
- clear_net_key(sub->net_idx);
+ clear_net_key(net_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = sub->net_idx;
+ 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(struct bt_mesh_app_key *key)
+void bt_mesh_clear_app_key(uint16_t app_idx)
{
struct key_update *update, *free_slot;
- BT_DBG("AppKeyIndex 0x%03x", key->app_idx);
+ BT_DBG("AppKeyIndex 0x%03x", app_idx);
- update = key_update_find(true, key->app_idx, &free_slot);
+ update = key_update_find(true, app_idx, &free_slot);
if (update) {
update->clear = 1;
schedule_store(BT_MESH_KEYS_PENDING);
@@ -1940,12 +2172,12 @@ void bt_mesh_clear_app_key(struct bt_mesh_app_key *key)
}
if (!free_slot) {
- clear_app_key(key->app_idx);
+ clear_app_key(app_idx);
return;
}
free_slot->valid = 1;
- free_slot->key_idx = key->app_idx;
+ free_slot->key_idx = app_idx;
free_slot->app_key = 1;
free_slot->clear = 1;
@@ -1981,64 +2213,217 @@ void bt_mesh_store_label(void)
schedule_store(BT_MESH_VA_PENDING);
}
-void bt_mesh_store_node(struct bt_mesh_node *node)
+#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 = node_update_find(node->addr, &free_slot);
+ update = cdb_node_update_find(node->addr, &free_slot);
if (update) {
update->clear = false;
- schedule_store(BT_MESH_NODES_PENDING);
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
return;
}
if (!free_slot) {
- store_node(node);
+ store_cdb_node(node);
return;
}
free_slot->addr = node->addr;
+ free_slot->clear = false;
- schedule_store(BT_MESH_NODES_PENDING);
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
}
-void bt_mesh_clear_node(struct bt_mesh_node *node)
+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 = node_update_find(node->addr, &free_slot);
+ update = cdb_node_update_find(node->addr, &free_slot);
if (update) {
update->clear = true;
- schedule_store(BT_MESH_NODES_PENDING);
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
return;
}
if (!free_slot) {
- clear_node(node->addr);
+ clear_cdb_node(node->addr);
return;
}
free_slot->addr = node->addr;
+ free_slot->clear = true;
- schedule_store(BT_MESH_NODES_PENDING);
+ schedule_cdb_store(BT_MESH_CDB_NODES_PENDING);
}
-int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
- const void *data, size_t data_len)
+/* 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)
{
- char path[20];
+ 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) {
- mod->flags |= BT_MESH_MOD_DATA_PRESENT;
val = settings_str_from_bytes(data, data_len,
buf, sizeof(buf));
if (!val) {
@@ -2046,12 +2431,8 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
return -EINVAL;
}
err = settings_save_one(path, val);
- } else if (mod->flags & BT_MESH_MOD_DATA_PRESENT) {
- mod->flags &= ~BT_MESH_MOD_DATA_PRESENT;
- err = settings_save_one(path, NULL);
} else {
- /* Nothing to delete */
- err = 0;
+ err = settings_save_one(path, NULL);
}
if (err) {
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.h
index c630814e5..9060a14a7 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/settings.h
@@ -8,20 +8,25 @@ 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(struct bt_mesh_subnet *sub);
-void bt_mesh_store_app_key(struct bt_mesh_app_key *key);
+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_node(struct bt_mesh_node *node);
+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(struct bt_mesh_subnet *sub);
-void bt_mesh_clear_app_key(struct bt_mesh_app_key *key);
+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_node(struct bt_mesh_node *node);
+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);
void bt_mesh_settings_init(void);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c
index c19342764..f8951b827 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/shell.c
@@ -26,12 +26,12 @@
/* Private includes for raw Network & Transport layer access */
#include "net.h"
+#include "rpl.h"
#include "access.h"
#include "mesh_priv.h"
#include "lpn.h"
#include "transport.h"
#include "foundation.h"
-#include "testing.h"
#include "settings.h"
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
@@ -56,50 +56,29 @@ static struct os_eventq mesh_shell_queue;
#define VND_MODEL_ID_1 0x1234
/* Default net, app & dev key values, unless otherwise specified */
-static const u8_t default_key[16] = {
+static const uint8_t default_key[16] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
};
static struct {
- u16_t local;
- u16_t dst;
- u16_t net_idx;
- u16_t app_idx;
+ uint16_t local;
+ uint16_t dst;
+ uint16_t net_idx;
+ uint16_t app_idx;
} net = {
.local = BT_MESH_ADDR_UNASSIGNED,
.dst = BT_MESH_ADDR_UNASSIGNED,
};
-static struct bt_mesh_cfg_srv cfg_srv = {
- .relay = BT_MESH_RELAY_DISABLED,
- .beacon = BT_MESH_BEACON_ENABLED,
-#if MYNEWT_VAL(BLE_MESH_FRIEND)
- .frnd = BT_MESH_FRIEND_DISABLED,
-#else
- .frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
-#endif
-#if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
- .gatt_proxy = BT_MESH_GATT_PROXY_DISABLED,
-#else
- .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
-#endif
-
- .default_ttl = 7,
-
- /* 3 transmissions with 20ms interval */
- .net_transmit = BT_MESH_TRANSMIT(2, 20),
- .relay_retransmit = BT_MESH_TRANSMIT(2, 20),
-};
-
#define CUR_FAULTS_MAX 4
-static u8_t cur_faults[CUR_FAULTS_MAX];
-static u8_t reg_faults[CUR_FAULTS_MAX * 2];
+static uint8_t cur_faults[CUR_FAULTS_MAX];
+static uint8_t reg_faults[CUR_FAULTS_MAX * 2];
-static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
+static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
{
- u8_t i, limit = *count;
+ uint8_t i, limit = *count;
for (i = 0, *count = 0; i < faults_size && *count < limit; i++) {
if (faults[i]) {
@@ -109,8 +88,8 @@ static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
}
}
-static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
- u16_t *company_id, u8_t *faults, u8_t *fault_count)
+static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id,
+ uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
{
printk("Sending current faults\n");
@@ -122,8 +101,8 @@ static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
return 0;
}
-static int fault_get_reg(struct bt_mesh_model *model, u16_t cid,
- u8_t *test_id, u8_t *faults, u8_t *fault_count)
+static int fault_get_reg(struct bt_mesh_model *model, uint16_t cid,
+ uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
{
if (cid != CID_VENDOR) {
printk("Faults requested for unknown Company ID 0x%04x\n", cid);
@@ -190,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(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
+void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count)
{
size_t i;
@@ -208,8 +187,8 @@ void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
}
}
-static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr,
- u8_t test_id, u16_t cid, u8_t *faults,
+static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
+ uint8_t test_id, uint16_t cid, uint8_t *faults,
size_t fault_count)
{
printk("Health Current Status from 0x%04x\n", addr);
@@ -243,22 +222,22 @@ static struct bt_mesh_light_lightness_srv light_lightness_srv = {
.set = light_model_light_lightness_set,
};
-void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state),
- int (*set)(struct bt_mesh_model *model, u8_t state))
+void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state),
+ int (*set)(struct bt_mesh_model *model, uint8_t state))
{
gen_onoff_srv.get = get;
gen_onoff_srv.set = set;
}
-void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
- int (*set)(struct bt_mesh_model *model, s16_t level))
+void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level))
{
gen_level_srv.get = get;
gen_level_srv.set = set;
}
-void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level),
- int (*set)(struct bt_mesh_model *model, s16_t level))
+void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level),
+ int (*set)(struct bt_mesh_model *model, int16_t level))
{
light_lightness_srv.get = get;
light_lightness_srv.set = set;
@@ -266,7 +245,7 @@ void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model,
#endif
static struct bt_mesh_model root_models[] = {
- BT_MESH_MODEL_CFG_SRV(&cfg_srv),
+ BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
#if MYNEWT_VAL(BLE_MESH_CFG_CLI)
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
@@ -298,7 +277,7 @@ static const struct bt_mesh_comp comp = {
.elem_count = ARRAY_SIZE(elements),
};
-static u8_t hex2val(char c)
+static uint8_t hex2val(char c)
{
if (c >= '0' && c <= '9') {
return c - '0';
@@ -311,7 +290,54 @@ static u8_t hex2val(char c)
}
}
-static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
+int char2hex(char c, uint8_t *x)
+{
+ if (c >= '0' && c <= '9') {
+ *x = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ *x = c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ *x = c - 'A' + 10;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int hex2char(uint8_t x, char *c)
+{
+ if (x <= 9) {
+ *c = x + '0';
+ } else if (x <= 15) {
+ *c = x - 10 + 'a';
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)
+{
+ if ((hexlen + 1) < buflen * 2) {
+ return 0;
+ }
+
+ for (size_t i = 0; i < buflen; i++) {
+ if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) {
+ return 0;
+ }
+ if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) {
+ return 0;
+ }
+ }
+
+ hex[2 * buflen] = '\0';
+ return 2 * buflen;
+}
+
+static size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len)
{
size_t len = 0;
@@ -329,7 +355,7 @@ static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
return len;
}
-static void prov_complete(u16_t net_idx, u16_t addr)
+static void prov_complete(uint16_t net_idx, uint16_t addr)
{
printk("Local node provisioned, net_idx 0x%04x address 0x%04x\n",
net_idx, addr);
@@ -338,7 +364,8 @@ static void prov_complete(u16_t net_idx, u16_t addr)
net.dst = addr;
}
-static void prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem)
+static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
+ uint8_t num_elem)
{
printk("Node provisioned, net_idx 0x%04x address "
"0x%04x elements %d", net_idx, addr, num_elem);
@@ -370,7 +397,7 @@ static int output_string(const char *str)
}
static bt_mesh_input_action_t input_act;
-static u8_t input_size;
+static uint8_t input_size;
static int cmd_input_num(int argc, char *argv[])
{
@@ -438,7 +465,7 @@ struct shell_cmd_help cmd_input_str_help = {
NULL, "", NULL
};
-static int input(bt_mesh_input_action_t act, u8_t size)
+static int input(bt_mesh_input_action_t act, uint8_t size)
{
switch (act) {
case BT_MESH_ENTER_NUMBER:
@@ -482,9 +509,9 @@ static void link_close(bt_mesh_prov_bearer_t bearer)
printk("Provisioning link closed on %s\n", bearer2str(bearer));
}
-static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
+static uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
-static u8_t static_val[16];
+static uint8_t static_val[16];
static struct bt_mesh_prov prov = {
.uuid = dev_uuid,
@@ -535,7 +562,7 @@ struct shell_cmd_help cmd_static_oob_help = {
static int cmd_uuid(int argc, char *argv[])
{
- u8_t uuid[16];
+ uint8_t uuid[16];
size_t len;
if (argc < 2) {
@@ -561,12 +588,38 @@ struct shell_cmd_help cmd_uuid_help = {
static int cmd_reset(int argc, char *argv[])
{
- bt_mesh_reset();
- printk("Local node reset complete\n");
+ uint16_t addr;
+ if (argc < 2) {
+ return -EINVAL;
+ }
+
+ addr = strtoul(argv[1], NULL, 0);
+
+ if (addr == net.local) {
+ bt_mesh_reset();
+ printk("Local node reset complete");
+ } else {
+ int err;
+ bool reset = false;
+
+ err = bt_mesh_cfg_node_reset(net.net_idx, net.dst, &reset);
+ if (err) {
+ printk("Unable to send "
+ "Remote Node Reset (err %d)", err);
+ return 0;
+ }
+
+ printk("Remote node reset complete");
+ }
+
return 0;
}
-static u8_t str2u8(const char *str)
+struct shell_cmd_help cmd_reset_help = {
+ NULL, "", NULL
+};
+
+static uint8_t str2u8(const char *str)
{
if (isdigit(str[0])) {
return strtoul(str, NULL, 0);
@@ -632,7 +685,7 @@ static int cmd_poll(int argc, char *argv[])
return 0;
}
-static void lpn_cb(u16_t friend_addr, bool established)
+static void lpn_cb(uint16_t friend_addr, bool established)
{
if (established) {
printk("Friendship (as LPN) established to Friend 0x%04x\n",
@@ -785,8 +838,6 @@ static int cmd_net_send(int argc, char *argv[])
struct bt_mesh_net_tx tx = {
.ctx = &ctx,
.src = net.local,
- .xmit = bt_mesh_net_transmit_get(),
- .sub = bt_mesh_subnet_get(net.net_idx),
};
size_t len;
int err = 0;
@@ -796,12 +847,6 @@ static int cmd_net_send(int argc, char *argv[])
goto done;
}
- if (!tx.sub) {
- printk("No matching subnet for NetKey Index 0x%04x\n",
- net.net_idx);
- goto done;
- }
-
net_buf_simple_init(msg, 0);
len = hex2bin(argv[1], msg->om_data, net_buf_simple_tailroom(msg) - 4);
net_buf_simple_add(msg, len);
@@ -829,7 +874,7 @@ static int cmd_rpl_clear(int argc, char *argv[])
#if MYNEWT_VAL(BLE_MESH_LOW_POWER)
static int cmd_lpn_subscribe(int argc, char *argv[])
{
- u16_t address;
+ uint16_t address;
if (argc < 2) {
return -EINVAL;
@@ -850,7 +895,7 @@ struct shell_cmd_help cmd_lpn_subscribe_help = {
static int cmd_lpn_unsubscribe(int argc, char *argv[])
{
- u16_t address;
+ uint16_t address;
if (argc < 2) {
return -EINVAL;
@@ -913,7 +958,7 @@ struct shell_cmd_help cmd_iv_update_test_help = {
int cmd_timeout(int argc, char *argv[])
{
- s32_t timeout;
+ int32_t timeout;
if (argc < 2) {
timeout = bt_mesh_cfg_cli_timeout_get();
@@ -953,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(32);
- u8_t status, page = 0x00;
+ uint8_t status, page = 0x00;
int err = 0;
if (argc > 1) {
@@ -981,8 +1026,8 @@ static int cmd_get_comp(int argc, char *argv[])
printk("\tFeatures 0x%04x\n", net_buf_simple_pull_le16(comp));
while (comp->om_len > 4) {
- u8_t sig, vnd;
- u16_t loc;
+ uint8_t sig, vnd;
+ uint16_t loc;
int i;
loc = net_buf_simple_pull_le16(comp);
@@ -1003,7 +1048,7 @@ static int cmd_get_comp(int argc, char *argv[])
}
for (i = 0; i < sig; i++) {
- u16_t mod_id = net_buf_simple_pull_le16(comp);
+ uint16_t mod_id = net_buf_simple_pull_le16(comp);
printk("\t\t\t0x%04x\n", mod_id);
}
@@ -1015,8 +1060,8 @@ static int cmd_get_comp(int argc, char *argv[])
}
for (i = 0; i < vnd; i++) {
- u16_t cid = net_buf_simple_pull_le16(comp);
- u16_t mod_id = net_buf_simple_pull_le16(comp);
+ uint16_t cid = net_buf_simple_pull_le16(comp);
+ uint16_t mod_id = net_buf_simple_pull_le16(comp);
printk("\t\t\tCompany 0x%04x: 0x%04x\n", cid, mod_id);
}
@@ -1033,13 +1078,13 @@ struct shell_cmd_help cmd_get_comp_help = {
static int cmd_beacon(int argc, char *argv[])
{
- u8_t status;
+ uint8_t status;
int err;
if (argc < 2) {
err = bt_mesh_cfg_beacon_get(net.net_idx, net.dst, &status);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_beacon_set(net.net_idx, net.dst, val,
&status);
@@ -1055,19 +1100,49 @@ static int cmd_beacon(int argc, char *argv[])
return 0;
}
+static void print_unprovisioned_beacon(uint8_t uuid[16],
+ bt_mesh_prov_oob_info_t oob_info,
+ uint32_t *uri_hash)
+{
+ char uuid_hex_str[32 + 1];
+
+ bin2hex(uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
+
+ printk("UUID %s, OOB Info 0x%04x, URI Hash 0x%lx",
+ uuid_hex_str, oob_info,
+ (uri_hash == NULL ? 0 : *uri_hash));
+}
+
+static int cmd_beacon_listen(int argc, char *argv[])
+{
+ uint8_t val = str2u8(argv[1]);
+
+ if (val) {
+ prov.unprovisioned_beacon = print_unprovisioned_beacon;
+ } else {
+ prov.unprovisioned_beacon = NULL;
+ }
+
+ return 0;
+}
+
struct shell_cmd_help cmd_beacon_help = {
NULL, "[val: off, on]", NULL
};
+struct shell_cmd_help cmd_beacon_listen_help = {
+ NULL, "[val: off, on]", NULL
+};
+
static int cmd_ttl(int argc, char *argv[])
{
- u8_t ttl;
+ uint8_t ttl;
int err;
if (argc < 2) {
err = bt_mesh_cfg_ttl_get(net.net_idx, net.dst, &ttl);
} else {
- u8_t val = strtoul(argv[1], NULL, 0);
+ uint8_t val = strtoul(argv[1], NULL, 0);
err = bt_mesh_cfg_ttl_set(net.net_idx, net.dst, val, &ttl);
}
@@ -1088,13 +1163,13 @@ struct shell_cmd_help cmd_ttl_help = {
static int cmd_friend(int argc, char *argv[])
{
- u8_t frnd;
+ uint8_t frnd;
int err;
if (argc < 2) {
err = bt_mesh_cfg_friend_get(net.net_idx, net.dst, &frnd);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_friend_set(net.net_idx, net.dst, val, &frnd);
}
@@ -1115,13 +1190,13 @@ struct shell_cmd_help cmd_friend_help = {
static int cmd_gatt_proxy(int argc, char *argv[])
{
- u8_t proxy;
+ uint8_t proxy;
int err;
if (argc < 2) {
err = bt_mesh_cfg_gatt_proxy_get(net.net_idx, net.dst, &proxy);
} else {
- u8_t val = str2u8(argv[1]);
+ uint8_t val = str2u8(argv[1]);
err = bt_mesh_cfg_gatt_proxy_set(net.net_idx, net.dst, val,
&proxy);
@@ -1141,17 +1216,60 @@ struct shell_cmd_help cmd_gatt_proxy_help = {
NULL, "[val: off, on]", NULL
};
+static int cmd_net_transmit(int argc, char *argv[])
+{
+ uint8_t transmit;
+ int err;
+
+ if (argc < 2) {
+ err = bt_mesh_cfg_net_transmit_get(net.net_idx,
+ net.dst, &transmit);
+ } else {
+ if (argc != 3) {
+ printk("Wrong number of input arguments"
+ "(2 arguments are required)");
+ return -EINVAL;
+ }
+
+ uint8_t count, interval, new_transmit;
+
+ count = strtoul(argv[1], NULL, 0);
+ interval = strtoul(argv[2], NULL, 0);
+
+ new_transmit = BT_MESH_TRANSMIT(count, interval);
+
+ err = bt_mesh_cfg_net_transmit_set(net.net_idx, net.dst,
+ new_transmit, &transmit);
+ }
+
+ if (err) {
+ printk("Unable to send network transmit"
+ " Get/Set (err %d)", err);
+ return 0;
+ }
+
+ printk("Transmit 0x%02x (count %u interval %ums)",
+ transmit, BT_MESH_TRANSMIT_COUNT(transmit),
+ BT_MESH_TRANSMIT_INT(transmit));
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_transmit_help = {
+ NULL, "[ ]", NULL
+};
+
static int cmd_relay(int argc, char *argv[])
{
- u8_t relay, transmit;
+ uint8_t relay, transmit;
int err;
if (argc < 2) {
err = bt_mesh_cfg_relay_get(net.net_idx, net.dst, &relay,
&transmit);
} else {
- u8_t val = str2u8(argv[1]);
- u8_t count, interval, new_transmit;
+ uint8_t val = str2u8(argv[1]);
+ uint8_t count, interval, new_transmit;
if (val) {
if (argc > 2) {
@@ -1193,9 +1311,10 @@ struct shell_cmd_help cmd_relay_help = {
static int cmd_net_key_add(int argc, char *argv[])
{
- u8_t key_val[16];
- u16_t key_net_idx;
- u8_t status;
+ bool has_key_val = (argc > 2);
+ uint8_t key_val[16];
+ uint16_t key_net_idx;
+ uint8_t status;
int err;
if (argc < 2) {
@@ -1204,7 +1323,7 @@ static int cmd_net_key_add(int argc, char *argv[])
key_net_idx = strtoul(argv[1], NULL, 0);
- if (argc > 2) {
+ if (has_key_val) {
size_t len;
len = hex2bin(argv[3], key_val, sizeof(key_val));
@@ -1213,6 +1332,29 @@ static int cmd_net_key_add(int argc, char *argv[])
memcpy(key_val, default_key, sizeof(key_val));
}
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ struct bt_mesh_cdb_subnet *subnet;
+
+ subnet = bt_mesh_cdb_subnet_get(key_net_idx);
+ if (subnet) {
+ if (has_key_val) {
+ printk("Subnet 0x%03x already has a value", key_net_idx);
+ return 0;
+ }
+
+ memcpy(key_val, subnet->keys[0].net_key, 16);
+ } else {
+ subnet = bt_mesh_cdb_subnet_alloc(key_net_idx);
+ if (!subnet) {
+ printk("No space for subnet in cdb");
+ return 0;
+ }
+
+ memcpy(subnet->keys[0].net_key, key_val, 16);
+ bt_mesh_cdb_subnet_store(subnet);
+ }
+ }
+
err = bt_mesh_cfg_net_key_add(net.net_idx, net.dst, key_net_idx,
key_val, &status);
if (err) {
@@ -1233,11 +1375,67 @@ struct shell_cmd_help cmd_net_key_add_help = {
NULL, " [val]", NULL
};
+static int cmd_net_key_get(int argc, char *argv[])
+{
+ uint16_t keys[16];
+ size_t cnt;
+ int err, i;
+
+ cnt = ARRAY_SIZE(keys);
+
+ err = bt_mesh_cfg_net_key_get(net.net_idx, net.dst, keys, &cnt);
+ if (err) {
+ printk("Unable to send NetKeyGet (err %d)", err);
+ return 0;
+ }
+
+ printk("NetKeys known by 0x%04x:", net.dst);
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%03x", keys[i]);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_key_get_help = {
+ NULL, NULL, NULL
+};
+
+static int cmd_net_key_del(int argc, char *argv[])
+{
+ uint16_t key_net_idx;
+ uint8_t status;
+ int err;
+
+ key_net_idx = strtoul(argv[1], NULL, 0);
+
+ err = bt_mesh_cfg_net_key_del(net.net_idx, net.dst, key_net_idx,
+ &status);
+ if (err) {
+ printk("Unable to send NetKeyDel (err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("NetKeyDel failed with status 0x%02x",
+ status);
+ } else {
+ printk("NetKey 0x%03x deleted", key_net_idx);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_net_key_del_help = {
+ NULL, "", NULL
+};
+
static int cmd_app_key_add(int argc, char *argv[])
{
- u8_t key_val[16];
- u16_t key_net_idx, key_app_idx;
- u8_t status;
+ uint8_t key_val[16];
+ uint16_t key_net_idx, key_app_idx;
+ bool has_key_val = (argc > 3);
+ uint8_t status;
int err;
if (argc < 3) {
@@ -1247,7 +1445,7 @@ static int cmd_app_key_add(int argc, char *argv[])
key_net_idx = strtoul(argv[1], NULL, 0);
key_app_idx = strtoul(argv[2], NULL, 0);
- if (argc > 3) {
+ if (has_key_val) {
size_t len;
len = hex2bin(argv[3], key_val, sizeof(key_val));
@@ -1256,6 +1454,30 @@ static int cmd_app_key_add(int argc, char *argv[])
memcpy(key_val, default_key, sizeof(key_val));
}
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ struct bt_mesh_cdb_app_key *app_key;
+
+ app_key = bt_mesh_cdb_app_key_get(key_app_idx);
+ if (app_key) {
+ if (has_key_val) {
+ printk("App key 0x%03x already has a value", key_app_idx);
+ return 0;
+ }
+
+ memcpy(key_val, app_key->keys[0].app_key, 16);
+ } else {
+ app_key = bt_mesh_cdb_app_key_alloc(key_net_idx,
+ key_app_idx);
+ if (!app_key) {
+ printk("No space for app key in cdb");
+ return 0;
+ }
+
+ memcpy(app_key->keys[0].app_key, key_val, 16);
+ bt_mesh_cdb_app_key_store(app_key);
+ }
+ }
+
err = bt_mesh_cfg_app_key_add(net.net_idx, net.dst, key_net_idx,
key_app_idx, key_val, &status);
if (err) {
@@ -1277,10 +1499,83 @@ struct shell_cmd_help cmd_app_key_add_help = {
NULL, " [val]", NULL
};
+static int cmd_app_key_get(int argc, char *argv[])
+{
+ uint16_t net_idx;
+ uint16_t keys[16];
+ size_t cnt;
+ uint8_t status;
+ int err, i;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+ cnt = ARRAY_SIZE(keys);
+
+ err = bt_mesh_cfg_app_key_get(net.net_idx, net.dst, net_idx, &status,
+ keys, &cnt);
+ if (err) {
+ printk("Unable to send AppKeyGet (err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("AppKeyGet failed with status 0x%02x",
+ status);
+ return 0;
+ }
+
+ printk(
+ "AppKeys for NetKey 0x%03x known by 0x%04x:", net_idx,
+ net.dst);
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%03x", keys[i]);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_app_key_get_help = {
+ NULL, "", NULL
+};
+
+static int cmd_app_key_del(int argc, char *argv[])
+{
+ uint16_t key_net_idx, key_app_idx;
+ uint8_t status;
+ int err;
+
+ if (argc < 3) {
+ return -EINVAL;
+ }
+
+ key_net_idx = strtoul(argv[1], NULL, 0);
+ key_app_idx = strtoul(argv[2], NULL, 0);
+
+ err = bt_mesh_cfg_app_key_del(net.net_idx, net.dst, key_net_idx,
+ key_app_idx, &status);
+ if (err) {
+ printk("Unable to send App Key del(err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("AppKeyDel failed with status 0x%02x",
+ status);
+ } else {
+ printk("AppKey deleted, NetKeyIndex 0x%04x "
+ "AppKeyIndex 0x%04x", key_net_idx, key_app_idx);
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_app_key_del_help = {
+ NULL, " ", NULL
+};
+
static int cmd_mod_app_bind(int argc, char *argv[])
{
- u16_t elem_addr, mod_app_idx, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1319,10 +1614,107 @@ struct shell_cmd_help cmd_mod_app_bind_help = {
NULL, " [Company ID]", NULL
};
+static int cmd_mod_app_unbind(int argc, char *argv[])
+{
+ uint16_t elem_addr, mod_app_idx, mod_id, cid;
+ uint8_t status;
+ int err;
+
+ if (argc < 4) {
+ return -EINVAL;
+ }
+
+ elem_addr = strtoul(argv[1], NULL, 0);
+ mod_app_idx = strtoul(argv[2], NULL, 0);
+ mod_id = strtoul(argv[3], NULL, 0);
+
+ if (argc > 4) {
+ cid = strtoul(argv[4], NULL, 0);
+ err = bt_mesh_cfg_mod_app_unbind_vnd(net.net_idx, net.dst,
+ elem_addr, mod_app_idx,
+ mod_id, cid, &status);
+ } else {
+ err = bt_mesh_cfg_mod_app_unbind(net.net_idx, net.dst,
+ elem_addr, mod_app_idx, mod_id, &status);
+ }
+
+ if (err) {
+ printk("Unable to send Model App Unbind (err %d)",
+ err);
+ return 0;
+ }
+
+ if (status) {
+ printk("Model App Unbind failed with status 0x%02x",
+ status);
+ } else {
+ printk("AppKey successfully unbound");
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_mod_app_unbind_help = {
+ NULL, " [Company ID]", NULL
+};
+
+static int cmd_mod_app_get(int argc,
+ char *argv[])
+{
+ uint16_t elem_addr, mod_id, cid;
+ uint16_t apps[16];
+ uint8_t status;
+ size_t cnt;
+ int err, i;
+
+ elem_addr = strtoul(argv[1], NULL, 0);
+ mod_id = strtoul(argv[2], NULL, 0);
+ cnt = ARRAY_SIZE(apps);
+
+ if (argc > 3) {
+ cid = strtoul(argv[3], NULL, 0);
+ err = bt_mesh_cfg_mod_app_get_vnd(net.net_idx, net.dst,
+ elem_addr, mod_id, cid,
+ &status, apps, &cnt);
+ } else {
+ err = bt_mesh_cfg_mod_app_get(net.net_idx, net.dst, elem_addr,
+ mod_id, &status, apps, &cnt);
+ }
+
+ if (err) {
+ printk("Unable to send Model App Get (err %d)",
+ err);
+ return 0;
+ }
+
+ if (status) {
+ printk("Model App Get failed with status 0x%02x",
+ status);
+ } else {
+ printk(
+ "Apps bound to Element 0x%04x, Model 0x%04x %s:",
+ elem_addr, mod_id, argc > 3 ? argv[3] : "(SIG)");
+
+ if (!cnt) {
+ printk("\tNone.");
+ }
+
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%04x", apps[i]);
+ }
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_mod_app_get_help = {
+ NULL, " [Company ID]", NULL
+};
+
static int cmd_mod_sub_add(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1364,8 +1756,8 @@ struct shell_cmd_help cmd_mod_sub_add_help = {
static int cmd_mod_sub_del(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t status;
int err;
if (argc < 4) {
@@ -1408,9 +1800,9 @@ struct shell_cmd_help cmd_mod_sub_del_help = {
static int cmd_mod_sub_add_va(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t label[16];
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t label[16];
+ uint8_t status;
size_t len;
int err;
@@ -1458,9 +1850,9 @@ struct shell_cmd_help cmd_mod_sub_add_va_help = {
static int cmd_mod_sub_del_va(int argc, char *argv[])
{
- u16_t elem_addr, sub_addr, mod_id, cid;
- u8_t label[16];
- u8_t status;
+ uint16_t elem_addr, sub_addr, mod_id, cid;
+ uint8_t label[16];
+ uint8_t status;
size_t len;
int err;
@@ -1507,10 +1899,64 @@ struct shell_cmd_help cmd_mod_sub_del_va_help = {
NULL, " [Company ID]", NULL
};
-static int mod_pub_get(u16_t addr, u16_t mod_id, u16_t cid)
+static int cmd_mod_sub_get(int argc,
+ char *argv[])
+{
+ uint16_t elem_addr, mod_id, cid;
+ uint16_t subs[16];
+ uint8_t status;
+ size_t cnt;
+ int err, i;
+
+ elem_addr = strtoul(argv[1], NULL, 0);
+ mod_id = strtoul(argv[2], NULL, 0);
+ cnt = ARRAY_SIZE(subs);
+
+ if (argc > 3) {
+ cid = strtoul(argv[3], NULL, 0);
+ err = bt_mesh_cfg_mod_sub_get_vnd(net.net_idx, net.dst,
+ elem_addr, mod_id, cid,
+ &status, subs, &cnt);
+ } else {
+ err = bt_mesh_cfg_mod_sub_get(net.net_idx, net.dst, elem_addr,
+ mod_id, &status, subs, &cnt);
+ }
+
+ if (err) {
+ printk("Unable to send Model Subscription Get "
+ "(err %d)", err);
+ return 0;
+ }
+
+ if (status) {
+ printk("Model Subscription Get failed with "
+ "status 0x%02x", status);
+ } else {
+ printk(
+ "Model Subscriptions for Element 0x%04x, "
+ "Model 0x%04x %s:",
+ elem_addr, mod_id, argc > 3 ? argv[3] : "(SIG)");
+
+ if (!cnt) {
+ printk("\tNone.");
+ }
+
+ for (i = 0; i < cnt; i++) {
+ printk("\t0x%04x", subs[i]);
+ }
+ }
+
+ return 0;
+}
+
+struct shell_cmd_help cmd_mod_sub_get_help = {
+ NULL, " [Company ID]", NULL
+};
+
+static int mod_pub_get(uint16_t addr, uint16_t mod_id, uint16_t cid)
{
struct bt_mesh_cfg_mod_pub pub;
- u8_t status;
+ uint8_t status;
int err;
if (cid == CID_NVAL) {
@@ -1547,11 +1993,11 @@ static int mod_pub_get(u16_t addr, u16_t mod_id, u16_t cid)
return 0;
}
-static int mod_pub_set(u16_t addr, u16_t mod_id, u16_t cid, char *argv[])
+static int mod_pub_set(uint16_t addr, uint16_t mod_id, uint16_t cid, char *argv[])
{
struct bt_mesh_cfg_mod_pub pub;
- u8_t status, count;
- u16_t interval;
+ uint8_t status, count;
+ uint16_t interval;
int err;
pub.addr = strtoul(argv[0], NULL, 0);
@@ -1599,7 +2045,7 @@ static int mod_pub_set(u16_t addr, u16_t mod_id, u16_t cid, char *argv[])
static int cmd_mod_pub(int argc, char *argv[])
{
- u16_t addr, mod_id, cid;
+ uint16_t addr, mod_id, cid;
if (argc < 3) {
return -EINVAL;
@@ -1651,7 +2097,7 @@ static void hb_sub_print(struct bt_mesh_cfg_hb_sub *sub)
static int hb_sub_get(int argc, char *argv[])
{
struct bt_mesh_cfg_hb_sub sub;
- u8_t status;
+ uint8_t status;
int err;
err = bt_mesh_cfg_hb_sub_get(net.net_idx, net.dst, &sub, &status);
@@ -1673,7 +2119,7 @@ static int hb_sub_get(int argc, char *argv[])
static int hb_sub_set(int argc, char *argv[])
{
struct bt_mesh_cfg_hb_sub sub;
- u8_t status;
+ uint8_t status;
int err;
sub.src = strtoul(argv[1], NULL, 0);
@@ -1716,7 +2162,7 @@ struct shell_cmd_help cmd_hb_sub_help = {
static int hb_pub_get(int argc, char *argv[])
{
struct bt_mesh_cfg_hb_pub pub;
- u8_t status;
+ uint8_t status;
int err;
err = bt_mesh_cfg_hb_pub_get(net.net_idx, net.dst, &pub, &status);
@@ -1743,7 +2189,7 @@ static int hb_pub_get(int argc, char *argv[])
static int hb_pub_set(int argc, char *argv[])
{
struct bt_mesh_cfg_hb_pub pub;
- u8_t status;
+ uint8_t status;
int err;
pub.dst = strtoul(argv[1], NULL, 0);
@@ -1788,7 +2234,7 @@ struct shell_cmd_help cmd_hb_pub_help = {
#endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
-#if MYNEWT_VAL(BLE_MESH_PROV)
+#if MYNEWT_VAL(BLE_MESH_PROV_DEVICE)
static int cmd_pb(bt_mesh_prov_bearer_t bearer, int argc, char *argv[])
{
int err;
@@ -1834,10 +2280,10 @@ static int cmd_pb_adv(int argc, char *argv[])
#if MYNEWT_VAL(BLE_MESH_PROVISIONER)
static int cmd_provision_adv(int argc, char *argv[])
{
- u8_t uuid[16];
- u8_t attention_duration;
- u16_t net_idx;
- u16_t addr;
+ uint8_t uuid[16];
+ uint8_t attention_duration;
+ uint16_t net_idx;
+ uint16_t addr;
size_t len;
int err;
@@ -1872,8 +2318,9 @@ static int cmd_pb_gatt(int argc, char *argv[])
static int cmd_provision(int argc, char *argv[])
{
- u16_t net_idx, addr;
- u32_t iv_index;
+ const uint8_t *net_key = default_key;
+ uint16_t net_idx, addr;
+ uint32_t iv_index;
int err;
if (argc < 3) {
@@ -1889,7 +2336,19 @@ static int cmd_provision(int argc, char *argv[])
iv_index = 0;
}
- err = bt_mesh_provision(default_key, net_idx, 0, iv_index, addr,
+ if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
+ const struct bt_mesh_cdb_subnet *sub;
+
+ sub = bt_mesh_cdb_subnet_get(net_idx);
+ if (!sub) {
+ printk("No cdb entry for subnet 0x%03x", net_idx);
+ return 0;
+ }
+
+ net_key = sub->keys[sub->kr_flag].net_key;
+ }
+
+ err = bt_mesh_provision(net_key, net_idx, 0, iv_index, addr,
default_key);
if (err) {
printk("Provisioning failed (err %d)\n", err);
@@ -1906,10 +2365,10 @@ struct shell_cmd_help cmd_provision_help = {
static int cmd_fault_get(int argc, char *argv[])
{
- u8_t faults[32];
+ uint8_t faults[32];
size_t fault_count;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
int err;
if (argc < 2) {
@@ -1919,8 +2378,8 @@ static int cmd_fault_get(int argc, char *argv[])
cid = strtoul(argv[1], NULL, 0);
fault_count = sizeof(faults);
- err = bt_mesh_health_fault_get(net.net_idx, net.dst, net.app_idx, cid,
- &test_id, faults, &fault_count);
+ err = bt_mesh_health_fault_get(net.dst, net.app_idx, cid, &test_id,
+ faults, &fault_count);
if (err) {
printk("Failed to send Health Fault Get (err %d)\n", err);
} else {
@@ -1936,10 +2395,10 @@ struct shell_cmd_help cmd_fault_get_help = {
static int cmd_fault_clear(int argc, char *argv[])
{
- u8_t faults[32];
+ uint8_t faults[32];
size_t fault_count;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
int err;
if (argc < 2) {
@@ -1949,8 +2408,8 @@ static int cmd_fault_clear(int argc, char *argv[])
cid = strtoul(argv[1], NULL, 0);
fault_count = sizeof(faults);
- err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
- cid, &test_id, faults, &fault_count);
+ err = bt_mesh_health_fault_clear(net.dst, net.app_idx, cid,
+ &test_id, faults, &fault_count);
if (err) {
printk("Failed to send Health Fault Clear (err %d)\n", err);
} else {
@@ -1966,7 +2425,7 @@ struct shell_cmd_help cmd_fault_clear_help = {
static int cmd_fault_clear_unack(int argc, char *argv[])
{
- u16_t cid;
+ uint16_t cid;
int err;
if (argc < 2) {
@@ -1975,8 +2434,8 @@ static int cmd_fault_clear_unack(int argc, char *argv[])
cid = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
- cid, NULL, NULL, NULL);
+ err = bt_mesh_health_fault_clear(net.dst, net.app_idx, cid,
+ NULL, NULL, NULL);
if (err) {
printk("Health Fault Clear Unacknowledged failed (err %d)\n",
err);
@@ -1991,10 +2450,10 @@ struct shell_cmd_help cmd_fault_clear_unack_help = {
static int cmd_fault_test(int argc, char *argv[])
{
- u8_t faults[32];
+ uint8_t faults[32];
size_t fault_count;
- u8_t test_id;
- u16_t cid;
+ uint8_t test_id;
+ uint16_t cid;
int err;
if (argc < 3) {
@@ -2005,8 +2464,8 @@ static int cmd_fault_test(int argc, char *argv[])
test_id = strtoul(argv[2], NULL, 0);
fault_count = sizeof(faults);
- err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
- cid, test_id, faults, &fault_count);
+ err = bt_mesh_health_fault_test(net.dst, net.app_idx, cid,
+ test_id, faults, &fault_count);
if (err) {
printk("Failed to send Health Fault Test (err %d)\n", err);
} else {
@@ -2022,8 +2481,8 @@ struct shell_cmd_help cmd_fault_test_help = {
static int cmd_fault_test_unack(int argc, char *argv[])
{
- u16_t cid;
- u8_t test_id;
+ uint16_t cid;
+ uint8_t test_id;
int err;
if (argc < 3) {
@@ -2033,8 +2492,8 @@ static int cmd_fault_test_unack(int argc, char *argv[])
cid = strtoul(argv[1], NULL, 0);
test_id = strtoul(argv[2], NULL, 0);
- err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
- cid, test_id, NULL, NULL);
+ err = bt_mesh_health_fault_test(net.dst, net.app_idx, cid,
+ test_id, NULL, NULL);
if (err) {
printk("Health Fault Test Unacknowledged failed (err %d)\n",
err);
@@ -2049,11 +2508,10 @@ struct shell_cmd_help cmd_fault_test_unack_help = {
static int cmd_period_get(int argc, char *argv[])
{
- u8_t divisor;
+ uint8_t divisor;
int err;
- err = bt_mesh_health_period_get(net.net_idx, net.dst, net.app_idx,
- &divisor);
+ err = bt_mesh_health_period_get(net.dst, net.app_idx, &divisor);
if (err) {
printk("Failed to send Health Period Get (err %d)\n", err);
} else {
@@ -2065,7 +2523,7 @@ static int cmd_period_get(int argc, char *argv[])
static int cmd_period_set(int argc, char *argv[])
{
- u8_t divisor, updated_divisor;
+ uint8_t divisor, updated_divisor;
int err;
if (argc < 2) {
@@ -2074,8 +2532,8 @@ static int cmd_period_set(int argc, char *argv[])
divisor = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
- divisor, &updated_divisor);
+ err = bt_mesh_health_period_set(net.dst, net.app_idx, divisor,
+ &updated_divisor);
if (err) {
printk("Failed to send Health Period Set (err %d)\n", err);
} else {
@@ -2091,7 +2549,7 @@ struct shell_cmd_help cmd_period_set_help = {
static int cmd_period_set_unack(int argc, char *argv[])
{
- u8_t divisor;
+ uint8_t divisor;
int err;
if (argc < 2) {
@@ -2100,8 +2558,7 @@ static int cmd_period_set_unack(int argc, char *argv[])
divisor = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
- divisor, NULL);
+ err = bt_mesh_health_period_set(net.dst, net.app_idx, divisor, NULL);
if (err) {
printk("Failed to send Health Period Set (err %d)\n", err);
}
@@ -2115,11 +2572,11 @@ struct shell_cmd_help cmd_period_set_unack_help = {
static int cmd_attention_get(int argc, char *argv[])
{
- u8_t attention;
+ uint8_t attention;
int err;
- err = bt_mesh_health_attention_get(net.net_idx, net.dst, net.app_idx,
- &attention);
+ err = bt_mesh_health_attention_get(net.dst, net.app_idx,
+ &attention);
if (err) {
printk("Failed to send Health Attention Get (err %d)\n", err);
} else {
@@ -2131,7 +2588,7 @@ static int cmd_attention_get(int argc, char *argv[])
static int cmd_attention_set(int argc, char *argv[])
{
- u8_t attention, updated_attention;
+ uint8_t attention, updated_attention;
int err;
if (argc < 2) {
@@ -2140,8 +2597,8 @@ static int cmd_attention_set(int argc, char *argv[])
attention = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
- attention, &updated_attention);
+ err = bt_mesh_health_attention_set(net.dst, net.app_idx, attention,
+ &updated_attention);
if (err) {
printk("Failed to send Health Attention Set (err %d)\n", err);
} else {
@@ -2157,7 +2614,7 @@ struct shell_cmd_help cmd_attention_set_help = {
static int cmd_attention_set_unack(int argc, char *argv[])
{
- u8_t attention;
+ uint8_t attention;
int err;
if (argc < 2) {
@@ -2166,8 +2623,8 @@ static int cmd_attention_set_unack(int argc, char *argv[])
attention = strtoul(argv[1], NULL, 0);
- err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
- attention, NULL);
+ err = bt_mesh_health_attention_set(net.dst, net.app_idx, attention,
+ NULL);
if (err) {
printk("Failed to send Health Attention Set (err %d)\n", err);
}
@@ -2183,8 +2640,8 @@ struct shell_cmd_help cmd_attention_set_unack_help = {
static int cmd_add_fault(int argc, char *argv[])
{
- u8_t fault_id;
- u8_t i;
+ uint8_t fault_id;
+ uint8_t i;
if (argc < 2) {
return -EINVAL;
@@ -2230,8 +2687,8 @@ struct shell_cmd_help cmd_add_fault_help = {
static int cmd_del_fault(int argc, char *argv[])
{
- u8_t fault_id;
- u8_t i;
+ uint8_t fault_id;
+ uint8_t i;
if (argc < 2) {
memset(cur_faults, 0, sizeof(cur_faults));
@@ -2262,10 +2719,337 @@ struct shell_cmd_help cmd_del_fault_help = {
NULL, "[Fault ID]", NULL
};
+#if MYNEWT_VAL(BLE_MESH_CDB)
+struct shell_cmd_help cmd_cdb_create_help = {
+ NULL, "[NetKey]", NULL
+};
+struct shell_cmd_help cmd_cdb_clear_help = {
+ NULL, NULL, NULL
+};
+struct shell_cmd_help cmd_cdb_show_help = {
+ NULL, NULL, NULL
+};
+struct shell_cmd_help cmd_cdb_node_add_help = {
+ NULL, " "
+ " [DevKey]", NULL
+};
+struct shell_cmd_help cmd_cdb_node_del_help = {
+ NULL, "", NULL
+};
+struct shell_cmd_help cmd_cdb_subnet_add_help = {
+ NULL, " []", NULL
+};
+struct shell_cmd_help cmd_cdb_subnet_del_help = {
+ NULL, "", NULL
+};
+struct shell_cmd_help cmd_cdb_app_key_add_help = {
+ NULL, " []", NULL
+};
+struct shell_cmd_help cmd_cdb_app_key_del_help = {
+ NULL, "", NULL
+};
+
+static int cmd_cdb_create(int argc, char *argv[])
+{
+ uint8_t net_key[16];
+ size_t len;
+ int err;
+
+ if (argc < 2) {
+ bt_rand(net_key, 16);
+ } else {
+ len = hex2bin(argv[1], net_key, sizeof(net_key));
+ memset(net_key + len, 0, sizeof(net_key) - len);
+ }
+
+ err = bt_mesh_cdb_create(net_key);
+ if (err < 0) {
+ printk("Failed to create CDB (err %d)", err);
+ }
+
+ return 0;
+}
+
+static int cmd_cdb_clear(int argc, char *argv[])
+{
+ bt_mesh_cdb_clear();
+
+ printk("Cleared CDB");
+
+ return 0;
+}
+
+static void cdb_print_nodes(void)
+{
+ char key_hex_str[32 + 1], uuid_hex_str[32 + 1];
+ struct bt_mesh_cdb_node *node;
+ int i, total = 0;
+ bool configured;
+
+ printk("Address Elements Flags %-32s DevKey", "UUID");
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
+ node = &bt_mesh_cdb.nodes[i];
+ if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
+ continue;
+ }
+
+ configured = atomic_test_bit(node->flags,
+ BT_MESH_CDB_NODE_CONFIGURED);
+
+ total++;
+ bin2hex(node->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
+ bin2hex(node->dev_key, 16, key_hex_str, sizeof(key_hex_str));
+ printk("0x%04x %-8d %-5s %s %s", node->addr,
+ node->num_elem, configured ? "C" : "-",
+ uuid_hex_str, key_hex_str);
+ }
+
+ printk("> Total nodes: %d", total);
+}
+
+static void cdb_print_subnets(void)
+{
+ struct bt_mesh_cdb_subnet *subnet;
+ char key_hex_str[32 + 1];
+ int i, total = 0;
+
+ printk("NetIdx NetKey");
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
+ subnet = &bt_mesh_cdb.subnets[i];
+ if (subnet->net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ total++;
+ bin2hex(subnet->keys[0].net_key, 16, key_hex_str,
+ sizeof(key_hex_str));
+ printk("0x%03x %s", subnet->net_idx,
+ key_hex_str);
+ }
+
+ printk("> Total subnets: %d", total);
+}
+
+static void cdb_print_app_keys(void)
+{
+ struct bt_mesh_cdb_app_key *app_key;
+ char key_hex_str[32 + 1];
+ int i, total = 0;
+
+ printk("NetIdx AppIdx AppKey");
+
+ for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
+ app_key = &bt_mesh_cdb.app_keys[i];
+ if (app_key->net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ total++;
+ bin2hex(app_key->keys[0].app_key, 16, key_hex_str,
+ sizeof(key_hex_str));
+ printk("0x%03x 0x%03x %s",
+ app_key->net_idx, app_key->app_idx, key_hex_str);
+ }
+
+ printk("> Total app-keys: %d", total);
+}
+
+static int cmd_cdb_show(int argc, char *argv[])
+{
+ if (!atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID)) {
+ printk("No valid networks");
+ return 0;
+ }
+
+ printk("Mesh Network Information");
+ printk("========================");
+
+ cdb_print_nodes();
+ printk("---");
+ cdb_print_subnets();
+ printk("---");
+ cdb_print_app_keys();
+
+ return 0;
+}
+
+static int cmd_cdb_node_add(int argc, char *argv[])
+{
+ struct bt_mesh_cdb_node *node;
+ uint8_t uuid[16], dev_key[16];
+ uint16_t addr, net_idx;
+ uint8_t num_elem;
+ size_t len;
+
+ len = hex2bin(argv[1], uuid, sizeof(uuid));
+ memset(uuid + len, 0, sizeof(uuid) - len);
+
+ addr = strtoul(argv[2], NULL, 0);
+ num_elem = strtoul(argv[3], NULL, 0);
+ net_idx = strtoul(argv[4], NULL, 0);
+
+ if (argc < 6) {
+ bt_rand(dev_key, 16);
+ } else {
+ len = hex2bin(argv[5], dev_key, sizeof(dev_key));
+ memset(dev_key + len, 0, sizeof(dev_key) - len);
+ }
+
+ node = bt_mesh_cdb_node_alloc(uuid, addr, num_elem, net_idx);
+ if (node == NULL) {
+ printk("Failed to allocate node");
+ return 0;
+ }
+
+ memcpy(node->dev_key, dev_key, 16);
+
+ if (IS_ENABLED(CONFIG_SETTINGS)) {
+ bt_mesh_store_cdb_node(node);
+ }
+
+ printk("Added node 0x%04x", addr);
+
+ return 0;
+}
+
+static int cmd_cdb_node_del(int argc, char *argv[])
+{
+ struct bt_mesh_cdb_node *node;
+ uint16_t addr;
+
+ addr = strtoul(argv[1], NULL, 0);
+
+ node = bt_mesh_cdb_node_get(addr);
+ if (node == NULL) {
+ printk("No node with address 0x%04x", addr);
+ return 0;
+ }
+
+ bt_mesh_cdb_node_del(node, true);
+
+ printk("Deleted node 0x%04x", addr);
+
+ return 0;
+}
+
+static int cmd_cdb_subnet_add(int argc,
+ char *argv[])
+{
+ struct bt_mesh_cdb_subnet *sub;
+ uint8_t net_key[16];
+ uint16_t net_idx;
+ size_t len;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+
+ if (argc < 3) {
+ bt_rand(net_key, 16);
+ } else {
+ len = hex2bin(argv[2], net_key, sizeof(net_key));
+ memset(net_key + len, 0, sizeof(net_key) - len);
+ }
+
+ sub = bt_mesh_cdb_subnet_alloc(net_idx);
+ if (sub == NULL) {
+ printk("Could not add subnet");
+ return 0;
+ }
+
+ memcpy(sub->keys[0].net_key, net_key, 16);
+
+ if (IS_ENABLED(CONFIG_SETTINGS)) {
+ bt_mesh_store_cdb_subnet(sub);
+ }
+
+ printk("Added Subnet 0x%03x", net_idx);
+
+ return 0;
+}
+
+static int cmd_cdb_subnet_del(int argc,
+ char *argv[])
+{
+ struct bt_mesh_cdb_subnet *sub;
+ uint16_t net_idx;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+
+ sub = bt_mesh_cdb_subnet_get(net_idx);
+ if (sub == NULL) {
+ printk("No subnet with NetIdx 0x%03x", net_idx);
+ return 0;
+ }
+
+ bt_mesh_cdb_subnet_del(sub, true);
+
+ printk("Deleted subnet 0x%03x", net_idx);
+
+ return 0;
+}
+
+static int cmd_cdb_app_key_add(int argc,
+ char *argv[])
+{
+ struct bt_mesh_cdb_app_key *key;
+ uint16_t net_idx, app_idx;
+ uint8_t app_key[16];
+ size_t len;
+
+ net_idx = strtoul(argv[1], NULL, 0);
+ app_idx = strtoul(argv[2], NULL, 0);
+
+ if (argc < 4) {
+ bt_rand(app_key, 16);
+ } else {
+ len = hex2bin(argv[3], app_key, sizeof(app_key));
+ memset(app_key + len, 0, sizeof(app_key) - len);
+ }
+
+ key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx);
+ if (key == NULL) {
+ printk("Could not add AppKey");
+ return 0;
+ }
+
+ memcpy(key->keys[0].app_key, app_key, 16);
+
+ if (IS_ENABLED(CONFIG_SETTINGS)) {
+ bt_mesh_store_cdb_app_key(key);
+ }
+
+ printk("Added AppKey 0x%03x", app_idx);
+
+ return 0;
+}
+
+static int cmd_cdb_app_key_del(int argc,
+ char *argv[])
+{
+ struct bt_mesh_cdb_app_key *key;
+ uint16_t app_idx;
+
+ app_idx = strtoul(argv[1], NULL, 0);
+
+ key = bt_mesh_cdb_app_key_get(app_idx);
+ if (key == NULL) {
+ printk("No AppKey 0x%03x", app_idx);
+ return 0;
+ }
+
+ bt_mesh_cdb_app_key_del(key, true);
+
+ printk("Deleted AppKey 0x%03x", app_idx);
+
+ return 0;
+}
+#endif
+
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
static int cmd_gen_onoff_get(int argc, char *argv[])
{
- u8_t state;
+ uint8_t state;
int err;
err = bt_mesh_gen_onoff_get(net.net_idx, net.dst, net.app_idx,
@@ -2281,8 +3065,8 @@ static int cmd_gen_onoff_get(int argc, char *argv[])
static int cmd_gen_onoff_set(int argc, char *argv[])
{
- u8_t state;
- u8_t val;
+ uint8_t state;
+ uint8_t val;
int err;
if (argc < 2) {
@@ -2308,7 +3092,7 @@ struct shell_cmd_help cmd_gen_onoff_set_help = {
static int cmd_gen_onoff_set_unack(int argc, char *argv[])
{
- u8_t val;
+ uint8_t val;
int err;
if (argc < 2) {
@@ -2332,7 +3116,7 @@ struct shell_cmd_help cmd_gen_onoff_set_unack_help = {
static int cmd_gen_level_get(int argc, char *argv[])
{
- s16_t state;
+ int16_t state;
int err;
err = bt_mesh_gen_level_get(net.net_idx, net.dst, net.app_idx,
@@ -2348,15 +3132,15 @@ static int cmd_gen_level_get(int argc, char *argv[])
static int cmd_gen_level_set(int argc, char *argv[])
{
- s16_t state;
- s16_t val;
+ int16_t state;
+ int16_t val;
int err;
if (argc < 2) {
return -EINVAL;
}
- val = (s16_t)strtoul(argv[1], NULL, 0);
+ val = (int16_t)strtoul(argv[1], NULL, 0);
err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
val, &state);
@@ -2375,14 +3159,14 @@ struct shell_cmd_help cmd_gen_level_set_help = {
static int cmd_gen_level_set_unack(int argc, char *argv[])
{
- s16_t val;
+ int16_t val;
int err;
if (argc < 2) {
return -EINVAL;
}
- val = (s16_t)strtoul(argv[1], NULL, 0);
+ val = (int16_t)strtoul(argv[1], NULL, 0);
err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
val, NULL);
@@ -2480,7 +3264,7 @@ static const struct shell_cmd mesh_commands[] = {
{
.sc_cmd = "reset",
.sc_cmd_func = cmd_reset,
- .help = NULL,
+ .help = &cmd_reset_help,
},
{
.sc_cmd = "uuid",
@@ -2606,6 +3390,11 @@ static const struct shell_cmd mesh_commands[] = {
.sc_cmd_func = cmd_beacon,
.help = &cmd_beacon_help,
},
+ {
+ .sc_cmd = "beacon-listen",
+ .sc_cmd_func = cmd_beacon_listen,
+ .help = &cmd_beacon_listen_help,
+ },
{
.sc_cmd = "ttl",
.sc_cmd_func = cmd_ttl,
@@ -2631,16 +3420,51 @@ static const struct shell_cmd mesh_commands[] = {
.sc_cmd_func = cmd_net_key_add,
.help = &cmd_net_key_add_help,
},
+ {
+ .sc_cmd = "net-key-get",
+ .sc_cmd_func = cmd_net_key_get,
+ .help = &cmd_net_key_get_help,
+ },
+ {
+ .sc_cmd = "net-key-del",
+ .sc_cmd_func = cmd_net_key_del,
+ .help = &cmd_net_key_del_help,
+ },
{
.sc_cmd = "app-key-add",
.sc_cmd_func = cmd_app_key_add,
.help = &cmd_app_key_add_help,
},
+ {
+ .sc_cmd = "app-key-del",
+ .sc_cmd_func = cmd_app_key_del,
+ .help = &cmd_app_key_del_help,
+ },
+ {
+ .sc_cmd = "app-key-get",
+ .sc_cmd_func = cmd_app_key_get,
+ .help = &cmd_app_key_get_help,
+ },
+ {
+ .sc_cmd = "net-transmit-param",
+ .sc_cmd_func = cmd_net_transmit,
+ .help = &cmd_net_transmit_help,
+ },
{
.sc_cmd = "mod-app-bind",
.sc_cmd_func = cmd_mod_app_bind,
.help = &cmd_mod_app_bind_help,
},
+ {
+ .sc_cmd = "mod-app-get",
+ .sc_cmd_func = cmd_mod_app_get,
+ .help = &cmd_mod_app_get_help,
+ },
+ {
+ .sc_cmd = "mod-app-unbind",
+ .sc_cmd_func = cmd_mod_app_unbind,
+ .help = &cmd_mod_app_unbind_help,
+ },
{
.sc_cmd = "mod-pub",
.sc_cmd_func = cmd_mod_pub,
@@ -2661,6 +3485,11 @@ static const struct shell_cmd mesh_commands[] = {
.sc_cmd_func = cmd_mod_sub_add_va,
.help = &cmd_mod_sub_add_va_help,
},
+ {
+ .sc_cmd = "mod-sub-get",
+ .sc_cmd_func = cmd_mod_sub_get,
+ .help = &cmd_mod_sub_get_help,
+ },
{
.sc_cmd = "mod-sub-del-va",
.sc_cmd_func = cmd_mod_sub_del_va,
@@ -2749,6 +3578,46 @@ static const struct shell_cmd mesh_commands[] = {
.help = &cmd_del_fault_help,
},
+#if MYNEWT_VAL(BLE_MESH_CDB)
+ {
+ .sc_cmd = "cdb-create",
+ .sc_cmd_func = cmd_cdb_create,
+ .help = &cmd_cdb_create_help,
+ },{
+ .sc_cmd = "cdb-clear",
+ .sc_cmd_func = cmd_cdb_clear,
+ .help = &cmd_cdb_clear_help,
+ },{
+ .sc_cmd = "cdb-show",
+ .sc_cmd_func = cmd_cdb_show,
+ .help = &cmd_cdb_show_help,
+ },{
+ .sc_cmd = "cdb-node-add",
+ .sc_cmd_func = cmd_cdb_node_add,
+ .help = &cmd_cdb_node_add_help,
+ },{
+ .sc_cmd = "cdb-node-del",
+ .sc_cmd_func = cmd_cdb_node_del,
+ .help = &cmd_cdb_node_del_help,
+ },{
+ .sc_cmd = "cdb-subnet-add",
+ .sc_cmd_func = cmd_cdb_subnet_add,
+ .help = &cmd_cdb_subnet_add_help,
+ },{
+ .sc_cmd = "cdb-subnet-del",
+ .sc_cmd_func = cmd_cdb_subnet_del,
+ .help = &cmd_cdb_subnet_del_help,
+ },{
+ .sc_cmd = "cdb-app-key-add",
+ .sc_cmd_func = cmd_cdb_app_key_add,
+ .help = &cmd_cdb_app_key_add_help,
+ },{
+ .sc_cmd = "cdb-app-key-add",
+ .sc_cmd_func = cmd_cdb_app_key_del,
+ .help = &cmd_cdb_app_key_del_help,
+ },
+#endif
+
#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
/* Generic Client Model Operations */
{
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/subnet.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/subnet.c
new file mode 100644
index 000000000..8e21a8597
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/subnet.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+#define MESH_LOG_MODULE BLE_MESH_NET_KEYS_LOG
+
+#if MYNEWT_VAL(BLE_MESH)
+
+#include "nimble/porting/nimble/include/log/log.h"
+
+#include "crypto.h"
+#include "adv.h"
+#include "../include/mesh/mesh.h"
+#include "net.h"
+#include "mesh_priv.h"
+#include "lpn.h"
+#include "friend.h"
+#include "proxy.h"
+#include "transport.h"
+#include "access.h"
+#include "foundation.h"
+#include "beacon.h"
+#include "rpl.h"
+#include "settings.h"
+#include "prov.h"
+
+#ifdef CONFIG_BT_MESH_GATT_PROXY
+void (*bt_mesh_subnet_cb_list[5]) (struct bt_mesh_subnet *sub,
+ enum bt_mesh_key_evt evt);
+#else
+void (*bt_mesh_subnet_cb_list[4]) (struct bt_mesh_subnet *sub,
+ enum bt_mesh_key_evt evt);
+#endif
+
+static struct bt_mesh_subnet subnets[CONFIG_BT_MESH_SUBNET_COUNT] = {
+ [0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = {
+ .net_idx = BT_MESH_KEY_UNUSED,
+ },
+};
+
+static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt)
+{
+ int i;
+ for (i = 0; i < (sizeof(bt_mesh_subnet_cb_list)/sizeof(void *)); i++) {
+ BT_DBG("%d", i);
+ if (bt_mesh_subnet_cb_list[i]) {
+ bt_mesh_subnet_cb_list[i] (sub, evt);
+ }
+ }
+}
+
+uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub)
+{
+ uint8_t flags = 0x00;
+
+ if (sub && (sub->kr_phase == BT_MESH_KR_PHASE_2)) {
+ flags |= BT_MESH_NET_FLAG_KR;
+ }
+
+ if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) {
+ flags |= BT_MESH_NET_FLAG_IVU;
+ }
+
+ return flags;
+}
+
+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);
+
+ switch (new_phase) {
+ /* Added second set of keys */
+ case BT_MESH_KR_PHASE_1:
+ sub->kr_phase = new_phase;
+ subnet_evt(sub, BT_MESH_KEY_UPDATED);
+ break;
+ /* Now using new keys for TX */
+ case BT_MESH_KR_PHASE_2:
+ sub->kr_phase = new_phase;
+ subnet_evt(sub, BT_MESH_KEY_SWAPPED);
+ break;
+ /* Revoking keys */
+ case BT_MESH_KR_PHASE_3:
+ if (sub->kr_phase == BT_MESH_KR_NORMAL) {
+ return;
+ }
+ /* __fallthrough; */
+ case BT_MESH_KR_NORMAL:
+ sub->kr_phase = BT_MESH_KR_NORMAL;
+ memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0]));
+ sub->keys[1].valid = 0U;
+ subnet_evt(sub, BT_MESH_KEY_REVOKED);
+ break;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing Updated NetKey persistently");
+ bt_mesh_store_subnet(sub->net_idx);
+ }
+}
+
+void bt_mesh_kr_update(struct bt_mesh_subnet *sub, bool kr_flag, bool new_key)
+{
+ if (!new_key) {
+ return;
+ }
+
+ if (sub->kr_phase == BT_MESH_KR_PHASE_1) {
+ /* Bluetooth Mesh Profile Specification Section 3.10.4.1:
+ * Can skip phase 2 if we get KR=0 on new key.
+ */
+ key_refresh(sub, (kr_flag ? BT_MESH_KR_PHASE_2 :
+ BT_MESH_KR_PHASE_3));
+ } else if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !kr_flag) {
+ key_refresh(sub, BT_MESH_KR_PHASE_3);
+ }
+}
+
+static struct bt_mesh_subnet *subnet_alloc(uint16_t net_idx)
+{
+ struct bt_mesh_subnet *sub = NULL;
+
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ /* Check for already existing subnet */
+ if (subnets[i].net_idx == net_idx) {
+ return &subnets[i];
+ }
+
+ if (!sub && subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+ sub = &subnets[i];
+ }
+ }
+
+ return sub;
+}
+
+static void subnet_del(struct bt_mesh_subnet *sub)
+{
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_clear_subnet(sub->net_idx);
+ }
+
+ bt_mesh_net_loopback_clear(sub->net_idx);
+
+ subnet_evt(sub, BT_MESH_KEY_DELETED);
+ (void)memset(sub, 0, sizeof(*sub));
+ sub->net_idx = BT_MESH_KEY_UNUSED;
+}
+
+static int msg_cred_create(struct bt_mesh_net_cred *cred, const uint8_t *p,
+ size_t p_len, const uint8_t key[16])
+{
+ return bt_mesh_k2(key, p, p_len, &cred->nid, cred->enc, cred->privacy);
+}
+
+static int net_keys_create(struct bt_mesh_subnet_keys *keys,
+ const uint8_t key[16])
+{
+ uint8_t p = 0;
+ int err;
+
+ err = msg_cred_create(&keys->msg, &p, 1, key);
+ if (err) {
+ BT_ERR("Unable to generate NID, EncKey & PrivacyKey");
+ return err;
+ }
+
+ memcpy(keys->net, key, 16);
+
+ BT_DBG("NID 0x%02x EncKey %s", keys->msg.nid,
+ bt_hex(keys->msg.enc, 16));
+ BT_DBG("PrivacyKey %s", bt_hex(keys->msg.privacy, 16));
+
+ err = bt_mesh_k3(key, keys->net_id);
+ if (err) {
+ BT_ERR("Unable to generate Net ID");
+ return err;
+ }
+
+ BT_DBG("NetID %s", bt_hex(keys->net_id, 8));
+
+#if defined(CONFIG_BT_MESH_GATT_PROXY)
+ err = bt_mesh_identity_key(key, keys->identity);
+ if (err) {
+ BT_ERR("Unable to generate IdentityKey");
+ return err;
+ }
+
+ BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16));
+#endif /* GATT_PROXY */
+
+ err = bt_mesh_beacon_key(key, keys->beacon);
+ if (err) {
+ BT_ERR("Unable to generate beacon key");
+ return err;
+ }
+
+ BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16));
+
+ keys->valid = 1U;
+
+ return 0;
+}
+
+uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16])
+{
+ struct bt_mesh_subnet *sub = NULL;
+ int err;
+
+ BT_DBG("0x%03x", net_idx);
+
+ sub = subnet_alloc(net_idx);
+ if (!sub) {
+ return STATUS_INSUFF_RESOURCES;
+ }
+
+ if (sub->net_idx == net_idx) {
+ if (memcmp(key, sub->keys[0].net, 16)) {
+ return STATUS_IDX_ALREADY_STORED;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ err = net_keys_create(&sub->keys[0], key);
+ if (err) {
+ return STATUS_UNSPECIFIED;
+ }
+
+ sub->net_idx = net_idx;
+ sub->kr_phase = BT_MESH_KR_NORMAL;
+
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
+ } else {
+ sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
+ }
+
+ subnet_evt(sub, BT_MESH_KEY_ADDED);
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ BT_DBG("Storing NetKey persistently");
+ bt_mesh_store_subnet(sub->net_idx);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+bool bt_mesh_subnet_exists(uint16_t net_idx)
+{
+ return !!bt_mesh_subnet_get(net_idx);
+}
+
+uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16])
+{
+ struct bt_mesh_subnet *sub;
+ int err;
+
+ BT_DBG("0x%03x", net_idx);
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ /* The node shall successfully process a NetKey Update message on a
+ * valid NetKeyIndex when the NetKey value is different and the Key
+ * Refresh procedure has not been started, or when the NetKey value is
+ * the same in Phase 1. The NetKey Update message shall generate an
+ * error when the node is in Phase 2, or Phase 3.
+ */
+ switch (sub->kr_phase) {
+ case BT_MESH_KR_NORMAL:
+ if (!memcmp(key, sub->keys[0].net, 16)) {
+ return STATUS_IDX_ALREADY_STORED;
+ }
+ break;
+ case BT_MESH_KR_PHASE_1:
+ if (!memcmp(key, sub->keys[1].net, 16)) {
+ return STATUS_SUCCESS;
+ }
+ /* __fallthrough; */
+ case BT_MESH_KR_PHASE_2:
+ case BT_MESH_KR_PHASE_3:
+ return STATUS_CANNOT_UPDATE;
+ }
+
+ err = net_keys_create(&sub->keys[1], key);
+ if (err) {
+ return STATUS_CANNOT_UPDATE;
+ }
+
+ key_refresh(sub, BT_MESH_KR_PHASE_1);
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_del(uint16_t net_idx)
+{
+ struct bt_mesh_subnet *sub;
+
+ BT_DBG("0x%03x", net_idx);
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ /* This could be a retry of a previous attempt that had its
+ * response lost, so pretend that it was a success.
+ */
+ return STATUS_INVALID_NETKEY;
+ }
+
+ subnet_del(sub);
+
+ return STATUS_SUCCESS;
+}
+
+int bt_mesh_friend_cred_create(struct bt_mesh_net_cred *cred, uint16_t lpn_addr,
+ uint16_t frnd_addr, uint16_t lpn_counter,
+ uint16_t frnd_counter, const uint8_t key[16])
+{
+ uint8_t p[9];
+
+ p[0] = 0x01;
+ sys_put_be16(lpn_addr, p + 1);
+ sys_put_be16(frnd_addr, p + 3);
+ sys_put_be16(lpn_counter, p + 5);
+ sys_put_be16(frnd_counter, p + 7);
+
+ return msg_cred_create(cred, p, sizeof(p), key);
+}
+
+uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase)
+{
+ /* Table in Bluetooth Mesh Profile Specification Section 4.2.14: */
+ const uint8_t valid_transitions[] = {
+ BIT(BT_MESH_KR_PHASE_3), /* Normal phase: KR is started by key update */
+ BIT(BT_MESH_KR_PHASE_2) | BIT(BT_MESH_KR_PHASE_3), /* Phase 1 */
+ BIT(BT_MESH_KR_PHASE_3), /* Phase 2 */
+ /* Subnet is never in Phase 3 */
+ };
+ struct bt_mesh_subnet *sub;
+
+ BT_DBG("0x%03x", net_idx);
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ *phase = 0x00;
+ return STATUS_INVALID_NETKEY;
+ }
+
+ if (*phase == sub->kr_phase) {
+ return STATUS_SUCCESS;
+ }
+
+ if (sub->kr_phase < ARRAY_SIZE(valid_transitions) &&
+ valid_transitions[sub->kr_phase] & BIT(*phase)) {
+ key_refresh(sub, *phase);
+
+ *phase = sub->kr_phase;
+
+ return STATUS_SUCCESS;
+ }
+
+ BT_WARN("Invalid KR transition: 0x%02x -> 0x%02x", sub->kr_phase,
+ *phase);
+
+ *phase = sub->kr_phase;
+
+ return STATUS_CANNOT_UPDATE;
+}
+
+uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase)
+{
+ struct bt_mesh_subnet *sub;
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ *phase = BT_MESH_KR_NORMAL;
+ return STATUS_INVALID_NETKEY;
+ }
+
+ *phase = sub->kr_phase;
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
+ enum bt_mesh_feat_state node_id)
+{
+ struct bt_mesh_subnet *sub;
+
+ if (node_id == BT_MESH_FEATURE_NOT_SUPPORTED) {
+ return STATUS_CANNOT_SET;
+ }
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ return STATUS_INVALID_NETKEY;
+ }
+
+ if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ return STATUS_FEAT_NOT_SUPP;
+ }
+
+ if (node_id) {
+ bt_mesh_proxy_identity_start(sub);
+ } else {
+ bt_mesh_proxy_identity_stop(sub);
+ }
+
+ bt_mesh_adv_update();
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
+ enum bt_mesh_feat_state *node_id)
+{
+ struct bt_mesh_subnet *sub;
+
+ sub = bt_mesh_subnet_get(net_idx);
+ if (!sub) {
+ *node_id = 0x00;
+ return STATUS_INVALID_NETKEY;
+ }
+
+ *node_id = sub->node_id;
+
+ return STATUS_SUCCESS;
+}
+
+ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip)
+{
+ size_t count = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ struct bt_mesh_subnet *sub = &subnets[i];
+
+ if (sub->net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (skip) {
+ skip--;
+ continue;
+ }
+
+ if (count >= max) {
+ return -ENOMEM;
+ }
+
+ net_idxs[count++] = sub->net_idx;
+ }
+
+ return count;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx)
+{
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ struct bt_mesh_subnet *sub = &subnets[i];
+
+ if (sub->net_idx == net_idx) {
+ return sub;
+ }
+ }
+
+ return NULL;
+}
+
+int bt_mesh_subnet_set(uint16_t net_idx, uint8_t kr_phase,
+ const uint8_t old_key[16], const uint8_t new_key[16])
+{
+ const uint8_t *keys[] = { old_key, new_key };
+ struct bt_mesh_subnet *sub;
+
+ sub = subnet_alloc(net_idx);
+ if (!sub) {
+ return -ENOMEM;
+ }
+
+ if (sub->net_idx == net_idx) {
+ return -EALREADY;
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(keys); i++) {
+ if (!keys[i]) {
+ continue;
+ }
+
+ if (net_keys_create(&sub->keys[i], keys[i])) {
+ return -EIO;
+ }
+ }
+
+ sub->net_idx = net_idx;
+ sub->kr_phase = kr_phase;
+
+ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) {
+ sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED;
+ } else {
+ sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED;
+ }
+
+ /* Make sure we have valid beacon data to be sent */
+ bt_mesh_beacon_update(sub);
+
+ return 0;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_find(int (*cb)(struct bt_mesh_subnet *sub,
+ void *cb_data),
+ void *cb_data)
+{
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ if (subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ if (!cb || cb(&subnets[i], cb_data)) {
+ return &subnets[i];
+ }
+ }
+
+ return NULL;
+}
+
+size_t bt_mesh_subnet_foreach(void (*cb)(struct bt_mesh_subnet *sub))
+{
+ size_t count = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++) {
+ if (subnets[i].net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ cb(&subnets[i]);
+ count++;
+ }
+
+ return count;
+}
+
+struct bt_mesh_subnet *bt_mesh_subnet_next(struct bt_mesh_subnet *sub)
+{
+ if (sub) {
+ sub++;
+ } else {
+ sub = &subnets[0];
+ }
+
+ for (int i = 0; i < ARRAY_SIZE(subnets); i++, sub++) {
+ /* Roll over once we reach the end */
+ if (sub == &subnets[ARRAY_SIZE(subnets)]) {
+ sub = &subnets[0];
+ }
+
+ if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+ return sub;
+ }
+ }
+
+ return NULL;
+}
+
+void bt_mesh_net_keys_reset(void)
+{
+ int i;
+
+ /* Delete all net keys, which also takes care of all app keys which
+ * are associated with each net key.
+ */
+ for (i = 0; i < ARRAY_SIZE(subnets); i++) {
+ struct bt_mesh_subnet *sub = &subnets[i];
+
+ if (sub->net_idx != BT_MESH_KEY_UNUSED) {
+ subnet_del(sub);
+ }
+ }
+}
+
+bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+ struct os_mbuf *out,
+ bool (*cb)(struct bt_mesh_net_rx *rx,
+ struct os_mbuf *in,
+ struct os_mbuf *out,
+ const struct bt_mesh_net_cred *cred))
+{
+ int i, j;
+
+ BT_DBG("");
+
+#if MYNEWT_VAL(BLE_MESH_LOW_POWER)
+ if (bt_mesh_lpn_waiting_update()) {
+ rx->sub = bt_mesh.lpn.sub;
+
+ for (j = 0; j < ARRAY_SIZE(bt_mesh.lpn.cred); j++) {
+ if (!rx->sub->keys[j].valid) {
+ continue;
+ }
+
+ if (cb(rx, in, out, &bt_mesh.lpn.cred[j])) {
+ rx->new_key = (j > 0);
+ rx->friend_cred = 1U;
+ rx->ctx.net_idx = rx->sub->net_idx;
+ return true;
+ }
+ }
+
+ /* LPN Should only receive on the friendship credentials when in
+ * a friendship.
+ */
+ return false;
+ }
+#endif
+
+#if MYNEWT_VAL(BLE_MESH_FRIEND)
+ /** Each friendship has unique friendship credentials */
+ for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) {
+ struct bt_mesh_friend *frnd = &bt_mesh.frnd[i];
+
+ if (!frnd->subnet) {
+ continue;
+ }
+
+ rx->sub = frnd->subnet;
+
+ for (j = 0; j < ARRAY_SIZE(frnd->cred); j++) {
+ if (!rx->sub->keys[j].valid) {
+ continue;
+ }
+
+ if (cb(rx, in, out, &frnd->cred[j])) {
+ rx->new_key = (j > 0);
+ rx->friend_cred = 1U;
+ rx->ctx.net_idx = rx->sub->net_idx;
+ return true;
+ }
+ }
+ }
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(subnets); i++) {
+ rx->sub = &subnets[i];
+ if (rx->sub->net_idx == BT_MESH_KEY_UNUSED) {
+ continue;
+ }
+
+ for (j = 0; j < ARRAY_SIZE(rx->sub->keys); j++) {
+ if (!rx->sub->keys[j].valid) {
+ continue;
+ }
+
+ if (cb(rx, in, out, &rx->sub->keys[j].msg)) {
+ rx->new_key = (j > 0);
+ rx->friend_cred = 0U;
+ rx->ctx.net_idx = rx->sub->net_idx;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+#endif /* MYNEWT_VAL(BLE_MESH) */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/subnet.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/subnet.h
new file mode 100644
index 000000000..e4a193b37
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/subnet.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2020 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _BLUETOOTH_MESH_SUBNET_H_
+#define _BLUETOOTH_MESH_SUBNET_H_
+
+#include
+#include
+#include "../include/mesh/glue.h"
+#define BT_MESH_NET_FLAG_KR BIT(0)
+#define BT_MESH_NET_FLAG_IVU BIT(1)
+
+#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
+
+/** Which of the two subnet.keys should be used for sending. */
+#define SUBNET_KEY_TX_IDX(sub) ((sub)->kr_phase == BT_MESH_KR_PHASE_2)
+
+struct bt_mesh_net_rx;
+enum bt_mesh_key_evt;
+
+/** Network message encryption credentials */
+struct bt_mesh_net_cred {
+ uint8_t nid; /* NID */
+ uint8_t enc[16]; /* EncKey */
+ uint8_t privacy[16]; /* PrivacyKey */
+};
+
+/** Subnet instance. */
+struct bt_mesh_subnet {
+ uint32_t beacon_sent; /* Timestamp of last sent beacon */
+ uint8_t beacons_last; /* Number of beacons during last
+ * observation window
+ */
+ uint8_t beacons_cur; /* Number of beaconds observed during
+ * currently ongoing window.
+ */
+
+ uint8_t beacon_cache[21]; /* Cached last authenticated beacon */
+
+ uint16_t net_idx; /* NetKeyIndex */
+
+ uint8_t kr_phase; /* Key Refresh Phase */
+
+ uint8_t node_id; /* Node Identity State */
+ uint32_t node_id_start; /* Node Identity started timestamp */
+
+ uint8_t auth[8]; /* Beacon Authentication Value */
+
+ struct bt_mesh_subnet_keys {
+ bool valid;
+ uint8_t net[16]; /* NetKey */
+ struct bt_mesh_net_cred msg;
+ uint8_t net_id[8]; /* Network ID */
+ #if defined(CONFIG_BT_MESH_GATT_PROXY)
+ uint8_t identity[16]; /* IdentityKey */
+ #endif
+ uint8_t beacon[16]; /* BeaconKey */
+ } keys[2];
+};
+
+#ifdef CONFIG_BT_MESH_GATT_PROXY
+extern void (*bt_mesh_subnet_cb_list[5]) (struct bt_mesh_subnet *sub,
+ enum bt_mesh_key_evt evt);
+#else
+extern void (*bt_mesh_subnet_cb_list[4]) (struct bt_mesh_subnet *sub,
+ enum bt_mesh_key_evt evt);
+#endif
+
+/** Subnet callback structure. Instantiate with @ref BT_MESH_SUBNET_CB */
+struct bt_mesh_subnet_cb {
+ void (*evt_handler)(struct bt_mesh_subnet *subnet,
+ enum bt_mesh_key_evt evt);
+};
+
+/** @brief Reset all Network keys. */
+void bt_mesh_net_keys_reset(void);
+
+/** @brief Call cb on every valid Subnet until it returns a non-zero value.
+ *
+ * @param cb Callback to call, or NULL to return first valid subnet.
+ * @param cb_data Callback data to pass to callback.
+ *
+ * @return Subnet that returned non-zero value.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_find(int (*cb)(struct bt_mesh_subnet *sub,
+ void *cb_data),
+ void *cb_data);
+
+/** @brief Iterate through all valid Subnets.
+ *
+ * @param cb Callback to call on every Subnet.
+ *
+ * @returns The number of valid subnets.
+ */
+size_t bt_mesh_subnet_foreach(void (*cb)(struct bt_mesh_subnet *sub));
+
+/** @brief Get the next valid Subnet.
+ *
+ * If there's only one valid Subnet, this will be returned on every call.
+ *
+ * @param sub Previous Subnet, or NULL to get the first valid.
+ *
+ * @returns Gets the next valid Subnet after @c sub, or NULL if there are no
+ * valid Subnets.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_next(struct bt_mesh_subnet *sub);
+
+/** @brief Get a pointer to the Subnet with the given index.
+ *
+ * @param net_idx Network index to look for.
+ *
+ * @returns Subnet with index @c net_idx, or NULL if no such Subnet is known.
+ */
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx);
+
+/** @brief Initialize a new Subnet.
+ *
+ * @param net_idx Network index of the Subnet.
+ * @param kr_phase Key refresh phase the Subnet should be in.
+ * @param key The current network key for the Subnet.
+ * @param new_key New network key, if available.
+ *
+ * @returns 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_subnet_set(uint16_t net_idx, uint8_t kr_phase,
+ const uint8_t key[16], const uint8_t new_key[16]);
+
+/** @brief Create Friendship credentials.
+ *
+ * @param cred Credential object to create.
+ * @param lpn_addr Address of the LPN node in the friendship.
+ * @param frnd_addr Address of the Friend node in the friendship.
+ * @param lpn_counter The LPN's counter parameter.
+ * @param frnd_counter The Friend node's counter parameter.
+ * @param key Network key to create the Friendship credentials for.
+ *
+ * @returns 0 on success, or (negative) error code on failure.
+ */
+int bt_mesh_friend_cred_create(struct bt_mesh_net_cred *cred,
+ uint16_t lpn_addr, uint16_t frnd_addr,
+ uint16_t lpn_counter, uint16_t frnd_counter,
+ const uint8_t key[16]);
+
+/** @brief Iterate through all valid network credentials to decrypt a message.
+ *
+ * @param rx Network RX parameters, passed to the callback.
+ * @param in Input message buffer, passed to the callback.
+ * @param out Output message buffer, passed to the callback.
+ * @param cb Callback to call for each known network credential. Iteration
+ * stops when this callback returns @c true.
+ *
+ * @returns Whether any of the credentials got a @c true return from the
+ * callback.
+ */
+bool bt_mesh_net_cred_find(struct bt_mesh_net_rx *rx, struct os_mbuf *in,
+ struct os_mbuf *out,
+ bool (*cb)(struct bt_mesh_net_rx *rx,
+ struct os_mbuf *in,
+ struct os_mbuf *out,
+ const struct bt_mesh_net_cred *cred));
+
+/** @brief Get the network flags of the given Subnet.
+ *
+ * @param sub Subnet to get the network flags of.
+ *
+ * @returns A bitmap of @ref BT_MESH_NET_FLAG_KR and @ref BT_MESH_NET_FLAG_IVU.
+ */
+uint8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub);
+
+/** @brief Process a Key Refresh event from a beacon.
+ *
+ * @param sub Subnet the Key Refresh was received on.
+ * @param kr_flag Key Refresh flag.
+ * @param new_key Whether the Key Refresh event was received on the new key
+ * set.
+ */
+void bt_mesh_kr_update(struct bt_mesh_subnet *sub, bool kr_flag, bool new_key);
+
+/** @brief Check whether the Subnet has the refreshed keys.
+ *
+ * @param sub Subnet.
+ *
+ * @returns Whether the Subnet's second key is valid.
+ */
+static inline bool
+bt_mesh_subnet_has_new_key(const struct bt_mesh_subnet *sub)
+{
+ return sub->kr_phase != BT_MESH_KR_NORMAL;
+}
+
+#endif /* _BLUETOOTH_MESH_SUBNET_H_ */
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c
index c8e716a04..8ec7dcfe7 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.c
@@ -15,42 +15,37 @@
#include
#include "../include/mesh/mesh.h"
+#include "../include/mesh/glue.h"
#include "mesh_priv.h"
#include "crypto.h"
#include "adv.h"
#include "net.h"
+#include "app_keys.h"
+#include "rpl.h"
#include "lpn.h"
#include "friend.h"
#include "access.h"
#include "foundation.h"
#include "settings.h"
+#include "heartbeat.h"
#include "transport.h"
-#include "testing.h"
-#include "nodes.h"
-/* The transport layer needs at least three buffers for itself to avoid
- * deadlocks. Ensure that there are a sufficient number of advertising
- * buffers available compared to the maximum supported outgoing segment
- * count.
- */
-BUILD_ASSERT(CONFIG_BT_MESH_ADV_BUF_COUNT >= (CONFIG_BT_MESH_TX_SEG_MAX + 3));
-
-#define AID_MASK ((u8_t)(BIT_MASK(6)))
+#define AID_MASK ((uint8_t)(BIT_MASK(6)))
#define SEG(data) ((data)[0] >> 7)
#define AKF(data) (((data)[0] >> 6) & 0x01)
#define AID(data) ((data)[0] & AID_MASK)
#define ASZMIC(data) (((data)[1] >> 7) & 1)
-#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4)
+#define APP_MIC_LEN(aszmic) ((aszmic) ? BT_MESH_MIC_LONG : BT_MESH_MIC_SHORT)
#define UNSEG_HDR(akf, aid) ((akf << 6) | (aid & AID_MASK))
#define SEG_HDR(akf, aid) (UNSEG_HDR(akf, aid) | 0x80)
-#define BLOCK_COMPLETE(seg_n) (u32_t)(((u64_t)1 << (seg_n + 1)) - 1)
+#define BLOCK_COMPLETE(seg_n) (uint32_t)(((uint64_t)1 << (seg_n + 1)) - 1)
-#define SEQ_AUTH(iv_index, seq) (((u64_t)iv_index) << 24 | (u64_t)seq)
+#define SEQ_AUTH(iv_index, seq) (((uint64_t)iv_index) << 24 | (uint64_t)seq)
/* Number of retransmit attempts (after the initial transmit) per segment */
#define SEG_RETRANSMIT_ATTEMPTS (MYNEWT_VAL(BLE_MESH_SEG_RETRANSMIT_ATTEMPTS))
@@ -59,59 +54,84 @@ BUILD_ASSERT(CONFIG_BT_MESH_ADV_BUF_COUNT >= (CONFIG_BT_MESH_TX_SEG_MAX + 3));
* We use 400 since 300 is a common send duration for standard HCI, and we
* need to have a timeout that's bigger than that.
*/
-#define SEG_RETRANSMIT_TIMEOUT(tx) (K_MSEC(400) + 50 * (tx)->ttl)
+#define SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) \
+ (MYNEWT_VAL(BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST) + 50 * (tx)->ttl)
+/* When sending to a group, the messages are not acknowledged, and there's no
+ * reason to delay the repetitions significantly. Delaying by more than 0 ms
+ * to avoid flooding the network.
+ */
+#define SEG_RETRANSMIT_TIMEOUT_GROUP \
+ MYNEWT_VAL(BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP)
+#define SEG_RETRANSMIT_TIMEOUT(tx) \
+ (BT_MESH_ADDR_IS_UNICAST(tx->dst) ? \
+ SEG_RETRANSMIT_TIMEOUT_UNICAST(tx) : \
+ SEG_RETRANSMIT_TIMEOUT_GROUP)
/* How long to wait for available buffers before giving up */
#define BUF_TIMEOUT K_NO_WAIT
static struct seg_tx {
- struct bt_mesh_subnet *sub;
- struct os_mbuf *seg[CONFIG_BT_MESH_TX_SEG_MAX];
- u64_t seq_auth;
- u16_t dst;
- u8_t seg_n:5, /* Last segment index */
- new_key:1; /* New/old key */
- u8_t nack_count; /* Number of unacked segs */
- u8_t ttl;
+ struct bt_mesh_subnet *sub;
+ void *seg[CONFIG_BT_MESH_TX_SEG_MAX];
+ uint64_t seq_auth;
+ uint16_t src;
+ uint16_t dst;
+ uint16_t len;
+ uint8_t hdr;
+ uint8_t xmit;
+ uint8_t seg_n; /* Last segment index */
+ uint8_t seg_o; /* Segment being sent */
+ uint8_t nack_count; /* Number of unacked segs */
+ uint8_t attempts; /* Remaining tx attempts */
+ uint8_t ttl; /* Transmitted TTL value */
+ uint8_t seg_pending; /* Number of segments pending */
+ uint8_t blocked:1, /* Blocked by ongoing tx */
+ ctl:1, /* Control packet */
+ aszmic:1, /* MIC size */
+ started:1, /* Start cb called */
+ sending:1, /* Sending is in progress */
+ friend_cred:1; /* Using Friend credentials */
const struct bt_mesh_send_cb *cb;
- void *cb_data;
- struct k_delayed_work retransmit; /* Retransmit timer */
+ void *cb_data;
+ struct k_delayed_work retransmit; /* Retransmit timer */
} seg_tx[MYNEWT_VAL(BLE_MESH_TX_SEG_MSG_COUNT)];
static struct seg_rx {
struct bt_mesh_subnet *sub;
- u64_t seq_auth;
- u8_t seg_n:5,
- ctl:1,
- in_use:1,
- obo:1;
- u8_t hdr;
- u8_t ttl;
- u16_t src;
- u16_t dst;
- u32_t block;
- u32_t last;
+ void *seg[CONFIG_BT_MESH_RX_SEG_MAX];
+ uint64_t seq_auth;
+ uint16_t src;
+ uint16_t dst;
+ uint16_t len;
+ uint8_t hdr;
+ uint8_t seg_n:5,
+ ctl:1,
+ in_use:1,
+ obo:1;
+ uint8_t ttl;
+ uint32_t block;
+ uint32_t last;
struct k_delayed_work ack;
- struct os_mbuf *buf;
-} seg_rx[MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT)] = {
- [0 ... (MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT) - 1)] = { 0 },
+} 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)];
+
+struct k_mem_slab segs = {
+ .num_blocks = CONFIG_BT_MESH_SEG_BUFS,
+ .block_size = BT_MESH_APP_SEG_SDU_MAX,
+ .buffer = _k_mem_slab_buffer_,
+ .free_list = NULL,
+ .num_used = 0
};
-static u16_t hb_sub_dst = BT_MESH_ADDR_UNASSIGNED;
-
-void bt_mesh_set_hb_sub_dst(u16_t addr)
-{
- hb_sub_dst = addr;
-}
+static struct bt_mesh_va 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)
+ const struct bt_mesh_send_cb *cb, void *cb_data,
+ const uint8_t *ctl_op)
{
struct os_mbuf *buf;
- BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x sdu_len %u",
- tx->src, tx->ctx->addr, tx->ctx->app_idx, sdu->om_len);
-
buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
if (!buf) {
BT_ERR("Out of network buffers");
@@ -120,7 +140,9 @@ static int send_unseg(struct bt_mesh_net_tx *tx, struct os_mbuf *sdu,
net_buf_reserve(buf, BT_MESH_NET_HDR_LEN);
- if (BT_MESH_IS_DEV_KEY(tx->ctx->app_idx)) {
+ if (ctl_op) {
+ net_buf_add_u8(buf, TRANS_CTL_HDR(*ctl_op, 0));
+ } else if (BT_MESH_IS_DEV_KEY(tx->ctx->app_idx)) {
net_buf_add_u8(buf, UNSEG_HDR(0, 0));
} else {
net_buf_add_u8(buf, UNSEG_HDR(1, tx->aid));
@@ -158,6 +180,15 @@ send:
return bt_mesh_net_send(tx, buf, cb, cb_data);
}
+static inline uint8_t seg_len(bool ctl)
+{
+ if (ctl) {
+ return BT_MESH_CTL_SEG_SDU_MAX;
+ } else {
+ return BT_MESH_APP_SEG_SDU_MAX;
+ }
+}
+
bool bt_mesh_tx_in_progress(void)
{
int i;
@@ -171,6 +202,41 @@ bool bt_mesh_tx_in_progress(void)
return false;
}
+static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx)
+{
+ k_mem_slab_free(&segs, (void **)&tx->seg[seg_idx]);
+ tx->seg[seg_idx] = NULL;
+ tx->nack_count--;
+}
+
+static bool seg_tx_blocks(struct seg_tx *tx, uint16_t src, uint16_t dst)
+{
+ return (tx->src == src) && (tx->dst == dst);
+}
+
+static void seg_tx_unblock_check(struct seg_tx *tx)
+{
+ struct seg_tx *blocked = NULL;
+ int i;
+
+ /* Unblock the first blocked tx with the same params. */
+ for (i = 0; i < ARRAY_SIZE(seg_tx); ++i) {
+ if (&seg_tx[i] != tx &&
+ seg_tx[i].blocked &&
+ seg_tx_blocks(tx, seg_tx[i].src, seg_tx[i].dst) &&
+ (!blocked || seg_tx[i].seq_auth < blocked->seq_auth)) {
+ blocked = &seg_tx[i];
+ }
+ }
+
+ if (blocked) {
+ BT_DBG("Unblocked 0x%04x",
+ (uint16_t)(blocked->seq_auth & TRANS_SEQ_ZERO_MASK));
+ blocked->blocked = false;
+ k_delayed_work_submit(&blocked->retransmit, 0);
+ }
+}
+
static void seg_tx_reset(struct seg_tx *tx)
{
int i;
@@ -181,22 +247,19 @@ static void seg_tx_reset(struct seg_tx *tx)
tx->cb_data = NULL;
tx->seq_auth = 0;
tx->sub = NULL;
+ tx->src = BT_MESH_ADDR_UNASSIGNED;
tx->dst = BT_MESH_ADDR_UNASSIGNED;
+ tx->blocked = false;
- if (!tx->nack_count) {
- return;
- }
-
- for (i = 0; i <= tx->seg_n; i++) {
+ for (i = 0; i <= tx->seg_n && tx->nack_count; i++) {
if (!tx->seg[i]) {
continue;
}
- net_buf_unref(tx->seg[i]);
- tx->seg[i] = NULL;
+ seg_tx_done(tx, i);
}
- tx->nack_count = 0U;
+ tx->nack_count = 0;
if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_IVU_PENDING)) {
BT_DBG("Proceding with pending IV Update");
@@ -204,41 +267,60 @@ static void seg_tx_reset(struct seg_tx *tx)
/* bt_mesh_net_iv_update() will re-enable the flag if this
* wasn't the only transfer.
*/
- if (bt_mesh_net_iv_update(bt_mesh.iv_index, false)) {
- bt_mesh_net_sec_update(NULL);
- }
+ bt_mesh_net_iv_update(bt_mesh.iv_index, false);
}
}
static inline void seg_tx_complete(struct seg_tx *tx, int err)
{
- if (tx->cb && tx->cb->end) {
- tx->cb->end(err, tx->cb_data);
- }
+ const struct bt_mesh_send_cb *cb = tx->cb;
+ void *cb_data = tx->cb_data;
+
+ seg_tx_unblock_check(tx);
seg_tx_reset(tx);
-}
-static void seg_first_send_start(u16_t duration, int err, void *user_data)
-{
- struct seg_tx *tx = user_data;
-
- if (tx->cb && tx->cb->start) {
- tx->cb->start(duration, err, tx->cb_data);
+ if (cb && cb->end) {
+ cb->end(err, cb_data);
}
}
-static void seg_send_start(u16_t duration, int err, void *user_data)
+static void schedule_retransmit(struct seg_tx *tx)
+{
+ if (!tx->nack_count) {
+ return;
+ }
+
+ if (--tx->seg_pending || tx->sending) {
+ return;
+ }
+
+ BT_DBG("");
+
+ /* If we haven't gone through all the segments for this attempt yet,
+ * (likely because of a buffer allocation failure or because we
+ * 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,
+ tx->seg_o ? 0 : K_MSEC(SEG_RETRANSMIT_TIMEOUT(tx)));
+}
+
+static void seg_send_start(uint16_t duration, int err, void *user_data)
{
struct seg_tx *tx = user_data;
+ if (!tx->started && tx->cb && tx->cb->start) {
+ tx->cb->start(duration, err, tx->cb_data);
+ tx->started = 1U;
+ }
+
/* If there's an error in transmitting the 'sent' callback will never
* be called. Make sure that we kick the retransmit timer also in this
* case since otherwise we risk the transmission of becoming stale.
*/
if (err) {
- k_delayed_work_submit(&tx->retransmit,
- SEG_RETRANSMIT_TIMEOUT(tx));
+ schedule_retransmit(tx);
}
}
@@ -246,52 +328,107 @@ static void seg_sent(int err, void *user_data)
{
struct seg_tx *tx = user_data;
- k_delayed_work_submit(&tx->retransmit,
- SEG_RETRANSMIT_TIMEOUT(tx));
+ schedule_retransmit(tx);
}
-static const struct bt_mesh_send_cb first_sent_cb = {
- .start = seg_first_send_start,
- .end = seg_sent,
-};
-
static const struct bt_mesh_send_cb seg_sent_cb = {
.start = seg_send_start,
.end = seg_sent,
};
+static void seg_tx_buf_build(struct seg_tx *tx, uint8_t seg_o,
+ struct os_mbuf *buf)
+{
+ uint16_t seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK;
+ uint8_t len = MIN(seg_len(tx->ctl), tx->len - (seg_len(tx->ctl) * seg_o));
+
+ net_buf_simple_add_u8(buf, tx->hdr);
+ net_buf_simple_add_u8(buf, (tx->aszmic << 7) | seq_zero >> 6);
+ net_buf_simple_add_u8(buf, (((seq_zero & 0x3f) << 2) | (seg_o >> 3)));
+ net_buf_simple_add_u8(buf, ((seg_o & 0x07) << 5) | tx->seg_n);
+ net_buf_simple_add_mem(buf, tx->seg[seg_o], len);
+}
+
static void seg_tx_send_unacked(struct seg_tx *tx)
{
- int i, err;
+ if (!tx->nack_count) {
+ return;
+ }
- for (i = 0; i <= tx->seg_n; i++) {
- struct os_mbuf *seg = tx->seg[i];
+ struct bt_mesh_msg_ctx ctx = {
+ .net_idx = tx->sub->net_idx,
+ /* App idx only used by network to detect control messages: */
+ .app_idx = (tx->ctl ? BT_MESH_KEY_UNUSED : 0),
+ .addr = tx->dst,
+ .send_rel = true,
+ .send_ttl = tx->ttl,
+ };
+ struct bt_mesh_net_tx net_tx = {
+ .sub = tx->sub,
+ .ctx = &ctx,
+ .src = tx->src,
+ .xmit = tx->xmit,
+ .friend_cred = tx->friend_cred,
+ .aid = tx->hdr & AID_MASK,
+ };
- if (!seg) {
- continue;
- }
-
- if (BT_MESH_ADV(seg)->busy) {
- BT_DBG("Skipping segment that's still advertising");
- continue;
- }
-
- if (!(BT_MESH_ADV(seg)->seg.attempts--)) {
+ if (!tx->attempts) {
+ if (BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
BT_ERR("Ran out of retransmit attempts");
seg_tx_complete(tx, -ETIMEDOUT);
- return;
+ } else {
+ /* Segmented sending to groups doesn't have acks, so
+ * running out of attempts is the expected behavior.
+ */
+ seg_tx_complete(tx, 0);
}
- BT_DBG("resending %u/%u", i, tx->seg_n);
+ return;
+ }
- err = bt_mesh_net_resend(tx->sub, seg, tx->new_key,
- &seg_sent_cb, tx);
+ BT_DBG("SeqZero: 0x%04x Attempts: %u",
+ (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->attempts);
+
+ tx->sending = 1U;
+
+ for (; tx->seg_o <= tx->seg_n; tx->seg_o++) {
+ struct os_mbuf *seg;
+ int err;
+
+ if (!tx->seg[tx->seg_o]) {
+ continue;
+ }
+
+ seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit,
+ BUF_TIMEOUT);
+ if (!seg) {
+ BT_DBG("Allocating segment failed");
+ goto end;
+ }
+
+ net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
+ seg_tx_buf_build(tx, tx->seg_o, seg);
+
+ tx->seg_pending++;
+
+ BT_DBG("Sending %u/%u", tx->seg_o, tx->seg_n);
+
+ err = bt_mesh_net_send(&net_tx, seg, &seg_sent_cb, tx);
if (err) {
- BT_ERR("Sending segment failed");
- seg_tx_complete(tx, -EIO);
- return;
+ BT_DBG("Sending segment failed");
+ tx->seg_pending--;
+ goto end;
}
}
+ tx->seg_o = 0U;
+ tx->attempts--;
+end:
+ if (!tx->seg_pending) {
+ k_delayed_work_submit(&tx->retransmit,
+ SEG_RETRANSMIT_TIMEOUT(tx));
+ }
+
+ tx->sending = 0U;
}
static void seg_retransmit(struct ble_npl_event *work)
@@ -301,31 +438,24 @@ static void seg_retransmit(struct ble_npl_event *work)
}
static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
- const struct bt_mesh_send_cb *cb, void *cb_data)
+ const struct bt_mesh_send_cb *cb, void *cb_data,
+ uint8_t *ctl_op)
{
- u8_t seg_hdr, seg_o;
- u16_t seq_zero;
+ bool blocked = false;
struct seg_tx *tx;
+ uint8_t seg_o;
int i;
BT_DBG("src 0x%04x dst 0x%04x app_idx 0x%04x aszmic %u sdu_len %u",
net_tx->src, net_tx->ctx->addr, net_tx->ctx->app_idx,
net_tx->aszmic, sdu->om_len);
- if (sdu->om_len < 1) {
- BT_ERR("Zero-length SDU not allowed");
- return -EINVAL;
- }
-
- if (sdu->om_len > BT_MESH_TX_SDU_MAX) {
- BT_ERR("Not enough segment buffers for length %u", sdu->om_len);
- return -EMSGSIZE;
- }
-
for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) {
- if (!seg_tx[i].nack_count) {
+ if (seg_tx[i].nack_count) {
+ blocked |= seg_tx_blocks(&seg_tx[i], net_tx->src,
+ net_tx->ctx->addr);
+ } else if (!tx) {
tx = &seg_tx[i];
- break;
}
}
@@ -334,31 +464,37 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
return -EBUSY;
}
- if (BT_MESH_IS_DEV_KEY(net_tx->ctx->app_idx)) {
- seg_hdr = SEG_HDR(0, 0);
+ if (ctl_op) {
+ tx->hdr = TRANS_CTL_HDR(*ctl_op, 1);
+ } else if (BT_MESH_IS_DEV_KEY(net_tx->ctx->app_idx)) {
+ tx->hdr = SEG_HDR(0, 0);
} else {
- seg_hdr = SEG_HDR(1, net_tx->aid);
+ tx->hdr = SEG_HDR(1, net_tx->aid);
}
- seg_o = 0;
+ tx->src = net_tx->src;
tx->dst = net_tx->ctx->addr;
- tx->seg_n = (sdu->om_len - 1) / 12;
+ tx->seg_n = (sdu->om_len - 1) / seg_len(!!ctl_op);
+ tx->seg_o = 0;
+ tx->len = sdu->om_len;
tx->nack_count = tx->seg_n + 1;
tx->seq_auth = SEQ_AUTH(BT_MESH_NET_IVI_TX, bt_mesh.seq);
tx->sub = net_tx->sub;
- tx->new_key = net_tx->sub->kr_flag;
tx->cb = cb;
tx->cb_data = cb_data;
+ tx->attempts = SEG_RETRANSMIT_ATTEMPTS;
+ tx->seg_pending = 0;
+ tx->xmit = net_tx->xmit;
+ tx->aszmic = net_tx->aszmic;
+ tx->friend_cred = net_tx->friend_cred;
+ tx->blocked = blocked;
+ tx->started = 0;
+ tx->ctl = !!ctl_op;
- if (net_tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
- tx->ttl = bt_mesh_default_ttl_get();
- } else {
- tx->ttl = net_tx->ctx->send_ttl;
- }
+ tx->ttl = net_tx->ctx->send_ttl;
- seq_zero = tx->seq_auth & TRANS_SEQ_ZERO_MASK;
-
- BT_DBG("SeqZero 0x%04x", seq_zero);
+ BT_DBG("SeqZero 0x%04x (segs: %u)",
+ (uint16_t)(tx->seq_auth & TRANS_SEQ_ZERO_MASK), tx->nack_count);
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) &&
!bt_mesh_friend_queue_has_space(tx->sub->net_idx, net_tx->src,
@@ -372,66 +508,48 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
}
for (seg_o = 0; sdu->om_len; seg_o++) {
- struct os_mbuf *seg;
- u16_t len;
+ void *buf;
+ uint16_t len;
int err;
- seg = bt_mesh_adv_create(BT_MESH_ADV_DATA, net_tx->xmit,
- BUF_TIMEOUT);
- if (!seg) {
+ err = k_mem_slab_alloc(&segs, &buf);
+ if (err) {
BT_ERR("Out of segment buffers");
seg_tx_reset(tx);
return -ENOBUFS;
}
- BT_MESH_ADV(seg)->seg.attempts = SEG_RETRANSMIT_ATTEMPTS;
+ len = MIN(sdu->om_len, seg_len(!!ctl_op));
+ memcpy(buf, net_buf_simple_pull_mem(sdu, len), len);
+ BT_DBG("seg %u: %s", seg_o, bt_hex(buf, len));
- net_buf_reserve(seg, BT_MESH_NET_HDR_LEN);
-
- net_buf_add_u8(seg, seg_hdr);
- net_buf_add_u8(seg, (net_tx->aszmic << 7) | seq_zero >> 6);
- net_buf_add_u8(seg, (((seq_zero & 0x3f) << 2) |
- (seg_o >> 3)));
- net_buf_add_u8(seg, ((seg_o & 0x07) << 5) | tx->seg_n);
-
- len = min(sdu->om_len, 12);
- net_buf_add_mem(seg, sdu->om_data, len);
- net_buf_simple_pull(sdu, len);
+ tx->seg[seg_o] = buf;
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
enum bt_mesh_friend_pdu_type type;
+ struct os_mbuf *seg = NET_BUF_SIMPLE(16);
+ seg_tx_buf_build(tx, seg_o, seg);
+
if (seg_o == tx->seg_n) {
type = BT_MESH_FRIEND_PDU_COMPLETE;
} else {
type = BT_MESH_FRIEND_PDU_PARTIAL;
}
- if (bt_mesh_friend_enqueue_tx(net_tx, type,
- &tx->seq_auth,
- tx->seg_n + 1,
- seg) &&
+ if (bt_mesh_friend_enqueue_tx(
+ net_tx, type, ctl_op ? NULL : &tx->seq_auth,
+ tx->seg_n + 1, seg) &&
BT_MESH_ADDR_IS_UNICAST(net_tx->ctx->addr)) {
/* PDUs for a specific Friend should only go
* out through the Friend Queue.
*/
- net_buf_unref(seg);
- continue;
+ k_mem_slab_free(&segs, &buf);
+ tx->seg[seg_o] = NULL;
}
+ os_mbuf_free_chain(seg);
}
- tx->seg[seg_o] = net_buf_ref(seg);
-
- BT_DBG("Sending %u/%u", seg_o, tx->seg_n);
-
- err = bt_mesh_net_send(net_tx, seg,
- seg_o ? &seg_sent_cb : &first_sent_cb,
- tx);
- if (err) {
- BT_ERR("Sending segment failed");
- seg_tx_reset(tx);
- return err;
- }
}
/* This can happen if segments only went into the Friend Queue */
@@ -443,8 +561,21 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
* with the Friend Queue.
*/
send_cb_finalize(cb, cb_data);
+ return 0;
}
+ if (blocked) {
+ /* Move the sequence number, so we don't end up creating
+ * another segmented transmission with the same SeqZero while
+ * this one is blocked.
+ */
+ bt_mesh_next_seq();
+ BT_DBG("Blocked.");
+ return 0;
+ }
+
+ seg_tx_send_unacked(tx);
+
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) &&
bt_mesh_lpn_established()) {
bt_mesh_lpn_poll();
@@ -453,50 +584,75 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct os_mbuf *sdu,
return 0;
}
-struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx)
+static int trans_encrypt(const struct bt_mesh_net_tx *tx, const uint8_t *key,
+ struct os_mbuf *msg)
{
- int i;
+ struct bt_mesh_app_crypto_ctx crypto = {
+ .dev_key = BT_MESH_IS_DEV_KEY(tx->ctx->app_idx),
+ .aszmic = tx->aszmic,
+ .src = tx->src,
+ .dst = tx->ctx->addr,
+ .seq_num = bt_mesh.seq,
+ .iv_index = BT_MESH_NET_IVI_TX,
+ };
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
-
- if (key->net_idx != BT_MESH_KEY_UNUSED &&
- key->app_idx == app_idx) {
- return key;
- }
+ if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
+ crypto.ad = bt_mesh_va_label_get(tx->ctx->addr);
}
- return NULL;
+ return bt_mesh_app_encrypt(key, &crypto, msg);
}
int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
const struct bt_mesh_send_cb *cb, void *cb_data)
{
- const u8_t *key;
- u8_t *ad;
- u8_t aid;
+ const uint8_t *key;
+ uint8_t aid;
int err;
+ if (msg->om_len < 1) {
+ BT_ERR("Zero-length SDU not allowed");
+ return -EINVAL;
+ }
+
+ if (msg->om_len > BT_MESH_TX_SDU_MAX) {
+ BT_ERR("Not enough segment buffers for length %u", msg->om_len);
+ return -EMSGSIZE;
+ }
+
if (net_buf_simple_tailroom(msg) < 4) {
BT_ERR("Insufficient tailroom for Transport MIC");
return -EINVAL;
}
- if (msg->om_len > 11) {
- tx->ctx->send_rel = 1;
+ if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
+ tx->ctx->send_ttl = bt_mesh_default_ttl_get();
+ } else if (tx->ctx->send_ttl > BT_MESH_TTL_MAX) {
+ BT_ERR("TTL too large (max 127)");
+ return -EINVAL;
+ }
+
+ if (msg->om_len > BT_MESH_SDU_UNSEG_MAX) {
tx->ctx->send_rel = true;
}
+ if (tx->ctx->addr == BT_MESH_ADDR_UNASSIGNED ||
+ (!BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) &&
+ BT_MESH_IS_DEV_KEY(tx->ctx->app_idx))) {
+ BT_ERR("Invalid destination address");
+ 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_app_key_get(tx->sub, tx->ctx->app_idx,
- tx->ctx->addr, &key, &aid);
+ err = bt_mesh_keys_resolve(tx->ctx, &tx->sub, &key, &aid);
if (err) {
return err;
}
+ tx->xmit = bt_mesh_net_transmit_get();
tx->aid = aid;
if (!tx->ctx->send_rel || net_buf_simple_tailroom(msg) < 8) {
@@ -505,115 +661,80 @@ int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
tx->aszmic = 1;
}
- if (BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
- ad = bt_mesh_label_uuid_get(tx->ctx->addr);
- } else {
- ad = NULL;
- }
-
- err = bt_mesh_app_encrypt(key, BT_MESH_IS_DEV_KEY(tx->ctx->app_idx),
- tx->aszmic, msg, ad, tx->src, tx->ctx->addr,
- bt_mesh.seq, BT_MESH_NET_IVI_TX);
+ err = trans_encrypt(tx, key, msg);
if (err) {
return err;
}
if (tx->ctx->send_rel) {
- err = send_seg(tx, msg, cb, cb_data);
+ err = send_seg(tx, msg, cb, cb_data, NULL);
} else {
- err = send_unseg(tx, msg, cb, cb_data);
+ err = send_unseg(tx, msg, cb, cb_data, NULL);
}
return err;
}
-static void update_rpl(struct bt_mesh_rpl *rpl, struct bt_mesh_net_rx *rx)
-{
- rpl->src = rx->ctx.addr;
- rpl->seq = rx->seq;
- rpl->old_iv = rx->old_iv;
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_store_rpl(rpl);
- }
-}
-
-/* Check the Replay Protection List for a replay attempt. If non-NULL match
- * parameter is given the RPL slot is returned but it is not immediately
- * updated (needed for segmented messages), whereas if a NULL match is given
- * the RPL is immediately updated (used for unsegmented messages).
- */
-static bool is_replay(struct bt_mesh_net_rx *rx, struct bt_mesh_rpl **match)
+static void seg_rx_assemble(struct seg_rx *rx, struct os_mbuf *buf,
+ uint8_t aszmic)
{
int i;
- /* Don't bother checking messages from ourselves */
- if (rx->net_if == BT_MESH_NET_IF_LOCAL) {
- return false;
+ net_buf_simple_reset(buf);
+
+ for (i = 0; i <= rx->seg_n; i++) {
+ net_buf_simple_add_mem(buf, rx->seg[i],
+ MIN(seg_len(rx->ctl),
+ rx->len - (i * seg_len(rx->ctl))));
}
- /* The RPL is used only for the local node */
- if (!rx->local_match) {
- return false;
+ /* Adjust the length to not contain the MIC at the end */
+ if (!rx->ctl) {
+ buf->om_len -= APP_MIC_LEN(aszmic);
}
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) {
- struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i];
-
- /* Empty slot */
- if (!rpl->src) {
- if (match) {
- *match = rpl;
- } else {
- update_rpl(rpl, rx);
- }
-
- return false;
- }
-
- /* Existing slot for given address */
- if (rpl->src == rx->ctx.addr) {
- if (rx->old_iv && !rpl->old_iv) {
- return true;
- }
-
- if ((!rx->old_iv && rpl->old_iv) ||
- rpl->seq < rx->seq) {
- if (match) {
- *match = rpl;
- } else {
- update_rpl(rpl, rx);
- }
-
- return false;
- } else {
- return true;
- }
- }
- }
-
- BT_ERR("RPL is full!");
- return true;
}
-static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
- u8_t aszmic, struct os_mbuf *buf)
+struct decrypt_ctx {
+ struct bt_mesh_app_crypto_ctx crypto;
+ struct os_mbuf *buf;
+ struct os_mbuf *sdu;
+ struct seg_rx *seg;
+};
+
+static int sdu_try_decrypt(struct bt_mesh_net_rx *rx, const uint8_t key[16],
+ void *cb_data)
{
- struct os_mbuf *sdu =
- NET_BUF_SIMPLE(MYNEWT_VAL(BLE_MESH_RX_SDU_MAX) - 4);
- u8_t *ad;
- u16_t i;
- int err = 0;
+ const struct decrypt_ctx *ctx = cb_data;
- BT_DBG("ASZMIC %u AKF %u AID 0x%02x", aszmic, AKF(&hdr), AID(&hdr));
- BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));
-
- if (buf->om_len < 1 + APP_MIC_LEN(aszmic)) {
- BT_ERR("Too short SDU + MIC");
- err = -EINVAL;
- goto done;
+ if (ctx->seg) {
+ seg_rx_assemble(ctx->seg, ctx->buf, ctx->crypto.aszmic);
}
+ net_buf_simple_reset(ctx->sdu);
+
+ return bt_mesh_app_decrypt(key, &ctx->crypto, ctx->buf, ctx->sdu);
+}
+
+static int sdu_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, uint8_t aszmic,
+ struct os_mbuf *buf, struct os_mbuf *sdu,
+ struct seg_rx *seg)
+{
+ struct decrypt_ctx ctx = {
+ .crypto = {
+ .dev_key = !AKF(&hdr),
+ .aszmic = aszmic,
+ .src = rx->ctx.addr,
+ .dst = rx->ctx.recv_dst,
+ .seq_num = seg ? (seg->seq_auth & 0xffffff) : rx->seq,
+ .iv_index = BT_MESH_NET_IVI_RX(rx),
+ },
+ .buf = buf,
+ .sdu = sdu,
+ .seg = seg,
+ };
+
+ BT_DBG("AKF %u AID 0x%02x", !ctx.crypto.dev_key, AID(&hdr));
+
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND) && !rx->local_match) {
BT_DBG("Ignoring PDU for LPN 0x%04x of this Friend",
rx->ctx.recv_dst);
@@ -621,109 +742,26 @@ static int sdu_recv(struct bt_mesh_net_rx *rx, u32_t seq, u8_t hdr,
}
if (BT_MESH_ADDR_IS_VIRTUAL(rx->ctx.recv_dst)) {
- ad = bt_mesh_label_uuid_get(rx->ctx.recv_dst);
- } else {
- ad = NULL;
+ ctx.crypto.ad = bt_mesh_va_label_get(rx->ctx.recv_dst);
}
- /* Adjust the length to not contain the MIC at the end */
- buf->om_len -= APP_MIC_LEN(aszmic);
-
- if (!AKF(&hdr)) {
- net_buf_simple_init(sdu, 0);
- err = bt_mesh_app_decrypt(bt_mesh.dev_key, true, aszmic, buf,
- sdu, ad, rx->ctx.addr,
- rx->ctx.recv_dst, seq,
- BT_MESH_NET_IVI_RX(rx));
- if (err) {
- BT_WARN("Unable to decrypt with local DevKey");
- } else {
- rx->ctx.app_idx = BT_MESH_KEY_DEV_LOCAL;
- bt_mesh_model_recv(rx, sdu);
- goto done;
- }
-
- if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- struct bt_mesh_node *node;
-
- /*
- * There is no way of knowing if we should use our
- * local DevKey or the remote DevKey to decrypt the
- * message so we must try both.
- */
-
- node = bt_mesh_node_find(rx->ctx.addr);
- if (node == NULL) {
- BT_ERR("No node found for addr 0x%04x",
- rx->ctx.addr);
- return -EINVAL;
- }
-
- net_buf_simple_init(sdu, 0);
- err = bt_mesh_app_decrypt(node->dev_key, true, aszmic,
- buf, sdu, ad, rx->ctx.addr,
- rx->ctx.recv_dst, seq,
- BT_MESH_NET_IVI_RX(rx));
- if (err) {
- BT_ERR("Unable to decrypt with node DevKey");
- return -EINVAL;
- }
-
- rx->ctx.app_idx = BT_MESH_KEY_DEV_REMOTE;
- bt_mesh_model_recv(rx, sdu);
- return 0;
- }
-
- return -EINVAL;
- }
-
- for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) {
- struct bt_mesh_app_key *key = &bt_mesh.app_keys[i];
- struct bt_mesh_app_keys *keys;
-
- /* Check that this AppKey matches received net_idx */
- if (key->net_idx != rx->sub->net_idx) {
- continue;
- }
-
- if (rx->new_key && key->updated) {
- keys = &key->keys[1];
- } else {
- keys = &key->keys[0];
- }
-
- /* Check that the AppKey ID matches */
- if (AID(&hdr) != keys->id) {
- continue;
- }
-
- net_buf_simple_init(sdu, 0);
- err = bt_mesh_app_decrypt(keys->val, false, aszmic, buf,
- sdu, ad, rx->ctx.addr,
- rx->ctx.recv_dst, seq,
- BT_MESH_NET_IVI_RX(rx));
- if (err) {
- BT_WARN("Unable to decrypt with AppKey 0x%03x",
- key->app_idx);
- continue;
-
- }
-
- rx->ctx.app_idx = key->app_idx;
-
- bt_mesh_model_recv(rx, sdu);
+ rx->ctx.app_idx = bt_mesh_app_key_find(ctx.crypto.dev_key, AID(&hdr),
+ rx, sdu_try_decrypt, &ctx);
+ if (rx->ctx.app_idx == BT_MESH_KEY_UNUSED) {
+ BT_DBG("No matching AppKey");
goto done;
}
- BT_WARN("No matching AppKey");
+ BT_DBG("Decrypted (AppIdx: 0x%03x)", rx->ctx.app_idx);
+
+ bt_mesh_model_recv(rx, sdu);
- err = -EINVAL;
done:
os_mbuf_free_chain(sdu);
- return err;
+ return 0;
}
-static struct seg_tx *seg_tx_lookup(u16_t seq_zero, u8_t obo, u16_t addr)
+static struct seg_tx *seg_tx_lookup(uint16_t seq_zero, uint8_t obo, uint16_t addr)
{
struct seg_tx *tx;
int i;
@@ -753,14 +791,14 @@ static struct seg_tx *seg_tx_lookup(u16_t seq_zero, u8_t obo, u16_t addr)
return NULL;
}
-static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
- struct os_mbuf *buf, u64_t *seq_auth)
+static int trans_ack(struct bt_mesh_net_rx *rx, uint8_t hdr,
+ struct os_mbuf *buf, uint64_t *seq_auth)
{
struct seg_tx *tx;
unsigned int bit;
- u32_t ack;
- u16_t seq_zero;
- u8_t obo;
+ uint32_t ack;
+ uint16_t seq_zero;
+ uint8_t obo;
if (buf->om_len < 6) {
BT_ERR("Too short ack message");
@@ -789,6 +827,11 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
return -EINVAL;
}
+ if (!BT_MESH_ADDR_IS_UNICAST(tx->dst)) {
+ BT_ERR("Received ack for group seg");
+ return -EINVAL;
+ }
+
*seq_auth = tx->seq_auth;
if (!ack) {
@@ -807,9 +850,7 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
while ((bit = find_lsb_set(ack))) {
if (tx->seg[bit - 1]) {
BT_DBG("seg %u/%u acked", bit - 1, tx->seg_n);
- net_buf_unref(tx->seg[bit - 1]);
- tx->seg[bit - 1] = NULL;
- tx->nack_count--;
+ seg_tx_done(tx, bit - 1);
}
ack &= ~BIT(bit - 1);
@@ -825,40 +866,10 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
return 0;
}
-static int trans_heartbeat(struct bt_mesh_net_rx *rx,
- struct os_mbuf *buf)
+static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr,
+ struct os_mbuf *buf, uint64_t *seq_auth)
{
- u8_t init_ttl, hops;
- u16_t feat;
-
- if (buf->om_len < 3) {
- BT_ERR("Too short heartbeat message");
- return -EINVAL;
- }
-
- if (rx->ctx.recv_dst != hb_sub_dst) {
- BT_WARN("Ignoring heartbeat to non-subscribed destination");
- return 0;
- }
-
- init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f);
- feat = net_buf_simple_pull_be16(buf);
-
- hops = (init_ttl - rx->ctx.recv_ttl + 1);
-
- BT_DBG("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x",
- rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops,
- (hops == 1) ? "" : "s", feat);
-
- bt_mesh_heartbeat(rx->ctx.addr, rx->ctx.recv_dst, hops, feat);
-
- return 0;
-}
-
-static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
- struct os_mbuf *buf, u64_t *seq_auth)
-{
- u8_t ctl_op = TRANS_CTL_OP(&hdr);
+ uint8_t ctl_op = TRANS_CTL_OP(&hdr);
BT_DBG("OpCode 0x%02x len %u", ctl_op, buf->om_len);
@@ -866,7 +877,7 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
case TRANS_CTL_OP_ACK:
return trans_ack(rx, hdr, buf, seq_auth);
case TRANS_CTL_OP_HEARTBEAT:
- return trans_heartbeat(rx, buf);
+ return bt_mesh_hb_recv(rx, buf);
}
/* Only acks and heartbeats may need processing without local_match */
@@ -921,9 +932,10 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, u8_t hdr,
}
static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
- u64_t *seq_auth)
+ uint64_t *seq_auth)
{
- u8_t hdr;
+ struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_SDU_UNSEG_MAX);
+ uint8_t hdr;
BT_DBG("AFK %u AID 0x%02x", AKF(buf->om_data), AID(buf->om_data));
@@ -932,7 +944,7 @@ static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
return -EINVAL;
}
- if (is_replay(rx, NULL)) {
+ 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, (unsigned) rx->seq);
return -EINVAL;
@@ -942,20 +954,23 @@ static int trans_unseg(struct os_mbuf *buf, struct bt_mesh_net_rx *rx,
if (rx->ctl) {
return ctl_recv(rx, hdr, buf, seq_auth);
- } else {
- /* SDUs must match a local element or an LPN of this Friend. */
- if (!rx->local_match && !rx->friend_match) {
- return 0;
- }
-
- return sdu_recv(rx, rx->seq, hdr, 0, buf);
}
+
+ if (buf->om_len < 1 + APP_MIC_LEN(0)) {
+ BT_ERR("Too short SDU + MIC");
+ return -EINVAL;
+ }
+
+ /* Adjust the length to not contain the MIC at the end */
+ buf->om_len -= APP_MIC_LEN(0);
+
+ return sdu_recv(rx, hdr, 0, buf, sdu, NULL);
}
-static inline s32_t ack_timeout(struct seg_rx *rx)
+static inline int32_t ack_timeout(struct seg_rx *rx)
{
- s32_t to;
- u8_t ttl;
+ int32_t to;
+ uint8_t ttl;
if (rx->ttl == BT_MESH_TTL_DEFAULT) {
ttl = bt_mesh_default_ttl_get();
@@ -977,45 +992,48 @@ static inline s32_t ack_timeout(struct seg_rx *rx)
return max(to, K_MSEC(400));
}
-int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
- size_t data_len, u64_t *seq_auth,
- const struct bt_mesh_send_cb *cb, void *cb_data)
+int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
+ size_t data_len, const struct bt_mesh_send_cb *cb, void *cb_data)
{
- struct os_mbuf *buf;
+ int err;
+ struct os_mbuf *buf = NET_BUF_SIMPLE(data_len);
+
+ net_buf_simple_init_with_data(buf, data, data_len);
+
+ if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) {
+ tx->ctx->send_ttl = bt_mesh_default_ttl_get();
+ } else if (tx->ctx->send_ttl > BT_MESH_TTL_MAX) {
+ BT_ERR("TTL too large (max 127)");
+ return -EINVAL;
+ }
+
+ if (data_len > BT_MESH_SDU_UNSEG_MAX) {
+ tx->ctx->send_rel = true;
+ }
+
+ tx->ctx->app_idx = BT_MESH_KEY_UNUSED;
+
+ if (tx->ctx->addr == BT_MESH_ADDR_UNASSIGNED ||
+ BT_MESH_ADDR_IS_VIRTUAL(tx->ctx->addr)) {
+ BT_ERR("Invalid destination address");
+ return -EINVAL;
+ }
BT_DBG("src 0x%04x dst 0x%04x ttl 0x%02x ctl 0x%02x", tx->src,
tx->ctx->addr, tx->ctx->send_ttl, ctl_op);
BT_DBG("len %zu: %s", data_len, bt_hex(data, data_len));
- buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, tx->xmit, BUF_TIMEOUT);
- if (!buf) {
- BT_ERR("Out of transport buffers");
- return -ENOBUFS;
+ if (tx->ctx->send_rel) {
+ err = send_seg(tx, buf, cb, cb_data, &ctl_op);
+ } else {
+ err = send_unseg(tx, buf, cb, cb_data, &ctl_op);
}
-
- net_buf_reserve(buf, BT_MESH_NET_HDR_LEN);
-
- net_buf_add_u8(buf, TRANS_CTL_HDR(ctl_op, 0));
-
- net_buf_add_mem(buf, data, data_len);
-
- if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
- if (bt_mesh_friend_enqueue_tx(tx, BT_MESH_FRIEND_PDU_SINGLE,
- seq_auth, 1, buf) &&
- BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) {
- /* PDUs for a specific Friend should only go
- * out through the Friend Queue.
- */
- net_buf_unref(buf);
- return 0;
- }
- }
-
- return bt_mesh_net_send(tx, buf, cb, cb_data);
+ os_mbuf_free_chain(buf);
+ return err;
}
-static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
- u8_t ttl, u64_t *seq_auth, u32_t block, u8_t obo)
+static int send_ack(struct bt_mesh_subnet *sub, uint16_t src, uint16_t dst,
+ uint8_t ttl, uint64_t *seq_auth, uint32_t block, uint8_t obo)
{
struct bt_mesh_msg_ctx ctx = {
.net_idx = sub->net_idx,
@@ -1029,8 +1047,8 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
.src = obo ? bt_mesh_primary_addr() : src,
.xmit = bt_mesh_net_transmit_get(),
};
- u16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK;
- u8_t buf[6];
+ uint16_t seq_zero = *seq_auth & TRANS_SEQ_ZERO_MASK;
+ uint8_t buf[6];
BT_DBG("SeqZero 0x%04x Block 0x%08x OBO %u", seq_zero,
(unsigned) block, obo);
@@ -1044,7 +1062,7 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
* or virtual address.
*/
if (!BT_MESH_ADDR_IS_UNICAST(src)) {
- BT_WARN("Not sending ack for non-unicast address");
+ BT_DBG("Not sending ack for non-unicast address");
return 0;
}
@@ -1052,11 +1070,13 @@ static int send_ack(struct bt_mesh_subnet *sub, u16_t src, u16_t dst,
sys_put_be32(block, &buf[2]);
return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_ACK, buf, sizeof(buf),
- NULL, NULL, NULL);
+ NULL, NULL);
}
static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
{
+ int i;
+
BT_DBG("rx %p", rx);
k_delayed_work_cancel(&rx->ack);
@@ -1068,6 +1088,15 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
&rx->seq_auth);
}
+ for (i = 0; i <= rx->seg_n; i++) {
+ if (!rx->seg[i]) {
+ continue;
+ }
+
+ k_mem_slab_free(&segs, &rx->seg[i]);
+ rx->seg[i] = NULL;
+ }
+
rx->in_use = 0;
/* We don't always reset these values since we need to be able to
@@ -1085,6 +1114,7 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
static void seg_ack(struct ble_npl_event *work)
{
struct seg_rx *rx = ble_npl_event_get_arg(work);
+ int32_t timeout;
BT_DBG("rx %p", rx);
@@ -1102,25 +1132,17 @@ static void seg_ack(struct ble_npl_event *work)
send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth,
rx->block, rx->obo);
- k_delayed_work_submit(&rx->ack, ack_timeout(rx));
+ timeout = ack_timeout(rx);
+ k_delayed_work_submit(&rx->ack, K_MSEC(timeout));
}
-static inline u8_t seg_len(bool ctl)
+static inline bool sdu_len_is_ok(bool ctl, uint8_t seg_n)
{
- if (ctl) {
- return 8;
- } else {
- return 12;
- }
-}
-
-static inline bool sdu_len_is_ok(bool ctl, u8_t seg_n)
-{
- return ((seg_n * seg_len(ctl) + 1) <= MYNEWT_VAL(BLE_MESH_RX_SDU_MAX));
+ return (seg_n < CONFIG_BT_MESH_RX_SEG_MAX);
}
static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
- const u64_t *seq_auth)
+ const uint64_t *seq_auth)
{
int i;
@@ -1157,7 +1179,7 @@ static struct seg_rx *seg_rx_find(struct bt_mesh_net_rx *net_rx,
}
static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
- const u8_t *hdr, u8_t seg_n)
+ const uint8_t *hdr, uint8_t seg_n)
{
if (rx->hdr != *hdr || rx->seg_n != seg_n) {
BT_ERR("Invalid segment for ongoing session");
@@ -1178,11 +1200,19 @@ static bool seg_rx_is_valid(struct seg_rx *rx, struct bt_mesh_net_rx *net_rx,
}
static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
- const u8_t *hdr, const u64_t *seq_auth,
- u8_t seg_n)
+ const uint8_t *hdr, const uint64_t *seq_auth,
+ uint8_t seg_n)
{
int i;
+ /* No race condition on this check, as this function only executes in
+ * the collaborative Bluetooth rx thread:
+ */
+ if (k_mem_slab_num_free_get(&segs) < 1) {
+ BT_WARN("Not enough segments for incoming message");
+ return NULL;
+ }
+
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
struct seg_rx *rx = &seg_rx[i];
@@ -1191,7 +1221,6 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
}
rx->in_use = 1;
- net_buf_simple_init(rx->buf, 0);
rx->sub = net_rx->sub;
rx->ctl = net_rx->ctl;
rx->seq_auth = *seq_auth;
@@ -1212,15 +1241,15 @@ static struct seg_rx *seg_rx_alloc(struct bt_mesh_net_rx *net_rx,
}
static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
- enum bt_mesh_friend_pdu_type *pdu_type, u64_t *seq_auth,
- u8_t *seg_count)
+ enum bt_mesh_friend_pdu_type *pdu_type, uint64_t *seq_auth,
+ uint8_t *seg_count)
{
struct bt_mesh_rpl *rpl = NULL;
struct seg_rx *rx;
- u8_t *hdr = buf->om_data;
- u16_t seq_zero;
- u8_t seg_n;
- u8_t seg_o;
+ uint8_t *hdr = buf->om_data;
+ uint16_t seq_zero;
+ uint8_t seg_n;
+ uint8_t seg_o;
int err;
if (buf->om_len < 5) {
@@ -1228,7 +1257,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
return -EINVAL;
}
- if (is_replay(net_rx, &rpl)) {
+ if (bt_mesh_rpl_check(net_rx, &rpl)) {
BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x",
net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq);
return -EINVAL;
@@ -1292,14 +1321,14 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
}
if (rx->block == BLOCK_COMPLETE(rx->seg_n)) {
- BT_WARN("Got segment for already complete SDU");
+ BT_DBG("Got segment for already complete SDU");
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);
if (rpl) {
- update_rpl(rpl, net_rx);
+ bt_mesh_rpl_update(rpl, net_rx);
}
return -EALREADY;
@@ -1353,7 +1382,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx,
found_rx:
if (BIT(seg_o) & rx->block) {
- BT_WARN("Received already received fragment");
+ BT_DBG("Received already received fragment");
return -EALREADY;
}
@@ -1363,11 +1392,11 @@ found_rx:
*/
if (seg_o == seg_n) {
/* Set the expected final buffer length */
- rx->buf->om_len = seg_n * seg_len(rx->ctl) + buf->om_len;
+ rx->len = seg_n * seg_len(rx->ctl) + buf->om_len;
BT_DBG("Target len %u * %u + %u = %u", seg_n, seg_len(rx->ctl),
- buf->om_len, rx->buf->om_len);
+ buf->om_len, rx->len);
- if (rx->buf->om_len > MYNEWT_VAL(BLE_MESH_RX_SDU_MAX)) {
+ if (rx->len > BT_MESH_RX_SDU_MAX) {
BT_ERR("Too large SDU len");
send_ack(net_rx->sub, net_rx->ctx.recv_dst,
net_rx->ctx.addr, net_rx->ctx.send_ttl,
@@ -1387,11 +1416,20 @@ found_rx:
if (!k_delayed_work_remaining_get(&rx->ack) &&
!bt_mesh_lpn_established()) {
- k_delayed_work_submit(&rx->ack, ack_timeout(rx));
+ int32_t timeout = ack_timeout(rx);
+
+ k_delayed_work_submit(&rx->ack, K_MSEC(timeout));
}
- /* Location in buffer can be calculated based on seg_o & rx->ctl */
- memcpy(rx->buf->om_data + (seg_o * seg_len(rx->ctl)), buf->om_data, buf->om_len);
+ /* Allocated segment here */
+ err = k_mem_slab_alloc(&segs, &rx->seg[seg_o]);
+ if (err) {
+ BT_WARN("Unable allocate buffer for Seg %u", seg_o);
+ return -ENOBUFS;
+ }
+
+ os_mbuf_copydata(buf, 0, buf->om_len, rx->seg[seg_o]);
+ BT_DBG("copied %s", bt_hex(rx->seg[seg_o], rx->len));
BT_DBG("Received %u/%u", seg_o, seg_n);
@@ -1406,7 +1444,7 @@ found_rx:
BT_DBG("Complete SDU");
if (rpl) {
- update_rpl(rpl, net_rx);
+ bt_mesh_rpl_update(rpl, net_rx);
}
*pdu_type = BT_MESH_FRIEND_PDU_COMPLETE;
@@ -1416,23 +1454,40 @@ found_rx:
net_rx->ctx.send_ttl, seq_auth, rx->block, rx->obo);
if (net_rx->ctl) {
- err = ctl_recv(net_rx, *hdr, rx->buf, seq_auth);
+ struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_RX_CTL_MAX);
+ seg_rx_assemble(rx, sdu, 0U);
+ err = ctl_recv(net_rx, *hdr, sdu, seq_auth);
+ } else if (rx->len < 1 + APP_MIC_LEN(ASZMIC(hdr))) {
+ BT_ERR("Too short SDU + MIC");
+ err = -EINVAL;
} else {
- err = sdu_recv(net_rx, (rx->seq_auth & 0xffffff), *hdr,
- ASZMIC(hdr), rx->buf);
+ struct os_mbuf *seg_buf = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX);
+ struct os_mbuf *sdu;
+
+ /* Decrypting in place to avoid creating two assembly buffers.
+ * We'll reassemble the buffer from the segments before each
+ * decryption attempt.
+ */
+ net_buf_simple_init(seg_buf, 0);
+
+ sdu = NET_BUF_SIMPLE(rx->len - APP_MIC_LEN(ASZMIC(hdr)));
+ net_buf_simple_init_with_data(
+ sdu, seg_buf->om_data, rx->len - APP_MIC_LEN(ASZMIC(hdr)));
+
+ err = sdu_recv(net_rx, *hdr, ASZMIC(hdr), seg_buf, sdu, rx);
+ os_mbuf_free_chain(seg_buf);
}
seg_rx_reset(rx, false);
-
return err;
}
int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx)
{
- u64_t seq_auth = TRANS_SEQ_AUTH_NVAL;
+ uint64_t seq_auth = TRANS_SEQ_AUTH_NVAL;
enum bt_mesh_friend_pdu_type pdu_type = BT_MESH_FRIEND_PDU_SINGLE;
struct net_buf_simple_state state;
- u8_t seg_count = 0;
+ uint8_t seg_count = 0;
int err;
if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) {
@@ -1527,28 +1582,43 @@ void bt_mesh_rx_reset(void)
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
seg_rx_reset(&seg_rx[i], true);
}
-
- if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
- bt_mesh_clear_rpl();
- } else {
- memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
- }
}
-void bt_mesh_tx_reset(void)
+void bt_mesh_trans_reset(void)
{
int i;
+ bt_mesh_rx_reset();
+
BT_DBG("");
for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
seg_tx_reset(&seg_tx[i]);
}
+
+ for (i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+ if (virtual_addrs[i].ref) {
+ virtual_addrs[i].ref = 0U;
+ virtual_addrs[i].changed = 1U;
+ }
+ }
+
+ bt_mesh_rpl_clear();
+
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_label();
+ }
}
void bt_mesh_trans_init(void)
{
- int i;
+ int i, rc;
+
+ /* We need to initialize memslab free list here */
+ rc = create_free_list(&segs);
+ if (rc) {
+ BT_ERR("Failed to create free memslab list")
+ }
for (i = 0; i < ARRAY_SIZE(seg_tx); i++) {
k_delayed_work_init(&seg_tx[i].retransmit, seg_retransmit);
@@ -1559,113 +1629,125 @@ void bt_mesh_trans_init(void)
* For now we increase MSYS_1_BLOCK_COUNT
*/
for (i = 0; i < ARRAY_SIZE(seg_rx); i++) {
- seg_rx[i].buf = NET_BUF_SIMPLE(MYNEWT_VAL(BLE_MESH_RX_SDU_MAX));
k_delayed_work_init(&seg_rx[i].ack, seg_ack);
k_delayed_work_add_arg(&seg_rx[i].ack, &seg_rx[i]);
}
}
-void bt_mesh_rpl_clear(void)
+struct bt_mesh_va *bt_mesh_va_get(uint16_t index)
{
- BT_DBG("");
- memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl));
+ if (index >= ARRAY_SIZE(virtual_addrs)) {
+ return NULL;
+ }
+
+ return &virtual_addrs[index];
}
-void bt_mesh_heartbeat_send(void)
+static inline void va_store(struct bt_mesh_va *store)
{
- struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get();
- u16_t feat = 0U;
- struct __packed {
- u8_t init_ttl;
- u16_t feat;
- } hb;
- struct bt_mesh_msg_ctx ctx = {
- .net_idx = cfg->hb_pub.net_idx,
- .app_idx = BT_MESH_KEY_UNUSED,
- .addr = cfg->hb_pub.dst,
- .send_ttl = cfg->hb_pub.ttl,
- };
- struct bt_mesh_net_tx tx = {
- .sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx),
- .ctx = &ctx,
- .src = bt_mesh_model_elem(cfg->model)->addr,
- .xmit = bt_mesh_net_transmit_get(),
- };
-
- /* Do nothing if heartbeat publication is not enabled */
- if (cfg->hb_pub.dst == BT_MESH_ADDR_UNASSIGNED) {
- return;
+ store->changed = 1U;
+ if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
+ bt_mesh_store_label();
}
-
- hb.init_ttl = cfg->hb_pub.ttl;
-
- if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) {
- feat |= BT_MESH_FEAT_RELAY;
- }
-
- if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) {
- feat |= BT_MESH_FEAT_PROXY;
- }
-
- if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) {
- feat |= BT_MESH_FEAT_FRIEND;
- }
-
- if (bt_mesh_lpn_established()) {
- feat |= BT_MESH_FEAT_LOW_POWER;
- }
-
- hb.feat = sys_cpu_to_be16(feat);
-
- BT_DBG("InitTTL %u feat 0x%04x", cfg->hb_pub.ttl, feat);
-
- bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb),
- NULL, NULL, NULL);
}
-int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
- u16_t addr, const u8_t **key, u8_t *aid)
+uint8_t bt_mesh_va_add(uint8_t uuid[16], uint16_t *addr)
{
- struct bt_mesh_app_key *app_key;
+ struct bt_mesh_va *va = NULL;
+ int err;
- if (app_idx == BT_MESH_KEY_DEV_LOCAL ||
- (app_idx == BT_MESH_KEY_DEV_REMOTE &&
- bt_mesh_elem_find(addr) != NULL)) {
- *aid = 0;
- *key = bt_mesh.dev_key;
- return 0;
- } else if (app_idx == BT_MESH_KEY_DEV_REMOTE) {
- if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) {
- return -EINVAL;
+ for (int i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+ if (!virtual_addrs[i].ref) {
+ if (!va) {
+ va = &virtual_addrs[i];
+ }
+
+ continue;
}
- struct bt_mesh_node *node = bt_mesh_node_find(addr);
- if (!node) {
- return -EINVAL;
+ if (!memcmp(uuid, virtual_addrs[i].uuid,
+ ARRAY_SIZE(virtual_addrs[i].uuid))) {
+ *addr = virtual_addrs[i].addr;
+ virtual_addrs[i].ref++;
+ va_store(&virtual_addrs[i]);
+ return STATUS_SUCCESS;
}
-
- *key = node->dev_key;
- *aid = 0;
- return 0;
}
- if (!subnet) {
- return -EINVAL;
+ if (!va) {
+ return STATUS_INSUFF_RESOURCES;
}
- app_key = bt_mesh_app_key_find(app_idx);
- if (!app_key) {
- return -ENOENT;
+ memcpy(va->uuid, uuid, ARRAY_SIZE(va->uuid));
+ err = bt_mesh_virtual_addr(uuid, &va->addr);
+ if (err) {
+ va->addr = BT_MESH_ADDR_UNASSIGNED;
+ return STATUS_UNSPECIFIED;
}
- if (subnet->kr_phase == BT_MESH_KR_PHASE_2 && app_key->updated) {
- *key = app_key->keys[1].val;
- *aid = app_key->keys[1].id;
- } else {
- *key = app_key->keys[0].val;
- *aid = app_key->keys[0].id;
+ va->ref = 1;
+ va_store(va);
+
+ *addr = va->addr;
+
+ return STATUS_SUCCESS;
+}
+
+uint8_t bt_mesh_va_del(uint8_t uuid[16], uint16_t *addr)
+{
+ struct bt_mesh_va *va = NULL;
+
+ 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))) {
+ va = &virtual_addrs[i];
+ break;
+ }
}
- return 0;
+ if (!va) {
+ return STATUS_CANNOT_REMOVE;
+ }
+
+ va->ref--;
+ if (addr) {
+ *addr = va->addr;
+ }
+
+ va_store(va);
+ 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;
+
+ BT_DBG("addr 0x%04x", addr);
+
+ for (i = 0; i < ARRAY_SIZE(virtual_addrs); i++) {
+ if (virtual_addrs[i].ref && virtual_addrs[i].addr == addr) {
+ BT_DBG("Found Label UUID for 0x%04x: %s", addr,
+ bt_hex(virtual_addrs[i].uuid, 16));
+ return virtual_addrs[i].uuid;
+ }
+ }
+
+ BT_WARN("No matching Label UUID for 0x%04x", addr);
+
+ return NULL;
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h
index 227ba5922..049660967 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/mesh/src/transport.h
@@ -11,10 +11,12 @@
#define TRANS_SEQ_AUTH_NVAL 0xffffffffffffffff
-#define BT_MESH_TX_SDU_MAX (CONFIG_BT_MESH_TX_SEG_MAX * 12)
+#define BT_MESH_SDU_UNSEG_MAX 11
+#define BT_MESH_CTL_SEG_SDU_MAX 8
+#define BT_MESH_RX_CTL_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_CTL_SEG_SDU_MAX)
-#define TRANS_SEQ_ZERO_MASK ((u16_t)BIT_MASK(13))
-#define TRANS_CTL_OP_MASK ((u8_t)BIT_MASK(7))
+#define TRANS_SEQ_ZERO_MASK ((uint16_t)BIT_MASK(13))
+#define TRANS_CTL_OP_MASK ((uint8_t)BIT_MASK(7))
#define TRANS_CTL_OP(data) ((data)[0] & TRANS_CTL_OP_MASK)
#define TRANS_CTL_HDR(op, seg) ((op & TRANS_CTL_OP_MASK) | (seg << 7))
@@ -31,64 +33,65 @@
#define TRANS_CTL_OP_HEARTBEAT 0x0a
struct bt_mesh_ctl_friend_poll {
- u8_t fsn;
+ uint8_t fsn;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_update {
- u8_t flags;
- u32_t iv_index;
- u8_t md;
+ uint8_t flags;
+ uint32_t iv_index;
+ uint8_t md;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_req {
- u8_t criteria;
- u8_t recv_delay;
- u8_t poll_to[3];
- u16_t prev_addr;
- u8_t num_elem;
- u16_t lpn_counter;
+ uint8_t criteria;
+ uint8_t recv_delay;
+ uint8_t poll_to[3];
+ uint16_t prev_addr;
+ uint8_t num_elem;
+ uint16_t lpn_counter;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_offer {
- u8_t recv_win;
- u8_t queue_size;
- u8_t sub_list_size;
- s8_t rssi;
- u16_t frnd_counter;
+ uint8_t recv_win;
+ uint8_t queue_size;
+ uint8_t sub_list_size;
+ int8_t rssi;
+ uint16_t frnd_counter;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_clear {
- u16_t lpn_addr;
- u16_t lpn_counter;
+ uint16_t lpn_addr;
+ uint16_t lpn_counter;
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_clear_confirm {
- u16_t lpn_addr;
- u16_t lpn_counter;
+ uint16_t lpn_addr;
+ uint16_t lpn_counter;
}__attribute__((__packed__));
#define BT_MESH_FRIEND_SUB_MIN_LEN (1 + 2)
struct bt_mesh_ctl_friend_sub {
- u8_t xact;
- u16_t addr_list[5];
+ uint8_t xact;
+ uint16_t addr_list[5];
}__attribute__((__packed__));
struct bt_mesh_ctl_friend_sub_confirm {
- u8_t xact;
+ uint8_t xact;
}__attribute__((__packed__));
-void bt_mesh_set_hb_sub_dst(u16_t addr);
-
-struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx);
+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);
-void bt_mesh_tx_reset(void);
-int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,
- size_t data_len, u64_t *seq_auth,
- const struct bt_mesh_send_cb *cb, void *cb_data);
+int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data,
+ size_t data_len, const struct bt_mesh_send_cb *cb, void *cb_data);
int bt_mesh_trans_send(struct bt_mesh_net_tx *tx, struct os_mbuf *msg,
const struct bt_mesh_send_cb *cb, void *cb_data);
@@ -97,9 +100,14 @@ int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx);
void bt_mesh_trans_init(void);
-void bt_mesh_rpl_clear(void);
+void bt_mesh_trans_reset(void);
-void bt_mesh_heartbeat_send(void);
+struct bt_mesh_va *bt_mesh_va_get(uint16_t index);
-int bt_mesh_app_key_get(const struct bt_mesh_subnet *subnet, u16_t app_idx,
- u16_t addr, const u8_t **key, u8_t *aid);
+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_del(uint8_t uuid[16], uint16_t *addr);
+
+uint8_t *bt_mesh_va_label_get(uint16_t addr);
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
index 2706b5d36..24b9a26c1 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h
@@ -28,4 +28,6 @@
int ble_svc_bas_battery_level_set(uint8_t level);
+void ble_svc_bas_init(void);
+
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
index d7b60df44..707a3bd0c 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h
@@ -34,6 +34,7 @@ extern "C" {
#define BLE_SVC_GAP_APPEARANCE_GEN_UNKNOWN 0
#define BLE_SVC_GAP_APPEARANCE_GEN_COMPUTER 128
+#define BLE_SVC_GAP_APPEARANCE_GEN_HID 960
#define BLE_SVC_GAP_APPEARANCE_CYC_SPEED_AND_CADENCE_SENSOR 1157
typedef void (ble_svc_gap_chr_changed_fn) (uint16_t uuid);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c
index f1cf2d9ba..ab057ea73 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c
@@ -41,6 +41,7 @@ static char ble_svc_gap_name[BLE_SVC_GAP_NAME_MAX_LEN + 1] =
MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME);
static uint16_t ble_svc_gap_appearance = MYNEWT_VAL(BLE_SVC_GAP_APPEARANCE);
+#if NIMBLE_BLE_CONNECT
static int
ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg);
@@ -239,6 +240,7 @@ ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle,
return BLE_ATT_ERR_UNLIKELY;
}
}
+#endif
const char *
ble_svc_gap_device_name(void)
@@ -285,14 +287,18 @@ ble_svc_gap_set_chr_changed_cb(ble_svc_gap_chr_changed_fn *cb)
void
ble_svc_gap_init(void)
{
+#if NIMBLE_BLE_CONNECT
int rc;
+#endif
/* Ensure this function only gets called by sysinit. */
SYSINIT_ASSERT_ACTIVE();
+#if NIMBLE_BLE_CONNECT
rc = ble_gatts_count_cfg(ble_svc_gap_defs);
SYSINIT_PANIC_ASSERT(rc == 0);
rc = ble_gatts_add_svcs(ble_svc_gap_defs);
SYSINIT_PANIC_ASSERT(rc == 0);
+#endif
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att.c
index cc7a1f115..8aab7f919 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att.c
@@ -21,6 +21,7 @@
#include
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
static uint16_t ble_att_preferred_mtu_val;
/** Dispatch table for incoming ATT requests. Sorted by op code. */
@@ -587,3 +588,5 @@ ble_att_init(void)
return 0;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c
index 2416ecbcb..a61def73e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_clt.c
@@ -26,6 +26,7 @@
#include "nimble/nimble/host/include/host/ble_uuid.h"
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
/*****************************************************************************
* $error response *
*****************************************************************************/
@@ -954,3 +955,5 @@ ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom)
ble_gattc_rx_indicate_rsp(conn_handle);
return 0;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c
index 4c3af1f60..452113b9e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_cmd.c
@@ -26,6 +26,7 @@
#include "nimble/nimble/host/include/host/ble_uuid.h"
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
void *
ble_att_cmd_prepare(uint8_t opcode, size_t len, struct os_mbuf *txom)
{
@@ -634,3 +635,5 @@ ble_att_indicate_rsp_write(void *payload, int len)
ble_att_init_write(BLE_ATT_OP_INDICATE_RSP, payload,
BLE_ATT_INDICATE_RSP_SZ, len);
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c
index 73172ef73..fb96c72fc 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_att_svr.c
@@ -29,6 +29,7 @@
#include "nimble/esp_port/port/include/esp_nimble_mem.h"
#endif
+#if NIMBLE_BLE_CONNECT
/**
* ATT server - Attribute Protocol
*
@@ -1364,7 +1365,7 @@ done:
*att_err = 0;
/* Fill the response base. */
- rsp->batp_length = htole16(sizeof(*data) + prev_attr_len);
+ rsp->batp_length = sizeof(*data) + prev_attr_len;
}
*out_txom = txom;
@@ -2745,3 +2746,5 @@ ble_att_svr_init(void)
return 0;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c
index 8b18360c9..1d4ffb444 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap.c
@@ -114,7 +114,9 @@ struct ble_gap_connect_reattempt_ctxt {
};
static struct ble_gap_connect_reattempt_ctxt ble_conn_reattempt[MYNEWT_VAL(BLE_MAX_CONNECTIONS)];
+#if !MYNEWT_VAL(BLE_EXT_ADV)
static uint16_t reattempt_idx;
+#endif
static bool conn_cookie_enabled;
#endif
@@ -241,7 +243,9 @@ ble_gap_update_entry_remove(uint16_t conn_handle);
static int ble_gap_adv_enable_tx(int enable);
#endif
+#if NIMBLE_BLE_CONNECT
static int ble_gap_conn_cancel_tx(void);
+#endif
#if NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)
static int ble_gap_disc_enable_tx(int enable, int filter_duplicates);
@@ -403,6 +407,7 @@ ble_gap_log_adv(uint8_t own_addr_type, const ble_addr_t *direct_addr,
* $snapshot *
*****************************************************************************/
+#if NIMBLE_BLE_CONNECT
static void
ble_gap_fill_conn_desc(struct ble_hs_conn *conn,
struct ble_gap_conn_desc *desc)
@@ -476,16 +481,14 @@ ble_gap_find_snapshot(uint16_t handle, struct ble_gap_snapshot *snap)
return 0;
}
}
+#endif
int
ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc)
{
+#if NIMBLE_BLE_CONNECT
struct ble_hs_conn *conn;
- if (!ble_hs_is_enabled()) {
- return BLE_HS_EDISABLED;
- }
-
ble_hs_lock();
conn = ble_hs_conn_find(handle);
@@ -500,12 +503,16 @@ ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc)
} else {
return 0;
}
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
int
ble_gap_conn_find_by_addr(const ble_addr_t *addr,
struct ble_gap_conn_desc *out_desc)
{
+#if NIMBLE_BLE_CONNECT
struct ble_hs_conn *conn;
if (!ble_hs_is_enabled()) {
@@ -526,8 +533,12 @@ ble_gap_conn_find_by_addr(const ble_addr_t *addr,
}
return 0;
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
+#if NIMBLE_BLE_CONNECT
static int
ble_gap_extract_conn_cb(uint16_t conn_handle,
ble_gap_event_fn **out_cb, void **out_cb_arg)
@@ -555,20 +566,26 @@ ble_gap_extract_conn_cb(uint16_t conn_handle,
return 0;
}
}
+#endif
int
ble_gap_set_priv_mode(const ble_addr_t *peer_addr, uint8_t priv_mode)
{
+#if NIMBLE_BLE_CONNECT
if (!ble_hs_is_enabled()) {
return BLE_HS_EDISABLED;
}
return ble_hs_pvcy_set_mode(peer_addr, priv_mode);
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
int
ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy)
{
+#if NIMBLE_BLE_CONNECT
struct ble_hci_le_rd_phy_cp cmd;
struct ble_hci_le_rd_phy_rp rsp;
struct ble_hs_conn *conn;
@@ -603,11 +620,15 @@ ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy)
*rx_phy = rsp.rx_phy;
return 0;
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
int
ble_gap_set_prefered_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask)
{
+#if NIMBLE_BLE_CONNECT
struct ble_hci_le_set_default_phy_cp cmd;
if (tx_phys_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK |
@@ -643,12 +664,16 @@ ble_gap_set_prefered_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask)
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_DEFAULT_PHY),
&cmd, sizeof(cmd), NULL, 0);
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
int
ble_gap_set_prefered_le_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
uint8_t rx_phys_mask, uint16_t phy_opts)
{
+#if NIMBLE_BLE_CONNECT
struct ble_hci_le_set_phy_cp cmd;
struct ble_hs_conn *conn;
@@ -699,6 +724,9 @@ ble_gap_set_prefered_le_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PHY),
&cmd, sizeof(cmd), NULL, 0);
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
/*****************************************************************************
@@ -730,7 +758,7 @@ ble_gap_call_event_cb(struct ble_gap_event *event,
return rc;
}
-
+#if NIMBLE_BLE_CONNECT
static int
ble_gap_call_conn_event_cb(struct ble_gap_event *event, uint16_t conn_handle)
{
@@ -750,28 +778,32 @@ ble_gap_call_conn_event_cb(struct ble_gap_event *event, uint16_t conn_handle)
return 0;
}
+#endif
static bool
ble_gap_is_preempted(void)
{
+#if NIMBLE_BLE_ADVERTISE
int i;
-
+#endif
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
+#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER)
if (ble_gap_master.preempted_op != BLE_GAP_OP_NULL) {
return true;
}
-
+#endif
+#if NIMBLE_BLE_ADVERTISE
for (i = 0; i < BLE_ADV_INSTANCES; i++) {
if (ble_gap_slave[i].preempted) {
return true;
}
}
-
+#endif
return false;
}
-#if NIMBLE_BLE_CONNECT
+#if MYNEWT_VAL(BLE_ROLE_OBSERVER) || NIMBLE_BLE_CONNECT
static void
ble_gap_master_reset_state(void)
{
@@ -783,6 +815,7 @@ ble_gap_master_reset_state(void)
}
#endif
+#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT
static void
ble_gap_slave_reset_state(uint8_t instance)
{
@@ -793,8 +826,9 @@ ble_gap_slave_reset_state(uint8_t instance)
ble_hs_timer_resched();
#endif
}
+#endif
-#if NIMBLE_BLE_CONNECT
+#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER)
static bool
ble_gap_has_client(struct ble_gap_master_state *out_state)
{
@@ -802,9 +836,11 @@ ble_gap_has_client(struct ble_gap_master_state *out_state)
return 0;
}
- return out_state->cb;
+ return out_state->cb != NULL;
}
+#endif
+#if MYNEWT_VAL(BLE_ROLE_OBSERVER) || NIMBLE_BLE_CONNECT
static void
ble_gap_master_extract_state(struct ble_gap_master_state *out_state,
int reset_state)
@@ -822,6 +858,7 @@ ble_gap_master_extract_state(struct ble_gap_master_state *out_state,
}
#endif
+#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT
static void
ble_gap_slave_extract_cb(uint8_t instance,
ble_gap_event_fn **out_cb, void **out_cb_arg)
@@ -859,6 +896,7 @@ ble_gap_adv_finished(uint8_t instance, int reason, uint16_t conn_handle,
cb(&event, cb_arg);
}
}
+#endif
#if NIMBLE_BLE_CONNECT
static int
@@ -1019,22 +1057,27 @@ ble_gap_disc_report(void *desc)
static void
ble_gap_disc_complete(void)
{
+#if NIMBLE_BLE_CONNECT
struct ble_gap_master_state state;
+#endif
struct ble_gap_event event;
memset(&event, 0, sizeof event);
event.type = BLE_GAP_EVENT_DISC_COMPLETE;
event.disc_complete.reason = 0;
+#if NIMBLE_BLE_CONNECT
ble_gap_master_extract_state(&state, 1);
if (ble_gap_has_client(&state)) {
ble_gap_call_event_cb(&event, state.cb, state.cb_arg);
}
+#endif
ble_gap_event_listener_call(&event);
}
#endif
+#if NIMBLE_BLE_CONNECT
static void
ble_gap_update_notify(uint16_t conn_handle, int status)
{
@@ -1053,6 +1096,7 @@ ble_gap_update_notify(uint16_t conn_handle, int status)
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
}
+#endif
static uint32_t
ble_gap_master_ticks_until_exp(void)
@@ -1142,7 +1186,7 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now)
}
-#if MYNEWT_VAL(BLE_ROLE_CENTRAL)
+#if NIMBLE_BLE_SCAN
static void
ble_gap_master_set_timer(uint32_t ticks_from_now)
{
@@ -1164,7 +1208,7 @@ ble_gap_slave_set_timer(uint32_t ticks_from_now)
}
#endif
-#if NIMBLE_BLE_CONNECT
+#if (NIMBLE_BLE_CONNECT || NIMBLE_BLE_SCAN)
/**
* Called when an error is encountered while the master-connection-fsm is
* active.
@@ -1173,10 +1217,12 @@ static void
ble_gap_master_failed(int status)
{
switch (ble_gap_master.op) {
+#if NIMBLE_BLE_CONNECT
case BLE_GAP_OP_M_CONN:
STATS_INC(ble_gap_stats, initiate_fail);
ble_gap_master_connect_failure(status);
break;
+#endif
#if NIMBLE_BLE_SCAN
case BLE_GAP_OP_M_DISC:
@@ -1191,7 +1237,9 @@ ble_gap_master_failed(int status)
break;
}
}
+#endif
+#if NIMBLE_BLE_CONNECT
static void
ble_gap_update_failed(uint16_t conn_handle, int status)
{
@@ -1212,6 +1260,7 @@ ble_gap_update_failed(uint16_t conn_handle, int status)
void
ble_gap_conn_broken(uint16_t conn_handle, int reason)
{
+#if NIMBLE_BLE_CONNECT
struct ble_gap_update_entry *entry;
struct ble_gap_snapshot snap;
struct ble_gap_event event;
@@ -1257,6 +1306,7 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason)
ble_gap_call_event_cb(&event, snap.cb, snap.cb_arg);
STATS_INC(ble_gap_stats, disconnect);
+#endif
}
#if NIMBLE_BLE_CONNECT
@@ -1379,19 +1429,25 @@ ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *e
int
ble_gap_master_in_progress(void)
{
+#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER)
return ble_gap_master.op != BLE_GAP_OP_NULL;
+#else
+ return false;
+#endif
}
+#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT
static int
ble_gap_adv_active_instance(uint8_t instance)
{
/* Assume read is atomic; mutex not necessary. */
return ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV;
}
+#endif
/**
* Clears advertisement and discovery state. This function is necessary
- * when the controller loses its active state (e.g. on host stack reset).
+ * when the controller loses its active state (e.g. on stack reset).
*/
void
ble_gap_reset_state(int reason)
@@ -1998,6 +2054,7 @@ int
ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
struct ble_gap_upd_params *params)
{
+#if NIMBLE_BLE_CONNECT
struct ble_gap_event event;
int rc;
@@ -2008,11 +2065,15 @@ ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
rc = ble_gap_call_conn_event_cb(&event, conn_handle);
return rc;
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
void
ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_complete *ev)
{
+#if NIMBLE_BLE_CONNECT
struct ble_gap_event event;
uint16_t conn_handle = le16toh(ev->conn_handle);
@@ -2025,13 +2086,16 @@ ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_compl
ble_gap_event_listener_call(&event);
ble_gap_call_conn_event_cb(&event, conn_handle);
+#endif
}
static int32_t
ble_gap_master_timer(void)
{
uint32_t ticks_until_exp;
+#if NIMBLE_BLE_SCAN || NIMBLE_BLE_CONNECT
int rc;
+#endif
ticks_until_exp = ble_gap_master_ticks_until_exp();
if (ticks_until_exp != 0) {
@@ -2042,6 +2106,7 @@ ble_gap_master_timer(void)
/*** Timer expired; process event. */
switch (ble_gap_master.op) {
+#if NIMBLE_BLE_CONNECT
case BLE_GAP_OP_M_CONN:
rc = ble_gap_conn_cancel_tx();
if (rc != 0) {
@@ -2059,6 +2124,7 @@ ble_gap_master_timer(void)
*/
}
break;
+#endif
case BLE_GAP_OP_M_DISC:
#if NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)
@@ -2145,12 +2211,9 @@ ble_gap_update_timer(void)
int
ble_gap_set_event_cb(uint16_t conn_handle, ble_gap_event_fn *cb, void *cb_arg)
{
+#if NIMBLE_BLE_CONNECT
struct ble_hs_conn *conn;
- if (!ble_hs_is_enabled()) {
- return BLE_HS_EDISABLED;
- }
-
ble_hs_lock();
conn = ble_hs_conn_find(conn_handle);
@@ -2166,6 +2229,9 @@ ble_gap_set_event_cb(uint16_t conn_handle, ble_gap_event_fn *cb, void *cb_arg)
}
return 0;
+#else
+ return BLE_HS_ENOTCONN;
+#endif
}
/**
@@ -2754,10 +2820,6 @@ ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields)
uint8_t buf_sz;
int rc;
- if (!ble_hs_is_enabled()) {
- return BLE_HS_EDISABLED;
- }
-
rc = ble_hs_adv_set_fields(rsp_fields, buf, &buf_sz, sizeof buf);
if (rc != 0) {
return rc;
@@ -2777,7 +2839,11 @@ ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields)
int
ble_gap_adv_active(void)
{
+#if NIMBLE_BLE_ADVERTISE
return ble_gap_adv_active_instance(0);
+#else
+ return 0;
+#endif
}
#if MYNEWT_VAL(BLE_EXT_ADV)
@@ -3802,7 +3868,7 @@ ble_gap_periodic_adv_stop(uint8_t instance)
return rc;
}
-static void
+void
ble_gap_npl_sync_lost(struct ble_npl_event *ev)
{
struct ble_hs_periodic_sync *psync;
@@ -4778,8 +4844,12 @@ done:
int
ble_gap_disc_active(void)
{
+#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER)
/* Assume read is atomic; mutex not necessary. */
return ble_gap_master.op == BLE_GAP_OP_M_DISC;
+#else
+ return 0;
+#endif
}
#if MYNEWT_VAL(BLE_ROLE_CENTRAL) && !MYNEWT_VAL(BLE_EXT_ADV)
@@ -4852,8 +4922,7 @@ ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params)
}
/* Check connection latency */
- if ((params->latency < BLE_HCI_CONN_LATENCY_MIN) ||
- (params->latency > BLE_HCI_CONN_LATENCY_MAX)) {
+ if (params->latency > BLE_HCI_CONN_LATENCY_MAX) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
@@ -5310,8 +5379,12 @@ done:
int
ble_gap_conn_active(void)
{
+#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER)
/* Assume read is atomic; mutex not necessary. */
return ble_gap_master.op == BLE_GAP_OP_M_CONN;
+#else
+ return 0;
+#endif
}
/*****************************************************************************
@@ -5320,6 +5393,7 @@ ble_gap_conn_active(void)
int
ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason)
{
+#if NIMBLE_BLE_CONNECT
struct ble_hci_lc_disconnect_cp cmd;
int rc;
@@ -5344,11 +5418,15 @@ ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason)
conn->bhc_flags |= BLE_HS_CONN_F_TERMINATING;
return 0;
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
int
ble_gap_terminate(uint16_t conn_handle, uint8_t hci_reason)
{
+#if NIMBLE_BLE_CONNECT
struct ble_hs_conn *conn;
int rc;
@@ -5375,12 +5453,16 @@ done:
STATS_INC(ble_gap_stats, terminate_fail);
}
return rc;
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
/*****************************************************************************
* $cancel *
*****************************************************************************/
+#if NIMBLE_BLE_CONNECT
static int
ble_gap_conn_cancel_tx(void)
{
@@ -5396,7 +5478,6 @@ ble_gap_conn_cancel_tx(void)
return 0;
}
-#if NIMBLE_BLE_CONNECT
static int
ble_gap_conn_cancel_no_lock(void)
{
@@ -5779,6 +5860,16 @@ int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_t
return ble_hs_hci_util_set_data_len(conn_handle, tx_octets, tx_time);
}
+int ble_gap_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets, uint16_t *out_sugg_max_tx_time)
+{
+ return ble_hs_hci_util_read_sugg_def_data_len(out_sugg_max_tx_octets, out_sugg_max_tx_time);
+}
+
+int ble_gap_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_t sugg_max_tx_time)
+{
+ return ble_hs_hci_util_write_sugg_def_data_len(sugg_max_tx_octets, sugg_max_tx_time);
+}
+
/*****************************************************************************
* $security *
*****************************************************************************/
@@ -5906,6 +5997,7 @@ ble_gap_encryption_initiate(uint16_t conn_handle,
int
ble_gap_unpair(const ble_addr_t *peer_addr)
{
+#if NIMBLE_BLE_SM
struct ble_hs_conn *conn;
if (!ble_hs_is_enabled()) {
@@ -5929,11 +6021,15 @@ ble_gap_unpair(const ble_addr_t *peer_addr)
peer_addr->val);
return ble_store_util_delete_peer(peer_addr);
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
int
ble_gap_unpair_oldest_peer(void)
{
+#if NIMBLE_BLE_SM
ble_addr_t oldest_peer_id_addr;
int num_peers;
int rc;
@@ -5949,7 +6045,7 @@ ble_gap_unpair_oldest_peer(void)
}
if (num_peers == 0) {
- return 0;
+ return BLE_HS_ENOENT;
}
rc = ble_gap_unpair(&oldest_peer_id_addr);
@@ -5958,11 +6054,15 @@ ble_gap_unpair_oldest_peer(void)
}
return 0;
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
int
ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr)
{
+#if NIMBLE_BLE_SM
ble_addr_t peer_id_addrs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
int num_peers;
int rc, i;
@@ -5992,13 +6092,16 @@ ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr)
}
return ble_gap_unpair(&peer_id_addrs[i]);
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
void
ble_gap_passkey_event(uint16_t conn_handle,
struct ble_gap_passkey_params *passkey_params)
{
-#if NIMBLE_BLE_SM
+#if NIMBLE_BLE_SM && NIMBLE_BLE_CONNECT
struct ble_gap_event event;
BLE_HS_LOG(DEBUG, "send passkey action request %d\n",
@@ -6016,7 +6119,7 @@ void
ble_gap_enc_event(uint16_t conn_handle, int status,
int security_restored, int bonded)
{
-#if NIMBLE_BLE_SM
+#if NIMBLE_BLE_SM && NIMBLE_BLE_CONNECT
struct ble_gap_event event;
memset(&event, 0, sizeof event);
@@ -6052,7 +6155,7 @@ ble_gap_enc_event(uint16_t conn_handle, int status,
void
ble_gap_identity_event(uint16_t conn_handle)
{
-#if NIMBLE_BLE_SM
+#if NIMBLE_BLE_SM && NIMBLE_BLE_CONNECT
struct ble_gap_event event;
BLE_HS_LOG(DEBUG, "send identity changed");
@@ -6067,7 +6170,7 @@ ble_gap_identity_event(uint16_t conn_handle)
int
ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp)
{
-#if NIMBLE_BLE_SM
+#if NIMBLE_BLE_SM && NIMBLE_BLE_CONNECT
struct ble_gap_event event;
int rc;
@@ -6106,9 +6209,7 @@ void
ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
struct os_mbuf *om, int is_indication)
{
-#if !MYNEWT_VAL(BLE_GATT_NOTIFY) && !MYNEWT_VAL(BLE_GATT_INDICATE)
- return;
-#endif
+#if (MYNEWT_VAL(BLE_GATT_NOTIFY) || MYNEWT_VAL(BLE_GATT_INDICATE)) && NIMBLE_BLE_CONNECT
struct ble_gap_event event;
@@ -6122,13 +6223,14 @@ ble_gap_notify_rx_event(uint16_t conn_handle, uint16_t attr_handle,
ble_gap_call_conn_event_cb(&event, conn_handle);
os_mbuf_free_chain(event.notify_rx.om);
+#endif
}
void
ble_gap_notify_tx_event(int status, uint16_t conn_handle, uint16_t attr_handle,
int is_indication)
{
-#if MYNEWT_VAL(BLE_GATT_NOTIFY) || MYNEWT_VAL(BLE_GATT_INDICATE)
+#if (MYNEWT_VAL(BLE_GATT_NOTIFY) || MYNEWT_VAL(BLE_GATT_INDICATE)) && NIMBLE_BLE_CONNECT
struct ble_gap_event event;
memset(&event, 0, sizeof event);
@@ -6152,6 +6254,7 @@ ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
uint8_t prev_notify, uint8_t cur_notify,
uint8_t prev_indicate, uint8_t cur_indicate)
{
+#if NIMBLE_BLE_CONNECT
struct ble_gap_event event;
BLE_HS_DBG_ASSERT(prev_notify != cur_notify ||
@@ -6172,6 +6275,7 @@ ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
ble_gap_event_listener_call(&event);
ble_gap_call_conn_event_cb(&event, conn_handle);
+#endif
}
/*****************************************************************************
@@ -6181,6 +6285,7 @@ ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
void
ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu)
{
+#if NIMBLE_BLE_CONNECT
struct ble_gap_event event;
memset(&event, 0, sizeof event);
@@ -6191,6 +6296,7 @@ ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu)
ble_gap_event_listener_call(&event);
ble_gap_call_conn_event_cb(&event, conn_handle);
+#endif
}
/*****************************************************************************
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h
index 3767ddba8..218501ed9 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gap_priv.h
@@ -136,6 +136,7 @@ void ble_gap_preempt(void);
void ble_gap_preempt_done(void);
int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason);
+void ble_gap_reset_state(int reason);
void ble_gap_conn_broken(uint16_t conn_handle, int reason);
void ble_gap_reset_state(int reason);
int32_t ble_gap_timer(void);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c
index f7bc9f47f..29c345773 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gattc.c
@@ -60,6 +60,7 @@
#include "nimble/nimble/host/include/host/ble_gap.h"
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
/*****************************************************************************
* $definitions / declarations *
*****************************************************************************/
@@ -697,12 +698,16 @@ ble_gattc_proc_free(struct ble_gattc_proc *proc)
switch (proc->op) {
case BLE_GATT_OP_WRITE_LONG:
- os_mbuf_free_chain(proc->write_long.attr.om);
+ if (MYNEWT_VAL(BLE_GATT_WRITE_LONG)) {
+ os_mbuf_free_chain(proc->write_long.attr.om);
+ }
break;
case BLE_GATT_OP_WRITE_RELIABLE:
- for (i = 0; i < proc->write_reliable.num_attrs; i++) {
- os_mbuf_free_chain(proc->write_reliable.attrs[i].om);
+ if (MYNEWT_VAL(BLE_GATT_WRITE_RELIABLE)) {
+ for (i = 0; i < proc->write_reliable.num_attrs; i++) {
+ os_mbuf_free_chain(proc->write_reliable.attrs[i].om);
+ }
}
break;
@@ -4804,3 +4809,5 @@ ble_gattc_init(void)
return 0;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c
index 989eb5c27..a1000255e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_gatts_lcl.c
@@ -24,6 +24,7 @@
#include "nimble/nimble/include/nimble/ble.h"
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
static const ble_uuid_t *uuid_ccc =
BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16);
@@ -209,3 +210,4 @@ ble_gatts_show_local(void)
ble_gatts_lcl_svc_foreach(ble_gatt_show_local_svc, NULL);
}
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c
index 7a0ba6e68..2a9d45d9e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs.c
@@ -36,7 +36,9 @@
MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
static void ble_hs_event_rx_hci_ev(struct ble_npl_event *ev);
+#if NIMBLE_BLE_CONNECT
static void ble_hs_event_tx_notify(struct ble_npl_event *ev);
+#endif
static void ble_hs_event_reset(struct ble_npl_event *ev);
static void ble_hs_event_start_stage1(struct ble_npl_event *ev);
static void ble_hs_event_start_stage2(struct ble_npl_event *ev);
@@ -62,6 +64,14 @@ static int ble_hs_reset_reason;
#define BLE_HS_SYNC_RETRY_TIMEOUT_MS 100 /* ms */
+extern void ble_hs_hci_deinit(void);
+extern void ble_gap_deinit(void);
+extern void ble_hs_stop_deinit(void);
+extern void ble_mqueue_deinit(struct ble_mqueue *);
+extern void ble_hs_flow_init(void);
+extern void ble_hs_flow_deinit(void);
+extern void ble_monitor_deinit(void);
+
static void *ble_hs_parent_task;
/**
@@ -418,12 +428,10 @@ ble_hs_timer_exp(struct ble_npl_event *ev)
switch (ble_hs_sync_state) {
case BLE_HS_SYNC_STATE_GOOD:
+#if NIMBLE_BLE_CONNECT
ticks_until_next = ble_gattc_timer();
ble_hs_timer_sched(ticks_until_next);
- ticks_until_next = ble_gap_timer();
- ble_hs_timer_sched(ticks_until_next);
-
ticks_until_next = ble_l2cap_sig_timer();
ble_hs_timer_sched(ticks_until_next);
@@ -432,6 +440,11 @@ ble_hs_timer_exp(struct ble_npl_event *ev)
ticks_until_next = ble_hs_conn_timer();
ble_hs_timer_sched(ticks_until_next);
+#endif
+
+ ticks_until_next = ble_gap_timer();
+ ble_hs_timer_sched(ticks_until_next);
+
break;
case BLE_HS_SYNC_STATE_BAD:
@@ -454,6 +467,7 @@ ble_hs_timer_reset(uint32_t ticks)
if (!ble_hs_is_enabled()) {
ble_npl_callout_stop(&ble_hs_timer);
+ ble_npl_callout_deinit(&ble_hs_timer);
} else {
rc = ble_npl_callout_reset(&ble_hs_timer, ticks);
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
@@ -478,6 +492,11 @@ ble_hs_timer_sched(int32_t ticks_from_now)
ble_npl_callout_get_ticks(&ble_hs_timer))) < 0) {
ble_hs_timer_reset(ticks_from_now);
}
+ else if (ble_npl_callout_get_ticks(&ble_hs_timer) <= ble_npl_time_get()) {
+ /* Reset timer if currect time is later than expiration time. */
+ BLE_HS_LOG(DEBUG,"exp_time:%d.now:%d.ticks:%d.active:%d.Need reset.",ble_npl_callout_get_ticks(&ble_hs_timer),ble_npl_time_get(),ticks_from_now,ble_npl_callout_is_active(&ble_hs_timer));
+ ble_hs_timer_reset(ticks_from_now);
+ }
}
void
@@ -515,6 +534,9 @@ ble_hs_event_rx_hci_ev(struct ble_npl_event *ev)
hci_ev = ble_npl_event_get_arg(ev);
+ /* Deinitialize hci npl event */
+ ble_npl_event_deinit(ev);
+
rc = os_memblock_put(&ble_hs_hci_ev_pool, ev);
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
@@ -526,11 +548,13 @@ ble_hs_event_rx_hci_ev(struct ble_npl_event *ev)
ble_hs_hci_evt_process(hci_ev);
}
+#if NIMBLE_BLE_CONNECT
static void
ble_hs_event_tx_notify(struct ble_npl_event *ev)
{
ble_gatts_tx_notifications();
}
+#endif
static void
ble_hs_event_rx_data(struct ble_npl_event *ev)
@@ -663,11 +687,12 @@ ble_hs_start(void)
ble_npl_callout_init(&ble_hs_timer, ble_hs_evq, ble_hs_timer_exp, NULL);
+#if NIMBLE_BLE_CONNECT
rc = ble_gatts_start();
if (rc != 0) {
return rc;
}
-
+#endif
ble_hs_sync();
return 0;
@@ -740,8 +765,10 @@ ble_hs_init(void)
ble_hs_reset_reason = 0;
ble_hs_enabled_state = BLE_HS_ENABLED_STATE_OFF;
+#if NIMBLE_BLE_CONNECT
ble_npl_event_init(&ble_hs_ev_tx_notifications, ble_hs_event_tx_notify,
NULL);
+#endif
ble_npl_event_init(&ble_hs_ev_reset, ble_hs_event_reset, NULL);
ble_npl_event_init(&ble_hs_ev_start_stage1, ble_hs_event_start_stage1,
NULL);
@@ -758,6 +785,7 @@ ble_hs_init(void)
SYSINIT_PANIC_ASSERT(rc == 0);
#endif
+#if NIMBLE_BLE_CONNECT
rc = ble_l2cap_init();
SYSINIT_PANIC_ASSERT(rc == 0);
@@ -767,14 +795,14 @@ ble_hs_init(void)
rc = ble_att_svr_init();
SYSINIT_PANIC_ASSERT(rc == 0);
- rc = ble_gap_init();
- SYSINIT_PANIC_ASSERT(rc == 0);
-
rc = ble_gattc_init();
SYSINIT_PANIC_ASSERT(rc == 0);
rc = ble_gatts_init();
SYSINIT_PANIC_ASSERT(rc == 0);
+#endif
+ rc = ble_gap_init();
+ SYSINIT_PANIC_ASSERT(rc == 0);
ble_hs_stop_init();
@@ -822,6 +850,8 @@ ble_hs_init(void)
#if BLE_MONITOR
ble_monitor_new_index(0, (uint8_t[6]){ }, "nimble0");
#endif
+ /* Initialize npl variables related to hs flow control */
+ ble_hs_flow_init();
}
void
@@ -839,5 +869,23 @@ ble_hs_deinit(void)
ble_hs_flow_stop();
+#if NIMBLE_BLE_CONNECT
+ ble_npl_event_deinit(&ble_hs_ev_tx_notifications);
+#endif
+
+ ble_npl_event_deinit(&ble_hs_ev_reset);
+
+ ble_npl_event_deinit(&ble_hs_ev_start_stage1);
+
+ ble_npl_event_deinit(&ble_hs_ev_start_stage2);
+
+ ble_mqueue_deinit(&ble_hs_rx_q);
+
+ ble_hs_flow_deinit();
+
ble_hs_stop_deinit();
+
+#if BLE_MONITOR
+ ble_monitor_deinit();
+#endif
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c
index 1625e7305..0f10c8267 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_conn.c
@@ -328,6 +328,7 @@ ble_hs_conn_find_by_addr(const ble_addr_t *addr)
#endif
struct ble_hs_conn *conn;
+ struct ble_hs_conn_addrs addrs;
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
@@ -344,6 +345,14 @@ ble_hs_conn_find_by_addr(const ble_addr_t *addr)
if (ble_addr_cmp(&conn->bhc_peer_addr, addr) == 0) {
return conn;
}
+ if (conn->bhc_peer_addr.type < BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT) {
+ continue;
+ }
+ /*If type 0x02 or 0x03 is used, let's double check if address is good */
+ ble_hs_conn_addrs(conn, &addrs);
+ if (ble_addr_cmp(&addrs.peer_id_addr, addr) == 0) {
+ return conn;
+ }
}
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c
index 50ec007d1..808a70618 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_flow.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/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));
@@ -235,7 +235,9 @@ ble_hs_flow_startup(void)
};
int rc;
- ble_npl_event_init(&ble_hs_flow_ev, ble_hs_flow_event_cb, NULL);
+ /* Remove previous event from queue, if any*/
+ ble_npl_eventq_remove(ble_hs_evq_get(), &ble_hs_flow_ev);
+
/* Assume failure. */
ble_hci_trans_set_acl_free_cb(NULL, NULL);
@@ -267,8 +269,8 @@ ble_hs_flow_startup(void)
/* Flow control successfully enabled. */
ble_hs_flow_num_completed_pkts = 0;
ble_hci_trans_set_acl_free_cb(ble_hs_flow_acl_free, NULL);
- ble_npl_callout_init(&ble_hs_flow_timer, ble_hs_evq_get(),
- ble_hs_flow_event_cb, NULL);
+ /* Stop flow control timer, if not already */
+ ble_npl_callout_stop(&ble_hs_flow_timer);
#endif
return 0;
@@ -281,3 +283,22 @@ ble_hs_flow_stop(void)
ble_npl_callout_deinit(&ble_hs_flow_timer);
#endif
}
+
+void
+ble_hs_flow_init(void)
+{
+#if MYNEWT_VAL(BLE_HS_FLOW_CTRL)
+ ble_npl_event_init(&ble_hs_flow_ev, ble_hs_flow_event_cb, NULL);
+ ble_npl_callout_init(&ble_hs_flow_timer, ble_hs_evq_get(),
+ ble_hs_flow_event_cb, NULL);
+#endif //MYNEWT_VAL(BLE_HS_FLOW_CTRL)
+}
+
+void
+ble_hs_flow_deinit(void)
+{
+#if MYNEWT_VAL(BLE_HS_FLOW_CTRL)
+ ble_npl_event_deinit(&ble_hs_flow_ev);
+ ble_npl_callout_deinit(&ble_hs_flow_timer);
+#endif //MYNEWT_VAL(BLE_HS_FLOW_CTRL)
+}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c
index 214fc8214..271d9258e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/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)
@@ -447,8 +461,8 @@ ble_hs_hci_acl_hdr_prepend(struct os_mbuf *om, uint16_t handle,
struct hci_data_hdr hci_hdr;
struct os_mbuf *om2;
- hci_hdr.hdh_handle_pb_bc =
- ble_hs_hci_util_handle_pb_bc_join(handle, pb_flag, 0);
+ put_le16(&hci_hdr.hdh_handle_pb_bc,
+ ble_hs_hci_util_handle_pb_bc_join(handle, pb_flag, 0));
put_le16(&hci_hdr.hdh_len, OS_MBUF_PKTHDR(om)->omp_len);
om2 = os_mbuf_prepend(om, sizeof hci_hdr);
@@ -621,10 +635,13 @@ ble_hs_hci_init(void)
BLE_HS_DBG_ASSERT_EVAL(rc == 0);
}
-void
-ble_hs_hci_deinit(void)
+void ble_hs_hci_deinit(void)
{
- ble_npl_mutex_deinit(&ble_hs_hci_mutex);
+ int rc;
- ble_npl_sem_deinit(&ble_hs_hci_sem);
+ rc = ble_npl_mutex_deinit(&ble_hs_hci_mutex);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+
+ rc = ble_npl_sem_deinit(&ble_hs_hci_sem);
+ BLE_HS_DBG_ASSERT_EVAL(rc == 0);
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c
index 63242ca88..f4b537633 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_cmd.c
@@ -27,6 +27,13 @@
#include "nimble/nimble/host/include/host/ble_monitor.h"
#include "ble_hs_priv.h"
#include "ble_monitor_priv.h"
+#ifdef ESP_PLATFORM
+# if defined __has_include
+# if __has_include ("soc/soc_caps.h")
+# include "soc/soc_caps.h"
+# endif
+# endif
+#endif
static int
ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd)
@@ -72,9 +79,11 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata)
buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
BLE_HS_DBG_ASSERT(buf != NULL);
+#if !(SOC_ESP_NIMBLE_CONTROLLER)
/* Hack for avoiding memcpy while handling tx pkt to VHCI,
* keep one byte for type field*/
buf++;
+#endif
put_le16(buf, opcode);
buf[2] = len;
if (len != 0) {
@@ -86,7 +95,10 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata)
ble_hs_log_flat_buf(buf, len + BLE_HCI_CMD_HDR_LEN);
BLE_HS_LOG(DEBUG, "\n");
#endif
+
+#if !(SOC_ESP_NIMBLE_CONTROLLER)
buf--;
+#endif
rc = ble_hs_hci_cmd_transport((void *) buf);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c
index 9b97f433b..f8d52d583 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_evt.c
@@ -44,22 +44,27 @@ _Static_assert(sizeof (struct hci_data_hdr) == BLE_HCI_DATA_HDR_SZ,
typedef int ble_hs_hci_evt_fn(uint8_t event_code, const void *data,
unsigned int len);
-static ble_hs_hci_evt_fn ble_hs_hci_evt_disconn_complete;
-static ble_hs_hci_evt_fn ble_hs_hci_evt_encrypt_change;
static ble_hs_hci_evt_fn ble_hs_hci_evt_hw_error;
static ble_hs_hci_evt_fn ble_hs_hci_evt_num_completed_pkts;
+#if NIMBLE_BLE_CONNECT
+static ble_hs_hci_evt_fn ble_hs_hci_evt_disconn_complete;
+static ble_hs_hci_evt_fn ble_hs_hci_evt_encrypt_change;
static ble_hs_hci_evt_fn ble_hs_hci_evt_enc_key_refresh;
+#endif
static ble_hs_hci_evt_fn ble_hs_hci_evt_le_meta;
typedef int ble_hs_hci_evt_le_fn(uint8_t subevent, const void *data,
unsigned int len);
-static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_complete;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_adv_rpt;
+#if NIMBLE_BLE_CONNECT
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_complete;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_upd_complete;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_lt_key_req;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_parm_req;
-static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_dir_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_phy_update_complete;
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_enh_conn_complete;
+#endif
+static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_dir_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_ext_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_rd_rem_used_feat_complete;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_scan_timeout;
@@ -68,7 +73,6 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_estab;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_lost;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_scan_req_rcvd;
-static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_enh_conn_complete;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_transfer;
/* Statistics */
@@ -91,9 +95,11 @@ struct ble_hs_hci_evt_dispatch_entry {
static const struct ble_hs_hci_evt_dispatch_entry ble_hs_hci_evt_dispatch[] = {
{ BLE_HCI_EVCODE_LE_META, ble_hs_hci_evt_le_meta },
{ BLE_HCI_EVCODE_NUM_COMP_PKTS, ble_hs_hci_evt_num_completed_pkts },
+#if NIMBLE_BLE_CONNECT
{ BLE_HCI_EVCODE_DISCONN_CMP, ble_hs_hci_evt_disconn_complete },
{ BLE_HCI_EVCODE_ENCRYPT_CHG, ble_hs_hci_evt_encrypt_change },
{ BLE_HCI_EVCODE_ENC_KEY_REFRESH, ble_hs_hci_evt_enc_key_refresh },
+#endif
{ BLE_HCI_EVCODE_HW_ERROR, ble_hs_hci_evt_hw_error },
};
@@ -101,14 +107,20 @@ static const struct ble_hs_hci_evt_dispatch_entry ble_hs_hci_evt_dispatch[] = {
(sizeof ble_hs_hci_evt_dispatch / sizeof ble_hs_hci_evt_dispatch[0])
static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
+#if NIMBLE_BLE_CONNECT
[BLE_HCI_LE_SUBEV_CONN_COMPLETE] = ble_hs_hci_evt_le_conn_complete,
+#endif
[BLE_HCI_LE_SUBEV_ADV_RPT] = ble_hs_hci_evt_le_adv_rpt,
+#if NIMBLE_BLE_CONNECT
[BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE] = ble_hs_hci_evt_le_conn_upd_complete,
[BLE_HCI_LE_SUBEV_LT_KEY_REQ] = ble_hs_hci_evt_le_lt_key_req,
[BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ] = ble_hs_hci_evt_le_conn_parm_req,
[BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE] = ble_hs_hci_evt_le_enh_conn_complete,
+#endif
[BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT] = ble_hs_hci_evt_le_dir_adv_rpt,
+#if NIMBLE_BLE_CONNECT
[BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE] = ble_hs_hci_evt_le_phy_update_complete,
+#endif
[BLE_HCI_LE_SUBEV_EXT_ADV_RPT] = ble_hs_hci_evt_le_ext_adv_rpt,
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB] = ble_hs_hci_evt_le_periodic_adv_sync_estab,
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT] = ble_hs_hci_evt_le_periodic_adv_rpt,
@@ -149,6 +161,7 @@ ble_hs_hci_evt_le_dispatch_find(uint8_t event_code)
return ble_hs_hci_evt_le_dispatch[event_code];
}
+#if NIMBLE_BLE_CONNECT
static int
ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data,
unsigned int len)
@@ -218,7 +231,7 @@ ble_hs_hci_evt_encrypt_change(uint8_t event_code, const void *data,
return 0;
}
-
+#endif
static int
ble_hs_hci_evt_hw_error(uint8_t event_code, const void *data, unsigned int len)
{
@@ -233,6 +246,7 @@ ble_hs_hci_evt_hw_error(uint8_t event_code, const void *data, unsigned int len)
return 0;
}
+#if NIMBLE_BLE_CONNECT
static int
ble_hs_hci_evt_enc_key_refresh(uint8_t event_code, const void *data,
unsigned int len)
@@ -247,6 +261,7 @@ ble_hs_hci_evt_enc_key_refresh(uint8_t event_code, const void *data,
return 0;
}
+#endif
static int
ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, const void *data,
@@ -308,6 +323,7 @@ ble_hs_hci_evt_le_meta(uint8_t event_code, const void *data, unsigned int len)
static struct ble_gap_conn_complete pend_conn_complete;
#endif
+#if NIMBLE_BLE_CONNECT
static int
ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data,
unsigned int len)
@@ -352,7 +368,6 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data,
evt.connection_handle = BLE_HS_CONN_HANDLE_NONE;
#endif
}
-
#if MYNEWT_VAL(BLE_EXT_ADV)
if (evt.status == BLE_ERR_DIR_ADV_TMO ||
evt.role == BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) {
@@ -418,7 +433,10 @@ ble_hs_hci_evt_le_conn_complete(uint8_t subevent, const void *data,
#endif
return ble_gap_rx_conn_complete(&evt, 0);
}
+#endif
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpointer-arith"
static int
ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len)
{
@@ -429,8 +447,7 @@ ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len)
if (len < sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpointer-arith"
+
len -= sizeof(*ev);
data += sizeof(*ev);
@@ -462,7 +479,7 @@ ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len)
if (len) {
return BLE_HS_ECONTROLLER;
}
-#pragma GCC diagnostic pop
+
return 0;
}
@@ -480,8 +497,7 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, const void *data, unsigned int len)
if (rc != 0) {
return rc;
}
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpointer-arith"
+
data += sizeof(*ev);
desc.direct_addr = *BLE_ADDR_ANY;
@@ -500,9 +516,10 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, const void *data, unsigned int len)
ble_gap_rx_adv_report(&desc);
}
-#pragma GCC diagnostic pop
+
return 0;
}
+#pragma GCC diagnostic pop
static int
ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, const void *data, unsigned int len)
@@ -552,20 +569,21 @@ ble_hs_hci_evt_le_rd_rem_used_feat_complete(uint8_t subevent, const void *data,
static int
ble_hs_hci_decode_legacy_type(uint16_t evt_type)
{
- switch (evt_type) {
- case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND:
- return BLE_HCI_ADV_RPT_EVTYPE_ADV_IND;
- case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND:
- return BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
- case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND:
- return BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND;
- case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND:
- return BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND;
- case BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND:
- return BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP;
- default:
- return -1;
- }
+ switch (evt_type) {
+ case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_IND:
+ return BLE_HCI_ADV_RPT_EVTYPE_ADV_IND;
+ case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_DIRECT_IND:
+ return BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
+ case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_SCAN_IND:
+ return BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND;
+ case BLE_HCI_LEGACY_ADV_EVTYPE_ADV_NONCON_IND:
+ return BLE_HCI_ADV_RPT_EVTYPE_NONCONN_IND;
+ case BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_IND:
+ case BLE_HCI_LEGACY_ADV_EVTYPE_SCAN_RSP_ADV_SCAN_IND:
+ return BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP;
+ default:
+ return -1;
+ }
}
#endif
@@ -762,6 +780,7 @@ ble_hs_hci_evt_le_scan_req_rcvd(uint8_t subevent, const void *data,
return 0;
}
+#if NIMBLE_BLE_CONNECT
static int
ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, const void *data,
unsigned int len)
@@ -840,6 +859,7 @@ ble_hs_hci_evt_le_phy_update_complete(uint8_t subevent, const void *data,
return 0;
}
+#endif
int
ble_hs_hci_evt_process(const struct ble_hci_ev *ev)
@@ -876,6 +896,7 @@ ble_hs_hci_evt_process(const struct ble_hci_ev *ev)
int
ble_hs_hci_evt_acl_process(struct os_mbuf *om)
{
+#if NIMBLE_BLE_CONNECT
struct hci_data_hdr hci_hdr;
struct ble_hs_conn *conn;
ble_l2cap_rx_fn *rx_cb;
@@ -946,4 +967,7 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
err:
os_mbuf_free_chain(om);
return rc;
+#else
+ return BLE_HS_ENOTSUP;
+#endif
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h
index d8a72cb29..4975996c4 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_priv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/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);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c
index 1f63acc94..d5d50585c 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_hci_util.c
@@ -157,6 +157,60 @@ ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
return 0;
}
+int
+ble_hs_hci_util_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets,
+ uint16_t *out_sugg_max_tx_time)
+{
+ struct ble_hci_le_rd_sugg_def_data_len_rp rsp;
+ int rc;
+
+ rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN),
+ NULL, 0, &rsp, sizeof(rsp));
+ if (rc != 0) {
+ return rc;
+ }
+
+ *out_sugg_max_tx_octets = le16toh(rsp.max_tx_octets);
+ *out_sugg_max_tx_time = le16toh(rsp.max_tx_time);
+
+ if (*out_sugg_max_tx_octets < BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN ||
+ *out_sugg_max_tx_octets > BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX) {
+ BLE_HS_LOG(WARN, "received suggested maximum tx octets is out of range\n");
+ }
+
+ if (*out_sugg_max_tx_time < BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN ||
+ *out_sugg_max_tx_time > BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX) {
+ BLE_HS_LOG(WARN, "received suggested maximum tx time is out of range\n");
+ }
+
+ return 0;
+}
+
+int
+ble_hs_hci_util_write_sugg_def_data_len(uint16_t sugg_max_tx_octets,
+ uint16_t sugg_max_tx_time)
+{
+ struct ble_hci_le_wr_sugg_def_data_len_cp cmd;
+
+ if (sugg_max_tx_octets < BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN ||
+ sugg_max_tx_octets > BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX) {
+ return BLE_HS_EINVAL;
+ }
+
+ if (sugg_max_tx_time < BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN ||
+ sugg_max_tx_time > BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX) {
+ return BLE_HS_EINVAL;
+ }
+
+ cmd.max_tx_octets = htole16(sugg_max_tx_octets);
+ cmd.max_tx_time = htole16(sugg_max_tx_time);
+
+ return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN),
+ &cmd, sizeof(cmd), NULL, 0);
+}
+
int
ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
struct hci_data_hdr *out_hdr)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mqueue.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mqueue.c
index 2e08efc14..99628c1fb 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mqueue.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_mqueue.c
@@ -29,6 +29,12 @@ ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg)
return (0);
}
+void
+ble_mqueue_deinit(struct ble_mqueue *mq)
+{
+ ble_npl_event_deinit(&mq->ev);
+}
+
struct os_mbuf *
ble_mqueue_get(struct ble_mqueue *mq)
{
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c
index 05a928201..309f0d934 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_periodic_sync.c
@@ -55,6 +55,9 @@ ble_hs_periodic_sync_free(struct ble_hs_periodic_sync *psync)
return;
}
+ if((psync->lost_ev).event != NULL)
+ ble_npl_event_deinit(&psync->lost_ev);
+
#if MYNEWT_VAL(BLE_HS_DEBUG)
memset(psync, 0xff, sizeof *psync);
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h
index f2a64a362..384fd158f 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_priv.h
@@ -143,6 +143,8 @@ int ble_mqueue_init(struct ble_mqueue *mq, ble_npl_event_fn *ev_fn, void *ev_arg
struct os_mbuf *ble_mqueue_get(struct ble_mqueue *mq);
int ble_mqueue_put(struct ble_mqueue *mq, struct ble_npl_eventq *evq, struct os_mbuf *om);
+void ble_gap_npl_sync_lost(struct ble_npl_event *ev);
+
#if MYNEWT_VAL(BLE_HS_DEBUG)
#define BLE_HS_DBG_ASSERT(x) assert(x)
#define BLE_HS_DBG_ASSERT_EVAL(x) assert(x)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c
index 7ae9ef12b..d70a9bdcc 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_hs_resolv.c
@@ -97,6 +97,7 @@ ble_rpa_remove_peer_dev_rec(struct ble_hs_dev_records *p_dev_rec)
if ((i != ble_store_num_peer_dev_rec) && (ble_store_num_peer_dev_rec != 0)) {
memmove(&peer_dev_rec[i], &peer_dev_rec[i + 1],
(ble_store_num_peer_dev_rec - i) * sizeof(struct ble_hs_dev_records ));
+ memset(&peer_dev_rec[ble_store_num_peer_dev_rec], 0, sizeof(struct ble_hs_dev_records));
}
BLE_HS_LOG(DEBUG, " RPA: removed device at index = %d, no. of peer records"
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c
index a4b98a9e7..3f0b52230 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap.c
@@ -26,6 +26,7 @@
#include "ble_hs_priv.h"
#include "ble_l2cap_coc_priv.h"
+#if NIMBLE_BLE_CONNECT
_Static_assert(sizeof (struct ble_l2cap_hdr) == BLE_L2CAP_HDR_SZ,
"struct ble_l2cap_hdr must be 4 bytes");
@@ -504,3 +505,5 @@ ble_l2cap_init(void)
return 0;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c
index 5258da84d..fa9e61be8 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_coc.c
@@ -25,7 +25,7 @@
#include "ble_l2cap_coc_priv.h"
#include "ble_l2cap_sig_priv.h"
-#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0
+#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 && NIMBLE_BLE_CONNECT
#define BLE_L2CAP_SDU_SIZE 2
@@ -73,7 +73,7 @@ ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu,
srv = ble_l2cap_coc_srv_alloc();
if (!srv) {
- return BLE_HS_ENOMEM;
+ return BLE_HS_ENOMEM;
}
srv->psm = psm;
@@ -392,6 +392,8 @@ ble_l2cap_event_coc_unstalled(struct ble_l2cap_chan *chan, int status)
chan->cb(&event, chan->cb_arg);
}
+/* WARNING: this function is called from different task contexts. We expect the
+ * host to be locked (ble_hs_lock()) before entering this function! */
static int
ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
{
@@ -406,6 +408,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
/* If there is no data to send, just return success */
tx = &chan->coc_tx;
if (!tx->sdu) {
+ ble_hs_unlock();
return 0;
}
@@ -440,6 +443,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
BLE_HS_LOG(DEBUG, "Sending SDU len=%d\n", OS_MBUF_PKTLEN(tx->sdu));
rc = os_mbuf_append(txom, &l, sizeof(uint16_t));
if (rc) {
+ rc = BLE_HS_ENOMEM;
BLE_HS_LOG(DEBUG, "Could not append data rc=%d", rc);
goto failed;
}
@@ -452,55 +456,63 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
rc = os_mbuf_appendfrom(txom, tx->sdu, tx->data_offset,
len - sdu_size_offset);
if (rc) {
+ rc = BLE_HS_ENOMEM;
BLE_HS_LOG(DEBUG, "Could not append data rc=%d", rc);
- goto failed;
+ goto failed;
}
- ble_hs_lock();
conn = ble_hs_conn_find_assert(chan->conn_handle);
rc = ble_l2cap_tx(conn, chan, txom);
- ble_hs_unlock();
if (rc) {
- /* txom is consumed by l2cap */
- txom = NULL;
- goto failed;
+ /* txom is consumed by l2cap */
+ txom = NULL;
+ goto failed;
} else {
- tx->credits --;
+ tx->credits--;
tx->data_offset += len - sdu_size_offset;
}
BLE_HS_LOG(DEBUG, "Sent %d bytes, credits=%d, to send %d bytes \n",
- len, tx->credits, OS_MBUF_PKTLEN(tx->sdu)- tx->data_offset );
+ len, tx->credits, OS_MBUF_PKTLEN(tx->sdu)- tx->data_offset);
if (tx->data_offset == OS_MBUF_PKTLEN(tx->sdu)) {
- BLE_HS_LOG(DEBUG, "Complete package sent\n");
- os_mbuf_free_chain(tx->sdu);
- tx->sdu = 0;
- tx->data_offset = 0;
- if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
- ble_l2cap_event_coc_unstalled(chan, 0);
- tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
- }
- break;
+ BLE_HS_LOG(DEBUG, "Complete package sent\n");
+ os_mbuf_free_chain(tx->sdu);
+ tx->sdu = NULL;
+ tx->data_offset = 0;
+ break;
}
}
if (tx->sdu) {
/* Not complete SDU sent, wait for credits */
tx->flags |= BLE_L2CAP_COC_FLAG_STALLED;
+ ble_hs_unlock();
return BLE_HS_ESTALLED;
}
+ if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
+ tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
+ ble_hs_unlock();
+ ble_l2cap_event_coc_unstalled(chan, 0);
+ } else {
+ ble_hs_unlock();
+ }
+
return 0;
failed:
os_mbuf_free_chain(tx->sdu);
tx->sdu = NULL;
+
os_mbuf_free_chain(txom);
if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
- ble_l2cap_event_coc_unstalled(chan, rc);
tx->flags &= ~BLE_L2CAP_COC_FLAG_STALLED;
+ ble_hs_unlock();
+ ble_l2cap_event_coc_unstalled(chan, rc);
+ } else {
+ ble_hs_unlock();
}
return rc;
@@ -535,7 +547,8 @@ ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid,
}
chan->coc_tx.credits += credits;
- ble_hs_unlock();
+
+ /* leave the host locked on purpose when ble_l2cap_coc_continue_tx() */
ble_l2cap_coc_continue_tx(chan);
}
@@ -584,18 +597,22 @@ ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx)
{
struct ble_l2cap_coc_endpoint *tx;
- tx = &chan->coc_tx;
- if (tx->sdu) {
- return BLE_HS_EBUSY;
- }
+ tx = &chan->coc_tx;
if (OS_MBUF_PKTLEN(sdu_tx) > tx->mtu) {
return BLE_HS_EBADDATA;
}
+ ble_hs_lock();
+ if (tx->sdu) {
+ ble_hs_unlock();
+ return BLE_HS_EBUSY;
+ }
tx->sdu = sdu_tx;
+
+ /* leave the host locked on purpose when ble_l2cap_coc_continue_tx() */
return ble_l2cap_coc_continue_tx(chan);
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h
index 30af30427..838014d70 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_priv.h
@@ -105,6 +105,7 @@ typedef int ble_l2cap_tx_fn(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan);
#define BLE_L2CAP_CHAN_F_TXED_MTU 0x01 /* We have sent our MTU. */
+#define BLE_L2CAP_CHAN_F_DISCONNECTING 0x02 /* We have sent L2CAP Disconnect. */
SLIST_HEAD(ble_l2cap_chan_list, ble_l2cap_chan);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c
index f9d32d0ac..792ff04e7 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig.c
@@ -48,6 +48,7 @@
#include "nimble/nimble/host/include/host/ble_monitor.h"
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
/*****************************************************************************
* $definitions / declarations *
*****************************************************************************/
@@ -661,8 +662,8 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
continue;
}
- if ((status == 0) && (chan->dcid != 0)) {
- ble_l2cap_event_coc_connected(chan, status);
+ if (chan->dcid != 0) {
+ ble_l2cap_event_coc_connected(chan, 0);
/* Let's forget about connected channel now.
* Not connected will be freed later on.
*/
@@ -864,6 +865,7 @@ ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data;
ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+ ble_l2cap_sig_proc_free(proc);
return 0;
}
@@ -1066,7 +1068,15 @@ ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle,
if (rsp->result) {
rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result));
- goto done;
+ /* Below results means that some of the channels has not been created
+ * and we have to look closer into the response.
+ * Any other results means that all the connections has been refused.
+ */
+ if ((rsp->result != BLE_L2CAP_COC_ERR_NO_RESOURCES) &&
+ (rsp->result != BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID) &&
+ (rsp->result != BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED)) {
+ goto done;
+ }
}
ble_hs_lock();
@@ -1630,6 +1640,10 @@ ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan)
struct ble_l2cap_sig_proc *proc;
int rc;
+ if (chan->flags & BLE_L2CAP_CHAN_F_DISCONNECTING) {
+ return 0;
+ }
+
proc = ble_l2cap_sig_proc_alloc();
if (proc == NULL) {
return BLE_HS_ENOMEM;
@@ -1651,6 +1665,10 @@ ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan)
req->scid = htole16(chan->scid);
rc = ble_l2cap_sig_tx(proc->conn_handle, txom);
+ /* Mark channel as disconnecting */
+ if (rc == 0) {
+ chan->flags |= BLE_L2CAP_CHAN_F_DISCONNECTING;
+ }
done:
ble_l2cap_sig_process_status(proc, rc);
@@ -1944,3 +1962,5 @@ ble_l2cap_sig_init(void)
return 0;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_cmd.c
index 510420f09..d9e507e25 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_cmd.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_l2cap_sig_cmd.c
@@ -20,6 +20,7 @@
#include
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
int
ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom)
{
@@ -112,3 +113,5 @@ ble_l2cap_sig_cmd_get(uint8_t opcode, uint8_t id, uint16_t len,
return hdr->data;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c
index d4a468284..9e66216ee 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_monitor.c
@@ -342,6 +342,15 @@ ble_monitor_init(void)
return 0;
}
+void
+ble_monitor_deinit(void)
+{
+#if MYNEWT_VAL(BLE_MONITOR_RTT) && MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED)
+ ble_npl_callout_deinit(&rtt_drops.tmo);
+#endif
+ ble_npl_mutex_deinit(&lock);
+}
+
int
ble_monitor_send(uint16_t opcode, const void *data, size_t len)
{
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c
index acbe8a1c1..5a7ffbb4a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm.c
@@ -50,6 +50,7 @@
#include "ble_hs_resolv_priv.h"
#include "../store/config/src/ble_store_config_priv.h"
+#if NIMBLE_BLE_CONNECT
#if NIMBLE_BLE_SM
/** Procedure timeout; 30 seconds. */
@@ -1912,6 +1913,9 @@ 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 (!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);
} else {
ble_sm_pair_cfg(proc);
@@ -2852,3 +2856,5 @@ ble_sm_create_chan(uint16_t conn_handle)
return chan;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c
index e17760efe..a916deb75 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_alg.c
@@ -23,6 +23,7 @@
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
#include "nimble/nimble/include/nimble/nimble_opt.h"
+#if NIMBLE_BLE_CONNECT
#if NIMBLE_BLE_SM
#include "nimble/nimble/include/nimble/ble.h"
@@ -65,6 +66,20 @@ static struct trng_dev *g_trng;
#endif
#endif
+/**
+ * Keep forward-compatibility with Mbed TLS 3.x.
+ *
+ * Direct access to fields of structures declared in public headers is no longer
+ * supported. In Mbed TLS 3, the layout of structures is not considered part of
+ * the stable API, and minor versions (3.1, 3.2, etc.) may add, remove, rename,
+ * reorder or change the type of structure fields.
+ */
+#if (MBEDTLS_VERSION_NUMBER < 0x03000000)
+#ifndef MBEDTLS_PRIVATE
+#define MBEDTLS_PRIVATE(member) member
+#endif
+#endif
+
static void
ble_sm_alg_xor_128(const uint8_t *p, const uint8_t *q, uint8_t *r)
{
@@ -533,15 +548,15 @@ ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_
mbedtls_mpi_init(&z);
/* Below 3 steps are to validate public key on curve secp256r1 */
- if (mbedtls_ecp_group_load(&keypair.grp, MBEDTLS_ECP_DP_SECP256R1) != 0) {
+ if (mbedtls_ecp_group_load(&keypair.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1) != 0) {
goto exit;
}
- if (mbedtls_ecp_point_read_binary(&keypair.grp, &pt, pub, 65) != 0) {
+ if (mbedtls_ecp_point_read_binary(&keypair.MBEDTLS_PRIVATE(grp), &pt, pub, 65) != 0) {
goto exit;
}
- if (mbedtls_ecp_check_pubkey(&keypair.grp, &pt) != 0) {
+ if (mbedtls_ecp_check_pubkey(&keypair.MBEDTLS_PRIVATE(grp), &pt) != 0) {
goto exit;
}
@@ -552,7 +567,7 @@ ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_
}
/* Prepare point Q from pub key */
- if (mbedtls_ecp_point_read_binary(&keypair.grp, &Q, pub, 65) != 0) {
+ if (mbedtls_ecp_point_read_binary(&keypair.MBEDTLS_PRIVATE(grp), &Q, pub, 65) != 0) {
goto exit;
}
@@ -560,7 +575,7 @@ ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_
goto exit;
}
- rc = mbedtls_ecdh_compute_shared(&keypair.grp, &z, &Q, &d,
+ rc = mbedtls_ecdh_compute_shared(&keypair.MBEDTLS_PRIVATE(grp), &z, &Q, &d,
mbedtls_ctr_drbg_random, &ctr_drbg);
if (rc != 0) {
goto exit;
@@ -628,6 +643,10 @@ mbedtls_gen_keypair(uint8_t *public_key, uint8_t *private_key)
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
+
+ /* Free the previously allocate keypair */
+ mbedtls_ecp_keypair_free(&keypair);
+
mbedtls_ecp_keypair_init(&keypair);
if (( rc = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
@@ -640,14 +659,14 @@ mbedtls_gen_keypair(uint8_t *public_key, uint8_t *private_key)
goto exit;
}
- if (( rc = mbedtls_mpi_write_binary(&keypair.d, private_key, 32)) != 0) {
+ if (( rc = mbedtls_mpi_write_binary(&keypair.MBEDTLS_PRIVATE(d), private_key, 32)) != 0) {
goto exit;
}
size_t olen = 0;
uint8_t pub[65] = {0};
- if ((rc = mbedtls_ecp_point_write_binary(&keypair.grp, &keypair.Q, MBEDTLS_ECP_PF_UNCOMPRESSED,
+ if ((rc = mbedtls_ecp_point_write_binary(&keypair.MBEDTLS_PRIVATE(grp), &keypair.MBEDTLS_PRIVATE(Q), MBEDTLS_ECP_PF_UNCOMPRESSED,
&olen, pub, 65)) != 0) {
goto exit;
}
@@ -664,6 +683,11 @@ exit:
return 0;
}
+
+void mbedtls_free_keypair(void)
+{
+ mbedtls_ecp_keypair_free(&keypair);
+}
#endif
/**
@@ -703,7 +727,10 @@ ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv)
return 0;
}
-#if !(MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS))
+#if MYNEWT_VAL(SELFTEST)
+/* Unit tests rely on custom RNG function not being set */
+#define ble_sm_alg_rand NULL
+#elif !(MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS))
/* used by uECC to get random data */
static int
ble_sm_alg_rand(uint8_t *dst, unsigned int size)
@@ -742,3 +769,4 @@ ble_sm_alg_ecc_init(void)
#endif
#endif
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c
index 92a34ed36..b3bb38d3d 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_cmd.c
@@ -24,6 +24,7 @@
#include "nimble/nimble/host/include/host/ble_sm.h"
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
void *
ble_sm_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom)
{
@@ -66,3 +67,5 @@ ble_sm_tx(uint16_t conn_handle, struct os_mbuf *txom)
return rc;
}
+
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c
index 2f150eeb3..7c4b7b63a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_lgcy.c
@@ -24,6 +24,7 @@
#include "nimble/nimble/host/include/host/ble_sm.h"
#include "ble_hs_priv.h"
+#if NIMBLE_BLE_CONNECT
#if MYNEWT_VAL(BLE_SM_LEGACY)
/**
@@ -252,3 +253,4 @@ ble_sm_lgcy_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res)
}
#endif
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c
index 2f481637c..ec3ce08fb 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_sm_sc.c
@@ -24,6 +24,7 @@
#include "ble_hs_priv.h"
#include "ble_sm_priv.h"
+#if NIMBLE_BLE_CONNECT
#if MYNEWT_VAL(BLE_SM_SC)
#define BLE_SM_SC_PASSKEY_BYTES 4
@@ -914,3 +915,4 @@ ble_sm_sc_init(void)
}
#endif /* MYNEWT_VAL(BLE_SM_SC) */
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c
index 1b2443683..45b2a6067 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/src/ble_uuid.c
@@ -228,6 +228,8 @@ ble_uuid_to_mbuf(const ble_uuid_t *uuid, struct os_mbuf *om)
return 0;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpointer-arith"
int
ble_uuid_flat(const ble_uuid_t *uuid, void *dst)
{
@@ -239,10 +241,7 @@ ble_uuid_flat(const ble_uuid_t *uuid, void *dst)
break;
case BLE_UUID_TYPE_32:
memcpy(dst, ble_uuid_base, 16);
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpointer-arith"
put_le32(dst + 12, BLE_UUID32(uuid)->value);
-#pragma GCC diagnostic pop
break;
case BLE_UUID_TYPE_128:
memcpy(dst, BLE_UUID128(uuid)->value, 16);
@@ -253,6 +252,7 @@ ble_uuid_flat(const ble_uuid_t *uuid, void *dst)
return 0;
}
+#pragma GCC diagnostic pop
int
ble_uuid_length(const ble_uuid_t *uuid)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c
index b8195a5b7..57a581732 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/host/util/src/addr.c
@@ -19,27 +19,37 @@
#include "nimble/nimble/host/include/host/ble_hs.h"
#include "../include/host/util/util.h"
+#include "../../src/ble_hs_hci_priv.h"
-#if MYNEWT_VAL(BLE_CONTROLLER)
-#include "nimble/nimble/controller/include/controller/ble_hw.h"
+#if SOC_ESP_NIMBLE_CONTROLLER
+#include "esp_bt.h"
#endif
static int
ble_hs_util_load_rand_addr(ble_addr_t *addr)
{
- /* XXX: It is unfortunate that the function to retrieve the random address
- * is in the controller package. A host-only device ought to be able to
- * automically restore a random address.
- */
-#if MYNEWT_VAL(BLE_CONTROLLER)
+#if MYNEWT_VAL(BLE_HCI_VS)
+ struct ble_hci_vs_rd_static_addr_rp rsp;
int rc;
- rc = ble_hw_get_static_addr(addr);
+ rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_VENDOR,
+ BLE_HCI_OCF_VS_RD_STATIC_ADDR),
+ NULL, 0, &rsp, sizeof(rsp));
if (rc == 0) {
+ addr->type = BLE_ADDR_RANDOM;
+ memcpy(addr->val, rsp.addr, sizeof(addr->val));
return 0;
}
#endif
+#if SOC_ESP_NIMBLE_CONTROLLER
+ int rc;
+
+ rc = esp_ble_hw_get_static_addr((esp_ble_addr_t *)addr);
+ if (rc == 0) {
+ return 0;
+ }
+#endif
return BLE_HS_ENOADDR;
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h
index f6847728c..296198749 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble.h
@@ -81,7 +81,14 @@ struct ble_mbuf_hdr_rxinfo
#endif
};
-/* Flag definitions for rxinfo */
+/*
+ * Flag definitions for rxinfo
+ *
+ * Note: it's ok to have symbols with the same values as long as they cannot be
+ * set for the same PDU (e.g. one use by scanner, other one used by
+ * connection)
+ */
+#define BLE_MBUF_HDR_F_CONN_CREDIT (0x8000)
#define BLE_MBUF_HDR_F_IGNORED (0x8000)
#define BLE_MBUF_HDR_F_SCAN_REQ_TXD (0x4000)
#define BLE_MBUF_HDR_F_INITA_RESOLVED (0x2000)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h
index d4c353f1f..b4c4e9e62 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/ble_hci_trans.h
@@ -66,6 +66,149 @@ struct os_mbuf;
typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg);
typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg);
+#if CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
+struct ble_hci_trans_funcs_t {
+ int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om);
+ int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd);
+ int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om);
+ int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev);
+ int(*_ble_hci_trans_reset)(void);
+ int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb,void *arg);
+};
+
+extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr;
+
+/**
+ * Sends an HCI event from the controller to the host.
+ *
+ * @param cmd The HCI event to send. This buffer must be
+ * allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
+#define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx
+
+/**
+ * Sends ACL data from controller to host.
+ *
+ * @param om The ACL data packet to send.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
+#define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx
+
+/**
+ * Sends an HCI command from the host to the controller.
+ *
+ * @param cmd The HCI command to send. This buffer must be
+ * allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
+#define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx
+
+/**
+ * Sends ACL data from host to controller.
+ *
+ * @param om The ACL data packet to send.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
+#define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type The type of buffer to allocate; one of the
+ * BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return The allocated buffer on success;
+ * NULL on buffer exhaustion.
+ */
+extern uint8_t *r_ble_hci_trans_buf_alloc(int type);
+#define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc
+
+/**
+ * Frees the specified flat buffer. The buffer must have been allocated via
+ * ble_hci_trans_buf_alloc().
+ *
+ * @param buf The buffer to free.
+ */
+extern void r_ble_hci_trans_buf_free(uint8_t *buf);
+#define ble_hci_trans_buf_free r_ble_hci_trans_buf_free
+
+/**
+ * Configures a callback to get executed whenever an ACL data packet is freed.
+ * The function is called immediately before the free occurs.
+ *
+ * @param cb The callback to configure.
+ * @param arg An optional argument to pass to the callback.
+ *
+ * @return 0 on success;
+ * BLE_ERR_UNSUPPORTED if the transport does not
+ * support this operation.
+ */
+extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg);
+#define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb
+
+/**
+ * Configures the HCI transport to operate with a controller. The transport
+ * will execute specified callbacks upon receiving HCI packets from the host.
+ *
+ * @param cmd_cb The callback to execute upon receiving an HCI
+ * command.
+ * @param cmd_arg Optional argument to pass to the command
+ * callback.
+ * @param acl_cb The callback to execute upon receiving ACL
+ * data.
+ * @param acl_arg Optional argument to pass to the ACL
+ * callback.
+ */
+extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
+ void *cmd_arg,
+ ble_hci_trans_rx_acl_fn *acl_cb,
+ void *acl_arg);
+#define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll
+
+/**
+ * Configures the HCI transport to operate with a host. The transport will
+ * execute specified callbacks upon receiving HCI packets from the controller.
+ *
+ * @param evt_cb The callback to execute upon receiving an HCI
+ * event.
+ * @param evt_arg Optional argument to pass to the event
+ * callback.
+ * @param acl_cb The callback to execute upon receiving ACL
+ * data.
+ * @param acl_arg Optional argument to pass to the ACL
+ * callback.
+ */
+extern void r_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);
+#define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs
+
+/**
+ * Resets the HCI module to a clean state. Frees all buffers and reinitializes
+ * the underlying transport.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+extern int r_ble_hci_trans_reset(void);
+#define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset
+
+void esp_ble_hci_trans_init(uint8_t);
+#else
/**
* Sends an HCI event from the controller to the host.
*
@@ -185,6 +328,78 @@ void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
*/
int ble_hci_trans_reset(void);
+
+/**
+ * Sends an HCI command from the host to the controller.
+ *
+ * @param cmd The HCI command to send. This buffer must be
+ * allocated via ble_hci_trans_buf_alloc().
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int esp_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
+
+/**
+ * Sends ACL data from host to controller.
+ *
+ * @param om The ACL data packet to send.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int esp_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
+
+/**
+ * Allocates a flat buffer of the specified type.
+ *
+ * @param type The type of buffer to allocate; one of the
+ * BLE_HCI_TRANS_BUF_[...] constants.
+ *
+ * @return The allocated buffer on success;
+ * NULL on buffer exhaustion.
+ */
+uint8_t *esp_ble_hci_trans_buf_alloc(int type);
+
+/**
+ * Frees the specified flat buffer. The buffer must have been allocated via
+ * ble_hci_trans_buf_alloc().
+ *
+ * @param buf The buffer to free.
+ */
+void esp_ble_hci_trans_buf_free(uint8_t *buf);
+
+/**
+ * Configures the HCI transport to operate with a host. The transport will
+ * execute specified callbacks upon receiving HCI packets from the controller.
+ *
+ * @param evt_cb The callback to execute upon receiving an HCI
+ * event.
+ * @param evt_arg Optional argument to pass to the event
+ * callback.
+ * @param acl_cb The callback to execute upon receiving ACL
+ * data.
+ * @param acl_arg Optional argument to pass to the ACL
+ * callback.
+ */
+void esp_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);
+
+/**
+ * Resets the HCI module to a clean state. Frees all buffers and reinitializes
+ * the underlying transport.
+ *
+ * @return 0 on success;
+ * A BLE_ERR_[...] error code on failure.
+ */
+int esp_ble_hci_trans_reset(void);
+
+
+#endif
+
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/hci_common.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/hci_common.h
index 10b42e71d..69c8d78e1 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/hci_common.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/include/nimble/hci_common.h
@@ -201,6 +201,14 @@ struct ble_hci_le_rd_buf_size_rp {
uint8_t data_packets;
} __attribute__((packed));
+#define BLE_HCI_OCF_LE_RD_BUF_SIZE_V2 (0x0060)
+struct ble_hci_le_rd_buf_size_v2_rp {
+ uint16_t data_len;
+ uint8_t data_packets;
+ uint16_t iso_data_len;
+ uint8_t iso_data_packets;
+} __attribute__((packed));
+
#define BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT (0x0003)
struct ble_hci_le_rd_loc_supp_feat_rp {
uint64_t features;
@@ -825,12 +833,240 @@ struct ble_hci_le_set_default_periodic_sync_transfer_params_cp {
#define BLE_HCI_OCF_LE_GENERATE_DHKEY_V2 (0x005E)
#define BLE_HCI_OCF_LE_MODIFY_SCA (0x005F)
+#if MYNEWT_VAL(BLE_ISO)
+#define BLE_HCI_OCF_LE_READ_ISO_TX_SYNC (0x0061)
+struct ble_hci_le_read_iso_tx_sync_cp {
+ uint16_t conn_handle;
+} __attribute__((packed));
+
+struct ble_hci_le_read_iso_tx_sync_rp {
+ uint16_t conn_handle;
+ uint16_t packet_seq_num;
+ uint32_t timestamp;
+ uint8_t timeoffset[3];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SET_CIG_CIS_MAX_NUM (0x1F)
+#define BLE_HCI_OCF_LE_SET_CIG_PARAM (0x0062)
+struct ble_hci_le_cis_params {
+ uint8_t cis_id;
+ uint16_t max_sdu_mtos;
+ uint16_t max_sdu_stom;
+ uint8_t phy_mtos;
+ uint8_t phy_stom;
+ uint8_t rnt_mtos;
+ uint8_t rnt_stom;
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_cp {
+ uint8_t cig_id;
+ uint8_t sdu_interval_mtos[3];
+ uint8_t sdu_interval_stom[3];
+ uint8_t sca;
+ uint8_t packing;
+ uint8_t framing;
+ uint16_t max_latency_mtos;
+ uint16_t max_latency_stom;
+ uint8_t cis_cnt;
+ struct ble_hci_le_cis_params cis_params[0];
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_rp {
+ uint8_t cig_id;
+ uint8_t cis_cnt;
+ uint16_t cis_handle[0];
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST (0x0063)
+struct ble_hci_le_cis_params_test {
+ uint8_t cis_id;
+ uint8_t nse;
+ uint16_t max_sdu_mtos;
+ uint16_t max_sdu_stom;
+ uint16_t max_pdu_mtos;
+ uint16_t max_pdu_stom;
+ uint8_t phy_mtos;
+ uint8_t phy_stom;
+ uint8_t bn_mtos;
+ uint8_t bn_stom;
+} __attribute__((packed));
+
+struct ble_hci_le_set_cig_params_test_cp {
+ uint8_t cig_id;
+ uint8_t sdu_interval_mtos[3];
+ uint8_t sdu_interval_stom[3];
+ uint8_t ft_mtos;
+ uint8_t ft_stom;
+ uint16_t iso_interval;
+ uint8_t sca;
+ uint8_t packing;
+ uint8_t framing;
+ uint8_t cis_cnt;
+ struct ble_hci_le_cis_params_test cis_params[0];
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_LE_CREATE_CIS_MAX_CIS_NUM (0x1F)
+#define BLE_HCI_OCF_LE_CREATE_CIS (0x0064)
+struct ble_hci_le_create_cis_params {
+ uint16_t cis_handle;
+ uint16_t conn_handle;
+} __attribute__((packed));
+
+struct ble_hci_le_create_cis_cp {
+ uint8_t cis_cnt;
+ struct ble_hci_le_create_cis_params params[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REMOVE_CIG (0x0065)
+struct ble_hci_le_remove_cig_cp {
+ uint8_t cig_id;
+} __attribute__((packed));
+
+struct ble_hci_le_remove_cig_rp {
+ uint8_t cig_id;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ACCEPT_CIS_REQ (0x0066)
+struct ble_hci_le_accept_cis_request_cp {
+ uint16_t cis_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_REJECT_CIS_REQ (0x0067)
+struct ble_hci_le_reject_cis_request_cp {
+ uint16_t cis_handle;
+ uint8_t reason;
+} __attribute__((packed));
+
+struct ble_hci_le_reject_cis_request_rp {
+ uint16_t conn_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_CREATE_BIG (0x0068)
+struct ble_hci_le_create_big_cp {
+ uint8_t big_handle;
+ uint8_t adv_handle;
+ uint8_t bis_cnt;
+ uint8_t sdu_interval[3];
+ uint16_t max_sdu;
+ uint16_t max_transport_latency;
+ uint8_t rnt;
+ uint8_t phy;
+ uint8_t packing;
+ uint8_t framing;
+ uint8_t encryption;
+ uint8_t broadcast_code[16];
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_CREATE_BIG_TEST (0x0069)
+struct ble_hci_le_create_big_test_cp {
+ uint8_t big_handle;
+ uint8_t adv_handle;
+ uint8_t bis_cnt;
+ uint8_t sdu_interval[3];
+ uint16_t iso_interval;
+ uint8_t nse;
+ uint16_t max_sdu;
+ uint16_t max_pdu;
+ uint8_t phy;
+ uint8_t packing;
+ uint8_t framing;
+ uint8_t bn;
+ uint8_t irc;
+ uint8_t pto;
+ uint8_t encryption;
+ uint8_t broadcast_code[16];
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_OCF_LE_TERMINATE_BIG (0x006a)
+struct ble_hci_le_terminate_big_cp {
+ uint8_t big_handle;
+ uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_BIG_CREATE_SYNC_LEN_MIN (25)
+#define BLE_HCI_OCF_LE_BIG_CREATE_SYNC (0x006b)
+struct ble_hci_le_big_create_sync_cp {
+ uint8_t big_handle;
+ uint16_t sync_handle;
+ uint8_t big_cnt;
+ uint8_t encryption;
+ uint8_t broadcast_code[16];
+ uint8_t mse;
+ uint16_t timeout;
+ uint8_t bis[0];
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC (0x006c)
+struct ble_hci_le_terminate_big_sync_cp {
+ uint8_t big_handle;
+} __attribute__((packed));
+#endif
+
+#define BLE_HCI_OCF_LE_REQ_PEER_SCA (0x006d)
+struct ble_hci_le_request_peer_sca_cp {
+ uint16_t conn_handle;
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO)
+#define BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH (0x006e)
+struct ble_hci_le_iso_setup_data_path_cp {
+ uint16_t iso_handle;
+ uint8_t direction;
+ uint8_t id;
+ uint8_t codec_id[5];
+ uint8_t controller_delay[3];
+ uint8_t codec_conf_len;
+ uint8_t codec_conf[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_REMOVE_INPUT_DATA_PATH_BIT (0x01)
+#define BLE_HCI_LE_REMOVE_OUTPUT_DATA_PATH_BIT (0x02)
+#define BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH (0x006f)
+struct ble_hci_le_iso_remove_data_path_cp {
+ uint16_t iso_handle;
+ uint8_t direction;
+} __attribute__((packed));
+
+#if MYNEWT_VAL(BLE_ISO_TEST)
+#define BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST (0x0070)
+struct ble_hci_le_iso_transmit_test_cp {
+ uint16_t iso_handle;
+ uint8_t payload_type;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_RECEIVE_TEST (0x0071)
+struct ble_hci_le_iso_receive_test_cp {
+ uint16_t iso_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS (0x0072)
+struct ble_hci_le_iso_read_test_counters_cp {
+ uint16_t iso_handle;
+} __attribute__((packed));
+
+#define BLE_HCI_OCF_LE_ISO_TEST_END (0x0073)
+struct ble_hci_le_iso_test_end_cp {
+ uint16_t iso_handle;
+} __attribute__((packed));
+#endif
+#endif
+
#define BLE_HCI_OCF_LE_SET_HOST_FEAT (0x0074)
struct ble_hci_le_set_host_feat_cp {
uint8_t bit_num;
uint8_t val;
} __attribute__((packed));
+/* --- Vendor specific commands (OGF 0x00FF) */
+#define BLE_HCI_OCF_VS_RD_STATIC_ADDR (0x0001)
+struct ble_hci_vs_rd_static_addr_rp {
+ uint8_t addr[6];
+} __attribute__((packed));
+
/* Command Specific Definitions */
/* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */
#define BLE_HCI_CTLR_TO_HOST_FC_OFF (0)
@@ -979,6 +1215,12 @@ struct ble_hci_le_set_host_feat_cp {
#define BLE_HCI_SET_DATALEN_TX_TIME_MIN (0x0148)
#define BLE_HCI_SET_DATALEN_TX_TIME_MAX (0x4290)
+/* --- LE read/write suggested default data length (OCF 0x0023 and 0x0024) */
+#define BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN (0x001b)
+#define BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX (0x00fb)
+#define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN (0x0148)
+#define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX (0x4290)
+
/* --- LE read maximum default PHY (OCF 0x0030) */
#define BLE_HCI_LE_PHY_1M (1)
#define BLE_HCI_LE_PHY_2M (2)
@@ -1212,7 +1454,7 @@ struct ble_hci_ev_auth_pyld_tmo {
struct ble_hci_ev_vendor_debug {
uint8_t id;
uint8_t data[0];
-}__attribute__((packed));
+} __attribute__((packed));
/* LE sub-event codes */
#define BLE_HCI_LE_SUBEV_CONN_COMPLETE (0x01)
@@ -1444,6 +1686,110 @@ struct ble_hci_ev_le_subev_periodic_adv_sync_transfer {
uint8_t aca;
} __attribute__((packed));
+#define BLE_HCI_LE_SUBEV_CIS_ESTAB (0x19)
+struct ble_hci_ev_le_subev_cis_established {
+ uint8_t subev_code;
+ uint8_t status;
+ uint16_t cis_handle;
+ uint8_t cig_sync_delay[3];
+ uint8_t cis_sync_delay[3];
+ uint8_t trans_latency_mtos[3];
+ uint8_t trans_latency_stom[3];
+ uint8_t phy_mtos;
+ uint8_t phy_stom;
+ uint8_t nse;
+ uint8_t bn_mtos;
+ uint8_t bn_stom;
+ uint8_t ft_mtos;
+ uint8_t ft_stom;
+ uint16_t max_pdu_mtos;
+ uint16_t max_pdu_stom;
+ uint16_t iso_interval;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_CIS_REQUEST (0x1A)
+struct ble_hci_ev_le_subev_cis_request {
+ uint8_t subev_code;
+ uint16_t conn_handle;
+ uint16_t cis_handle;
+ uint8_t cig_id;
+ uint8_t cis_id;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_COMP (0x1B)
+struct ble_hci_ev_le_subev_big_complete {
+ uint8_t subev_code;
+ uint8_t status;
+ uint8_t big_handle;
+ uint8_t big_sync_delay[3];
+ uint8_t transport_latency[3];
+ uint8_t phy;
+ uint8_t nse;
+ uint8_t bn;
+ uint8_t pto;
+ uint8_t irc;
+ uint16_t max_pdu;
+ uint16_t iso_interval;
+ uint8_t bis_cnt;
+ uint16_t bis[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_TERMINATE_COMP (0x1C)
+struct ble_hci_ev_le_subev_big_terminate_complete {
+ uint8_t subev_code;
+ uint8_t big_handle;
+ uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_SYNC_ESTAB (0x1D)
+struct ble_hci_ev_le_subev_big_sync_established {
+ uint8_t subev_code;
+ uint8_t status;
+ uint8_t big_handle;
+ uint8_t transport_latency[3];
+ uint8_t nse;
+ uint8_t bn;
+ uint8_t pto;
+ uint8_t irc;
+ uint16_t max_pdu;
+ uint16_t iso_interval;
+ uint8_t bis_cnt;
+ uint16_t bis_handles[0];
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIG_SYNC_LOST (0x1E)
+struct ble_hci_ev_le_subev_big_sync_lost {
+ uint8_t subev_code;
+ uint8_t big_handle;
+ uint8_t reason;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP (0x1F)
+struct ble_hci_ev_le_subev_peer_sca_complete {
+ uint8_t subev_code;
+ uint8_t status;
+ uint16_t conn_handle;
+ uint8_t sca;
+} __attribute__((packed));
+
+#define BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT (0x22)
+struct ble_hci_ev_le_subev_biginfo_adv_report {
+ uint8_t subev_code;
+ uint16_t sync_handle;
+ uint8_t bis_cnt;
+ uint8_t nse;
+ uint16_t iso_interval;
+ uint8_t bn;
+ uint8_t pto;
+ uint8_t irc;
+ uint16_t max_pdu;
+ uint8_t sdu_interval[3];
+ uint16_t max_sdu;
+ uint8_t phy;
+ uint8_t framing;
+ uint8_t encryption;
+} __attribute__((packed));
+
/* Data buffer overflow event */
#define BLE_HCI_EVENT_ACL_BUF_OVERFLOW (0x01)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c
index 9eaa1d866..eca28d266 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/nimble/transport/ram/src/ble_hci_ram.c
@@ -94,7 +94,7 @@ ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
}
int
-ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
+IRAM_ATTR ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
{
int rc;
@@ -127,7 +127,7 @@ ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
}
uint8_t *
-ble_hci_trans_buf_alloc(int type)
+IRAM_ATTR ble_hci_trans_buf_alloc(int type)
{
uint8_t *buf;
@@ -159,7 +159,7 @@ ble_hci_trans_buf_alloc(int type)
}
void
-ble_hci_trans_buf_free(uint8_t *buf)
+IRAM_ATTR ble_hci_trans_buf_free(uint8_t *buf)
{
int rc;
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h
index 00db3e2e1..377937ed0 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/log_common/log_common.h
@@ -20,12 +20,21 @@
#ifndef H_LOG_COMMON_
#define H_LOG_COMMON_
+#include
#include "ignore.h"
#ifdef __cplusplus
extern "C" {
#endif
+struct log;
+
+#define LOG_VERSION_V3 3
+
+#define LOG_TYPE_STREAM (0)
+#define LOG_TYPE_MEMORY (1)
+#define LOG_TYPE_STORAGE (2)
+
/*
#define LOG_LEVEL_DEBUG (0)
#define LOG_LEVEL_INFO (1)
@@ -40,10 +49,103 @@ extern "C" {
#define LOG_LEVEL_ERROR (1)
#define LOG_LEVEL_CRITICAL (5)
#define LOG_LEVEL_NONE (0)
-
/* Up to 7 custom log levels. */
#define LOG_LEVEL_MAX (15)
+#define LOG_LEVEL_STR(level) \
+ (LOG_LEVEL_DEBUG == level ? "DEBUG" :\
+ (LOG_LEVEL_INFO == level ? "INFO" :\
+ (LOG_LEVEL_WARN == level ? "WARN" :\
+ (LOG_LEVEL_ERROR == level ? "ERROR" :\
+ (LOG_LEVEL_CRITICAL == level ? "CRITICAL" :\
+ "UNKNOWN")))))
+
+/* XXX: These module IDs are defined for backwards compatibility. Application
+ * code should use the syscfg settings directly. These defines will be removed
+ * in a future release.
+ */
+#define LOG_MODULE_DEFAULT 0
+#define LOG_MODULE_OS 1
+#define LOG_MODULE_NEWTMGR 2
+#define LOG_MODULE_NIMBLE_CTLR 3
+#define LOG_MODULE_NIMBLE_HOST 4
+#define LOG_MODULE_NFFS 5
+#define LOG_MODULE_REBOOT 6
+#define LOG_MODULE_IOTIVITY 7
+#define LOG_MODULE_TEST 8
+
+#define LOG_MODULE_PERUSER 64
+#define LOG_MODULE_MAX (255)
+
+#define LOG_ETYPE_STRING (0)
+#define LOG_ETYPE_CBOR (1)
+#define LOG_ETYPE_BINARY (2)
+
+/* UTC Timestamp for Jan 2016 00:00:00 */
+#define UTC01_01_2016 1451606400
+
+#define LOG_NAME_MAX_LEN (64)
+
+#ifndef MYNEWT_VAL_LOG_LEVEL
+#define LOG_SYSLEVEL ((uint8_t)LOG_LEVEL_MAX)
+#else
+#define LOG_SYSLEVEL ((uint8_t)MYNEWT_VAL_LOG_LEVEL)
+#endif
+
+/**
+ * @brief Determines if a log module will accept an entry with a given level.
+ *
+ * A log entry is only accepted if its level is less than or equal to both:
+ * o Global log level setting (LOG_LEVEL), and
+ * o The specified module log level
+ *
+ * @param mod_level The module's minimum log level.
+ * @param entry_level The level of the entry to be logged.
+ *
+ * @return true if the entry would be logged;
+ * false otherwise.
+ */
+#define LOG_MOD_LEVEL_IS_ACTIVE(mod_level, entry_level) \
+ (LOG_LEVEL <= (entry_level) && (mod_level) <= (entry_level))
+
+/* Newtmgr Log opcodes */
+#define LOGS_NMGR_OP_READ (0)
+#define LOGS_NMGR_OP_CLEAR (1)
+#define LOGS_NMGR_OP_APPEND (2)
+#define LOGS_NMGR_OP_MODULE_LIST (3)
+#define LOGS_NMGR_OP_LEVEL_LIST (4)
+#define LOGS_NMGR_OP_LOGS_LIST (5)
+#define LOGS_NMGR_OP_SET_WATERMARK (6)
+#define LOGS_NMGR_OP_MODLEVEL (8)
+
+#define LOG_PRINTF_MAX_ENTRY_LEN (128)
+
+/* Global log info */
+struct log_info {
+#if MYNEWT_VAL(LOG_GLOBAL_IDX)
+ uint32_t li_next_index;
+#endif
+ uint8_t li_version;
+};
+
+extern struct log_info g_log_info;
+
+/** @typedef log_append_cb
+ * @brief Callback that is executed each time the corresponding log is appended
+ * to.
+ *
+ * @param log The log that was just appended to.
+ * @param idx The index of newly appended log entry.
+ */
+typedef void log_append_cb(struct log *log, uint32_t idx);
+
+/** @typdef log_notify_rotate_cb
+ * @brief Callback that is executed each time we are about to rotate a log.
+ *
+ * @param log The log that is about to rotate
+ */
+typedef void log_notify_rotate_cb(const struct log *log);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h
index d7422cc8f..b72f3721d 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/logcfg/logcfg.h
@@ -1,9 +1,9 @@
/**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
*/
-#ifndef H_MYNEWT_LOGCFG_
-#define H_MYNEWT_LOGCFG_
+#ifndef H_LOGCFG_
+#define H_LOGCFG_
#include "../modlog/modlog.h"
#include "../log_common/log_common.h"
@@ -131,6 +131,34 @@
#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__)
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/mem/mem.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/mem/mem.h
index 13a325b5a..bfe7cb392 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/mem/mem.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/mem/mem.h
@@ -27,6 +27,34 @@ extern "C" {
struct os_mempool;
struct os_mbuf_pool;
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+int r_mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks,
+ uint32_t block_size, char *name, void **out_buf);
+#define mem_malloc_mempool r_mem_malloc_mempool
+
+int r_mem_malloc_mempool_ext(struct os_mempool_ext *mempool, uint16_t num_blocks,
+ uint32_t block_size, char *name, void **out_buf);
+#define mem_malloc_mempool_ext r_mem_malloc_mempool_ext
+
+
+int r_mem_malloc_mbuf_pool(struct os_mempool *mempool,
+ struct os_mbuf_pool *mbuf_pool, uint16_t num_blocks,
+ uint32_t block_size, char *name,
+ void **out_buf);
+#define mem_malloc_mbuf_pool r_mem_malloc_mbuf_pool
+
+int r_mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
+ struct os_mbuf_pool *mbuf_pool, int num_blocks,
+ int block_size, char *name,
+ void **out_buf);
+#define mem_malloc_mbufpkt_pool r_mem_malloc_mbufpkt_pool
+
+int r_mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
+ struct os_mbuf_pool *mbuf_pool, int num_blocks,
+ int block_size, const char *name);
+#define mem_init_mbuf_pool r_mem_init_mbuf_pool
+#else
int mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks,
uint32_t block_size, char *name, void **out_buf);
int mem_malloc_mempool_ext(struct os_mempool_ext *mempool, uint16_t num_blocks,
@@ -43,6 +71,7 @@ int mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, const char *name);
+#endif
/**
* Specifies a function used as a callback. Functions of this type allocate an
@@ -58,9 +87,19 @@ int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
*/
typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+struct os_mbuf *r_mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
+ mem_frag_alloc_fn *alloc_cb, void *cb_arg);
+#define mem_split_frag r_mem_split_frag
+void *r_mem_pullup_obj(struct os_mbuf **om, uint16_t len);
+#define mem_pullup_obj r_mem_pullup_obj
+#else
struct os_mbuf *mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
mem_frag_alloc_fn *alloc_cb, void *cb_arg);
+void *mem_pullup_obj(struct os_mbuf **om, uint16_t len);
+#endif
#ifdef __cplusplus
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h
index c12b13991..2d56be990 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/modlog/modlog.h
@@ -22,6 +22,7 @@
#include
+#include "../log_common/log_common.h"
#include "../log/log.h"
#include "../log_common/log_common.h"
@@ -33,7 +34,7 @@
#define MODLOG_MODULE_DFLT 255
-#if defined(ESP_PLATFORM) && !defined(ARDUINO_ARCH_ESP32)
+#ifdef ESP_PLATFORM
#define MODLOG_ESP_LOCAL(level, ml_msg_, ...) do { \
if (MYNEWT_VAL(BLE_HS_LOG_LVL) <= LOG_LOCAL_LEVEL) ESP_LOG_LEVEL_LOCAL(level, "NimBLE", ml_msg_, ##__VA_ARGS__); \
} while(0)
@@ -55,54 +56,39 @@
#else
-#if (MYNEWT_VAL(LOG_LEVEL) > 0)
-static inline void
-modlog_dummy(const char *msg, ...)
-{
- (void)msg;
-}
-#endif
-
-#include "nimble/console/console.h"
-
-#if (MYNEWT_VAL(LOG_LEVEL) > 0)
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_DEBUG || defined __DOXYGEN__
#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
- modlog_dummy((ml_msg_), ##__VA_ARGS__)
+ printf((ml_msg_), ##__VA_ARGS__)
#else
-#define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \
- console_printf((ml_msg_), ##__VA_ARGS__);
+#define MODLOG_DEBUG(ml_mod_, ...)
#endif
-#if (MYNEWT_VAL(LOG_LEVEL) > 1)
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_INFO || defined __DOXYGEN__
#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
- modlog_dummy((ml_msg_), ##__VA_ARGS__)
+ printf((ml_msg_), ##__VA_ARGS__)
#else
-#define MODLOG_INFO(ml_mod_, ml_msg_, ...) \
- console_printf((ml_msg_), ##__VA_ARGS__);
+#define MODLOG_INFO(ml_mod_, ...)
#endif
-#if (MYNEWT_VAL(LOG_LEVEL) > 2)
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_WARN || defined __DOXYGEN__
#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
- modlog_dummy((ml_msg_), ##__VA_ARGS__)
+ printf((ml_msg_), ##__VA_ARGS__)
#else
-#define MODLOG_WARN(ml_mod_, ml_msg_, ...) \
- console_printf((ml_msg_), ##__VA_ARGS__);
+#define MODLOG_WARN(ml_mod_, ...)
#endif
-#if (MYNEWT_VAL(LOG_LEVEL) > 3)
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_ERROR || defined __DOXYGEN__
#define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \
- modlog_dummy((ml_msg_), ##__VA_ARGS__)
+ printf((ml_msg_), ##__VA_ARGS__)
#else
-#define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \
- console_printf((ml_msg_), ##__VA_ARGS__);
+#define MODLOG_ERROR(ml_mod_, ...)
#endif
-#if (MYNEWT_VAL(LOG_LEVEL) > 4)
+#if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_CRITICAL || defined __DOXYGEN__
#define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \
- modlog_dummy((ml_msg_), ##__VA_ARGS__)
+ printf((ml_msg_), ##__VA_ARGS__)
#else
-#define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \
- console_printf((ml_msg_), ##__VA_ARGS__);
+#define MODLOG_CRITICAL(ml_mod_, ...)
#endif
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h
index 68e7cdbb8..677b43d00 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/nimble/nimble_port.h
@@ -23,12 +23,17 @@
#include "nimble/nimble/include/nimble/nimble_npl.h"
#ifdef ESP_PLATFORM
+#include "esp_err.h"
#include "nimconfig.h"
#define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY)
-#define NIMBLE_STACK_SIZE CONFIG_BT_NIMBLE_TASK_STACK_SIZE
+#define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE
#else
#include "../syscfg/syscfg.h"
-#define NIMBLE_HS_TASK_STACK_SIZE (CONFIG_BT_NIMBLE_TASK_STACK_SIZE / 4)
+#define NIMBLE_HS_STACK_SIZE (CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE / 4)
+#endif
+
+#if (CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2)
+#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
#endif
#ifdef __cplusplus
@@ -41,6 +46,22 @@ void nimble_port_deinit(void);
void nimble_port_run(void);
int nimble_port_stop(void);
+#ifdef ESP_PLATFORM
+/**
+ * @brief esp_nimble_init - Initialize the NimBLE host stack
+ *
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_init(void);
+
+/**
+ * @brief esp_nimble_deinit - Deinitialize the NimBLE host stack
+ *
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_deinit(void);
+#endif // ESP_PLATFORM
+
struct ble_npl_eventq *nimble_port_get_dflt_eventq(void);
#if NIMBLE_CFG_CONTROLLER
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/endian.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/endian.h
index 152727225..895463340 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/endian.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/endian.h
@@ -189,7 +189,7 @@ extern "C" {
#endif
#ifndef htobe64
-#define htobe64(x) os_bswap64(x)
+#define htobe64(x) os_bswap_64(x)
#endif
#ifndef htole64
@@ -197,7 +197,7 @@ extern "C" {
#endif
#ifndef be64toh
-#define be64toh(x) os_bswap64(x)
+#define be64toh(x) os_bswap_64(x)
#endif
#ifndef le64toh
@@ -206,6 +206,63 @@ extern "C" {
#endif
+#if SOC_ESP_NIMBLE_CONTROLLER
+void r_put_le16(void *buf, uint16_t x);
+#define put_le16 r_put_le16
+
+void r_put_le24(void *buf, uint32_t x);
+#define put_le24 r_put_le24
+
+void r_put_le32(void *buf, uint32_t x);
+#define put_le32 r_put_le32
+
+void r_put_le64(void *buf, uint64_t x);
+#define put_le64 r_put_le64
+
+uint16_t r_get_le16(const void *buf);
+#define get_le16 r_get_le16
+
+uint32_t r_get_le24(const void *buf);
+#define get_le24 r_get_le24
+
+uint32_t r_get_le32(const void *buf);
+#define get_le32 r_get_le32
+
+uint64_t r_get_le64(const void *buf);
+#define get_le64 r_get_le64
+
+void r_put_be16(void *buf, uint16_t x);
+#define put_be16 r_put_be16
+
+void r_put_be24(void *buf, uint32_t x);
+#define put_be24 r_put_be24
+
+void r_put_be32(void *buf, uint32_t x);
+#define put_be32 r_put_be32
+
+void r_put_be64(void *buf, uint64_t x);
+#define put_be64 r_put_be64
+
+uint16_t r_get_be16(const void *buf);
+#define get_be16 r_get_be16
+
+uint32_t r_get_be24(const void *buf);
+#define get_be24 r_get_be24
+
+uint32_t r_get_be32(const void *buf);
+#define get_be32 r_get_be32
+
+uint64_t r_get_be64(const void *buf);
+#define get_be64 r_get_be64
+
+void r_swap_in_place(void *buf, int len);
+#define swap_in_place r_swap_in_place
+
+void r_swap_buf(uint8_t *dst, const uint8_t *src, int len);
+#define swap_buf r_swap_buf
+
+
+#else
void put_le16(void *buf, uint16_t x);
void put_le24(void *buf, uint32_t x);
void put_le32(void *buf, uint32_t x);
@@ -224,7 +281,7 @@ uint32_t get_be32(const void *buf);
uint64_t get_be64(const void *buf);
void swap_in_place(void *buf, int len);
void swap_buf(uint8_t *dst, const uint8_t *src, int len);
-
+#endif
#ifdef __cplusplus
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h
index d4f6101b7..bc456b2a5 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os.h
@@ -26,6 +26,10 @@
extern "C" {
#endif
+#if !defined __cplusplus
+#define static_assert _Static_assert
+#endif
+
#ifndef min
#define min(a, b) ((a)<(b)?(a):(b))
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h
index 9002ca56a..820bf5d13 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_cputime.h
@@ -17,12 +17,12 @@
* under the License.
*/
- /**
- * @addtogroup OSKernel
- * @{
- * @defgroup OSCPUTime High Resolution Timers
- * @{
- */
+/**
+ * @addtogroup OSKernel
+ * @{
+ * @defgroup OSCPUTime High Resolution Timers
+ * @{
+ */
#ifndef H_OS_CPUTIME_
#define H_OS_CPUTIME_
@@ -33,7 +33,6 @@ extern "C" {
#include "../syscfg/syscfg.h"
#include "../hal/hal_timer.h"
-#include "os.h"
/*
* NOTE: these definitions allow one to override the cputime frequency used.
@@ -56,6 +55,7 @@ extern "C" {
MYNEWT_VAL(OS_CPUTIME_FREQ) == 8192 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 16384 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768 || \
+ MYNEWT_VAL(OS_CPUTIME_FREQ) == 32000 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 65536 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 131072 || \
MYNEWT_VAL(OS_CPUTIME_FREQ) == 262144 || \
@@ -88,9 +88,9 @@ extern struct os_cputime_data g_os_cputime;
#define CPUTIME_LT(__t1, __t2) ((int32_t) ((__t1) - (__t2)) < 0)
/** evaluates to true if t1 is after t2 in time */
#define CPUTIME_GT(__t1, __t2) ((int32_t) ((__t1) - (__t2)) > 0)
-/** evaluates to true if t1 is after t2 in time */
-#define CPUTIME_GEQ(__t1, __t2) ((int32_t) ((__t1) - (__t2)) >= 0)
/** evaluates to true if t1 is on or after t2 in time */
+#define CPUTIME_GEQ(__t1, __t2) ((int32_t) ((__t1) - (__t2)) >= 0)
+/** evaluates to true if t1 is on or before t2 in time */
#define CPUTIME_LEQ(__t1, __t2) ((int32_t) ((__t1) - (__t2)) <= 0)
/**
@@ -188,7 +188,7 @@ void os_cputime_delay_usecs(uint32_t usecs);
* @param arg Pointer to data object to pass to timer.
*/
void os_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp,
- void *arg);
+ void *arg);
/**
* Start a cputimer that will expire at 'cputime'. If cputime has already
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h
index f2213bdf9..44f5d870e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_error.h
@@ -22,6 +22,11 @@
#include "os.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* OS error enumerations */
enum os_error {
OS_OK = 0,
OS_ENOMEM = 1,
@@ -40,4 +45,18 @@ enum os_error {
typedef enum os_error os_error_t;
+/**
+ * @brief Converts an OS error code (`OS_[...]`) to an equivalent system error
+ * code (`SYS_E[...]`).
+ *
+ * @param os_error The OS error code to convert.
+ *
+ * @return The equivalent system error code.
+ */
+int os_error_to_sys(os_error_t os_error);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h
index 0775556d2..77ecef00a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mbuf.h
@@ -189,7 +189,7 @@ _os_mbuf_leadingspace(struct os_mbuf *om)
}
leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) -
- ((uint8_t *) &om->om_databuf[0] + startoff));
+ ((uint8_t *) &om->om_databuf[0] + startoff));
return (leadingspace);
}
@@ -220,7 +220,7 @@ _os_mbuf_trailingspace(struct os_mbuf *om)
omp = om->om_omp;
return (&om->om_databuf[0] + omp->omp_databuf_len) -
- (om->om_data + om->om_len);
+ (om->om_data + om->om_len);
}
/** @endcond */
@@ -237,6 +237,467 @@ _os_mbuf_trailingspace(struct os_mbuf *om)
#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
+#if SOC_ESP_NIMBLE_CONTROLLER
+/**
+ * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a
+ * particular task's event queue. Mqueues form a helper API around a common
+ * paradigm: wait on an event queue until at least one packet is available,
+ * then process a queue of packets.
+ *
+ * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
+ * will be posted to the task's mbuf queue.
+ *
+ * @param mq The mqueue to initialize
+ * @param ev_cb The callback to associate with the mqeueue
+ * event. Typically, this callback pulls each
+ * packet off the mqueue and processes them.
+ * @param arg The argument to associate with the mqueue event.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int r_os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
+#define os_mqueue_init r_os_mqueue_init
+
+
+/**
+ * Remove and return a single mbuf from the mbuf queue. Does not block.
+ *
+ * @param mq The mbuf queue to pull an element off of.
+ *
+ * @return The next mbuf in the queue, or NULL if queue has no mbufs.
+ */
+struct os_mbuf *r_os_mqueue_get(struct os_mqueue *);
+#define os_mqueue_get r_os_mqueue_get
+/**
+ * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
+ * with the mqueue gets posted to the specified eventq.
+ *
+ * @param mq The mbuf queue to append the mbuf to.
+ * @param evq The event queue to post an event to.
+ * @param m The mbuf to append to the mbuf queue.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int r_os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
+#define os_mqueue_put r_os_mqueue_put
+
+
+/**
+ * MSYS is a system level mbuf registry. Allows the system to share
+ * packet buffers amongst the various networking stacks that can be running
+ * simultaeneously.
+ *
+ * Mbuf pools are created in the system initialization code, and then when
+ * a mbuf is allocated out of msys, it will try and find the best fit based
+ * upon estimated mbuf size.
+ *
+ * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
+ * allocate mbufs out of it.
+ *
+ * @param new_pool The pool to register with MSYS
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int r_os_msys_register(struct os_mbuf_pool *);
+#define os_msys_register r_os_msys_register
+
+
+/**
+ * Allocate a mbuf from msys. Based upon the data size requested,
+ * os_msys_get() will choose the mbuf pool that has the best fit.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param leadingspace The amount of leadingspace to allocate in the mbuf
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_msys_get(uint16_t dsize, uint16_t leadingspace);
+#define os_msys_get r_os_msys_get
+/**
+ * De-registers all mbuf pools from msys.
+ */
+void r_os_msys_reset(void);
+#define os_msys_reset r_os_msys_reset
+
+
+/**
+ * Allocate a packet header structure from the MSYS pool. See
+ * os_msys_register() for a description of MSYS.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param user_hdr_len The length to allocate for the packet header structure
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
+#define os_msys_get_pkthdr r_os_msys_get_pkthdr
+/**
+ * Count the number of blocks in all the mbuf pools that are allocated.
+ *
+ * @return total number of blocks allocated in Msys
+ */
+int r_os_msys_count(void);
+#define os_msys_count r_os_msys_count
+
+
+/**
+ * Return the number of free blocks in Msys
+ *
+ * @return Number of free blocks available in Msys
+ */
+int r_os_msys_num_free(void);
+#define os_msys_num_free r_os_msys_num_free
+
+
+/**
+ * Initialize a pool of mbufs.
+ *
+ * @param omp The mbuf pool to initialize
+ * @param mp The memory pool that will hold this mbuf pool
+ * @param buf_len The length of the buffer itself.
+ * @param nbufs The number of buffers in the pool
+ *
+ * @return 0 on success, error code on failure.
+ */
+int r_os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
+ uint16_t, uint16_t);
+#define os_mbuf_pool_init r_os_mbuf_pool_init
+/**
+ * Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized
+ * prior to being returned.
+ *
+ * @param omp The mbuf pool to return the packet from
+ * @param leadingspace The amount of leadingspace to put before the data
+ * section by default.
+ *
+ * @return An initialized mbuf on success, and NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
+#define os_mbuf_get r_os_mbuf_get
+/**
+ * Allocate a new packet header mbuf out of the os_mbuf_pool.
+ *
+ * @param omp The mbuf pool to allocate out of
+ * @param user_pkthdr_len The packet header length to reserve for the caller.
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
+ uint8_t pkthdr_len);
+#define os_mbuf_get_pkthdr r_os_mbuf_get_pkthdr
+/**
+ * Duplicate a chain of mbufs. Return the start of the duplicated chain.
+ *
+ * @param omp The mbuf pool to duplicate out of
+ * @param om The mbuf chain to duplicate
+ *
+ * @return A pointer to the new chain of mbufs
+ */
+struct os_mbuf *r_os_mbuf_dup(struct os_mbuf *m);
+#define os_mbuf_dup r_os_mbuf_dup
+/**
+ * Locates the specified absolute offset within an mbuf chain. The offset
+ * can be one past than the total length of the chain, but no greater.
+ *
+ * @param om The start of the mbuf chain to seek within.
+ * @param off The absolute address to find.
+ * @param out_off On success, this points to the relative offset
+ * within the returned mbuf.
+ *
+ * @return The mbuf containing the specified offset on
+ * success.
+ * NULL if the specified offset is out of bounds.
+ */
+struct os_mbuf *r_os_mbuf_off(const struct os_mbuf *om, int off,
+ uint16_t *out_off);
+#define os_mbuf_off r_os_mbuf_off
+
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer.
+ *
+ * @param m The mbuf chain to copy from
+ * @param off The offset into the mbuf chain to begin copying from
+ * @param len The length of the data to copy
+ * @param dst The destination buffer to copy into
+ *
+ * @return 0 on success;
+ * -1 if the mbuf does not contain enough data.
+ */
+int r_os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
+#define os_mbuf_copydata r_os_mbuf_copydata
+
+
+/**
+ * @brief Calculates the length of an mbuf chain.
+ *
+ * Calculates the length of an mbuf chain. If the mbuf contains a packet
+ * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to
+ * this function.
+ *
+ * @param om The mbuf to measure.
+ *
+ * @return The length, in bytes, of the provided mbuf
+ * chain.
+ */
+uint16_t r_os_mbuf_len(const struct os_mbuf *om);
+#define os_mbuf_len r_os_mbuf_len
+
+
+/**
+ * Append data onto a mbuf
+ *
+ * @param om The mbuf to append the data onto
+ * @param data The data to append onto the mbuf
+ * @param len The length of the data to append
+ *
+ * @return 0 on success, and an error code on failure
+ */
+int r_os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
+#define os_mbuf_append r_os_mbuf_append
+
+
+/**
+ * Reads data from one mbuf and appends it to another. On error, the specified
+ * data range may be partially appended. Neither mbuf is required to contain
+ * an mbuf packet header.
+ *
+ * @param dst The mbuf to append to.
+ * @param src The mbuf to copy data from.
+ * @param src_off The absolute offset within the source mbuf
+ * chain to read from.
+ * @param len The number of bytes to append.
+ *
+ * @return 0 on success;
+ * OS_EINVAL if the specified range extends beyond
+ * the end of the source mbuf chain.
+ */
+int r_os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+ uint16_t src_off, uint16_t len);
+#define os_mbuf_appendfrom r_os_mbuf_appendfrom
+/**
+ * Release a mbuf back to the pool
+ *
+ * @param omp The Mbuf pool to release back to
+ * @param om The Mbuf to release back to the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int os_mbuf_free(struct os_mbuf *mb);
+#define os_mbuf_free r_os_mbuf_free
+
+
+/**
+ * Free a chain of mbufs
+ *
+ * @param omp The mbuf pool to free the chain of mbufs into
+ * @param om The starting mbuf of the chain to free back into the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int r_os_mbuf_free_chain(struct os_mbuf *om);
+#define os_mbuf_free_chain r_os_mbuf_free_chain
+
+
+/**
+ * Adjust the length of a mbuf, trimming either from the head or the tail
+ * of the mbuf.
+ *
+ * @param mp The mbuf chain to adjust
+ * @param req_len The length to trim from the mbuf. If positive, trims
+ * from the head of the mbuf, if negative, trims from the
+ * tail of the mbuf.
+ */
+void r_os_mbuf_adj(struct os_mbuf *mp, int req_len);
+#define os_mbuf_adj r_os_mbuf_adj
+
+
+
+/**
+ * Performs a memory compare of the specified region of an mbuf chain against a
+ * flat buffer.
+ *
+ * @param om The start of the mbuf chain to compare.
+ * @param off The offset within the mbuf chain to start the
+ * comparison.
+ * @param data The flat buffer to compare.
+ * @param len The length of the flat buffer.
+ *
+ * @return 0 if both memory regions are identical;
+ * A memcmp return code if there is a mismatch;
+ * INT_MAX if the mbuf is too short.
+ */
+int r_os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
+#define os_mbuf_cmpf r_os_mbuf_cmpf
+
+
+/**
+ * Compares the contents of two mbuf chains. The ranges of the two chains to
+ * be compared are specified via the two offset parameters and the len
+ * parameter. Neither mbuf chain is required to contain a packet header.
+ *
+ * @param om1 The first mbuf chain to compare.
+ * @param offset1 The absolute offset within om1 at which to
+ * start the comparison.
+ * @param om2 The second mbuf chain to compare.
+ * @param offset2 The absolute offset within om2 at which to
+ * start the comparison.
+ * @param len The number of bytes to compare.
+ *
+ * @return 0 if both mbuf segments are identical;
+ * A memcmp() return code if the segment contents
+ * differ;
+ * INT_MAX if a specified range extends beyond the
+ * end of its corresponding mbuf chain.
+ */
+int r_os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+ const struct os_mbuf *om2, uint16_t offset2,
+ uint16_t len);
+#define os_mbuf_cmpm r_os_mbuf_cmpm
+/**
+ * Increases the length of an mbuf chain by adding data to the front. If there
+ * is insufficient room in the leading mbuf, additional mbufs are allocated and
+ * prepended as necessary. If this function fails to allocate an mbuf, the
+ * entire chain is freed.
+ *
+ * The specified mbuf chain does not need to contain a packet header.
+ *
+ * @param omp The mbuf pool to allocate from.
+ * @param om The head of the mbuf chain.
+ * @param len The number of bytes to prepend.
+ *
+ * @return The new head of the chain on success;
+ * NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_prepend(struct os_mbuf *om, int len);
+#define os_mbuf_prepend r_os_mbuf_prepend
+/**
+ * Prepends a chunk of empty data to the specified mbuf chain and ensures the
+ * chunk is contiguous. If either operation fails, the specified mbuf chain is
+ * freed and NULL is returned.
+ *
+ * @param om The mbuf chain to prepend to.
+ * @param len The number of bytes to prepend and pullup.
+ *
+ * @return The modified mbuf on success;
+ * NULL on failure (and the mbuf chain is freed).
+ */
+struct os_mbuf *r_os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_prepend_pullup r_os_mbuf_prepend_pullup
+/**
+ * Copies the contents of a flat buffer into an mbuf chain, starting at the
+ * specified destination offset. If the mbuf is too small for the source data,
+ * it is extended as necessary. If the destination mbuf contains a packet
+ * header, the header length is updated.
+ *
+ * @param omp The mbuf pool to allocate from.
+ * @param om The mbuf chain to copy into.
+ * @param off The offset within the chain to copy to.
+ * @param src The source buffer to copy from.
+ * @param len The number of bytes to copy.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int r_os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
+#define os_mbuf_copyinto r_os_mbuf_copyinto
+
+
+/**
+ * Attaches a second mbuf chain onto the end of the first. If the first chain
+ * contains a packet header, the header's length is updated. If the second
+ * chain has a packet header, its header is cleared.
+ *
+ * @param first The mbuf chain being attached to.
+ * @param second The mbuf chain that gets attached.
+ */
+void r_os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
+#define os_mbuf_concat r_os_mbuf_concat
+
+
+
+/**
+ * Increases the length of an mbuf chain by the specified amount. If there is
+ * not sufficient room in the last buffer, a new buffer is allocated and
+ * appended to the chain. It is an error to request more data than can fit in
+ * a single buffer.
+ *
+ * @param omp
+ * @param om The head of the chain to extend.
+ * @param len The number of bytes to extend by.
+ *
+ * @return A pointer to the new data on success;
+ * NULL on failure.
+ */
+void *r_os_mbuf_extend(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_extend r_os_mbuf_extend
+/**
+ * Rearrange a mbuf chain so that len bytes are contiguous,
+ * and in the data area of an mbuf (so that OS_MBUF_DATA() will
+ * work on a structure of size len.) Returns the resulting
+ * mbuf chain on success, free's it and returns NULL on failure.
+ *
+ * If there is room, it will add up to "max_protohdr - len"
+ * extra bytes to the contiguous region, in an attempt to avoid being
+ * called next time.
+ *
+ * @param omp The mbuf pool to take the mbufs out of
+ * @param om The mbuf chain to make contiguous
+ * @param len The number of bytes in the chain to make contiguous
+ *
+ * @return The contiguous mbuf chain on success, NULL on failure.
+ */
+struct os_mbuf *r_os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
+#define os_mbuf_pullup r_os_mbuf_pullup
+
+/**
+ * Removes and frees empty mbufs from the front of a chain. If the chain
+ * contains a packet header, it is preserved.
+ *
+ * @param om The mbuf chain to trim.
+ *
+ * @return The head of the trimmed mbuf chain.
+ */
+struct os_mbuf *r_os_mbuf_trim_front(struct os_mbuf *om);
+#define os_mbuf_trim_front r_os_mbuf_trim_front
+/**
+ * Increases the length of an mbuf chain by inserting a gap at the specified
+ * offset. The contents of the gap are indeterminate. If the mbuf chain
+ * contains a packet header, its total length is increased accordingly.
+ *
+ * This function never frees the provided mbuf chain.
+ *
+ * @param om The mbuf chain to widen.
+ * @param off The offset at which to insert the gap.
+ * @param len The size of the gap to insert.
+ *
+ * @return 0 on success; SYS_[...] error code on failure.
+ */
+int r_os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len);
+#define os_mbuf_widen r_os_mbuf_widen
+
+
+
+/**
+ * Creates a single chained mbuf from m1 and m2 utilizing all
+ * the available buffer space in all mbufs in the resulting
+ * chain. In other words, ensures there is no leading space in
+ * any mbuf in the resulting chain and trailing space only in
+ * the last mbuf in the chain. Mbufs from either chain may be
+ * freed if not needed. No mbufs are allocated. Note that mbufs
+ * from m2 are added to the end of m1. If m1 has a packet
+ * header, it is retained and length updated. If m2 has a packet
+ * header it is discarded. If m1 is NULL, NULL is returned and
+ * m2 is left untouched.
+ *
+ * @param m1 Pointer to first mbuf chain to pack
+ * @param m2 Pointer to second mbuf chain to pack
+ *
+ * @return struct os_mbuf* Pointer to resulting mbuf chain
+ */
+struct os_mbuf *r_os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2);
+#define os_mbuf_pack_chains r_os_mbuf_pack_chains
+
+#else
/**
* Initializes an mqueue. An mqueue is a queue of mbufs that ties to a
* particular task's event queue. Mqueues form a helper API around a common
@@ -347,7 +808,7 @@ int os_msys_num_free(void);
* @return 0 on success, error code on failure.
*/
int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
- uint16_t, uint16_t);
+ uint16_t, uint16_t);
/**
* Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized
@@ -370,7 +831,7 @@ struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
* @return A freshly allocated mbuf on success, NULL on failure.
*/
struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
- uint8_t pkthdr_len);
+ uint8_t pkthdr_len);
/**
* Duplicate a chain of mbufs. Return the start of the duplicated chain.
@@ -413,6 +874,20 @@ struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
*/
int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
+/**
+ * @brief Calculates the length of an mbuf chain.
+ *
+ * Calculates the length of an mbuf chain. If the mbuf contains a packet
+ * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to
+ * this function.
+ *
+ * @param om The mbuf to measure.
+ *
+ * @return The length, in bytes, of the provided mbuf
+ * chain.
+ */
+uint16_t os_mbuf_len(const struct os_mbuf *om);
+
/**
* Append data onto a mbuf
*
@@ -614,6 +1089,22 @@ struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
*/
struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
+/**
+ * Increases the length of an mbuf chain by inserting a gap at the specified
+ * offset. The contents of the gap are indeterminate. If the mbuf chain
+ * contains a packet header, its total length is increased accordingly.
+ *
+ * This function never frees the provided mbuf chain.
+ *
+ * @param om The mbuf chain to widen.
+ * @param off The offset at which to insert the gap.
+ * @param len The size of the gap to insert.
+ *
+ * @return 0 on success; SYS_[...] error code on failure.
+ */
+int os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len);
+
+
/**
* Creates a single chained mbuf from m1 and m2 utilizing all
* the available buffer space in all mbufs in the resulting
@@ -633,6 +1124,7 @@ struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
*/
struct os_mbuf *os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2);
+#endif
#ifdef __cplusplus
}
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h
index a01d34ded..4dc76e91f 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_mempool.h
@@ -66,7 +66,7 @@ struct os_mempool {
/** Bitmap of OS_MEMPOOL_F_[...] values. */
uint8_t mp_flags;
/** Address of memory buffer used by pool */
- uintptr_t mp_membuf_addr;
+ uint32_t mp_membuf_addr;
STAILQ_ENTRY(os_mempool) mp_list;
SLIST_HEAD(,os_memblock);
/** Name for memory block */
@@ -140,25 +140,153 @@ struct os_mempool_info {
* when at the last memory pool.
*/
struct os_mempool *os_mempool_info_get_next(struct os_mempool *,
- struct os_mempool_info *);
+ struct os_mempool_info *);
/*
* To calculate size of the memory buffer needed for the pool. NOTE: This size
* is NOT in bytes! The size is the number of os_membuf_t elements required for
* the memory pool.
*/
-#if (OS_CFG_ALIGNMENT == OS_CFG_ALIGN_4)
-#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + 3) / 4) * (n))
-typedef uint32_t os_membuf_t;
+#if MYNEWT_VAL(OS_MEMPOOL_GUARD)
+/*
+ * Leave extra 4 bytes of guard area at the end.
+ */
+#define OS_MEMPOOL_BLOCK_SZ(sz) ((sz) + sizeof(os_membuf_t))
#else
-#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + 7) / 8) * (n))
-typedef uint64_t os_membuf_t;
+#define OS_MEMPOOL_BLOCK_SZ(sz) (sz)
#endif
+#if (OS_ALIGNMENT == 4)
+typedef uint32_t os_membuf_t;
+#elif (OS_ALIGNMENT == 8)
+typedef uint64_t os_membuf_t;
+#elif (OS_ALIGNMENT == 16)
+typedef __uint128_t os_membuf_t;
+#else
+#error "Unhandled `OS_ALIGNMENT` for `os_membuf_t`"
+#endif /* OS_ALIGNMENT == * */
+#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n))
/** Calculates the number of bytes required to initialize a memory pool. */
#define OS_MEMPOOL_BYTES(n,blksize) \
(sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
+#if SOC_ESP_NIMBLE_CONTROLLER
+/**
+ * Initialize a memory pool.
+ *
+ * @param mp Pointer to a pointer to a mempool
+ * @param blocks The number of blocks in the pool
+ * @param blocks_size The size of the block, in bytes.
+ * @param membuf Pointer to memory to contain blocks.
+ * @param name Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks,
+ uint32_t block_size, void *membuf, const char *name);
+#define os_mempool_init r_os_mempool_init
+/**
+ * Initializes an extended memory pool. Extended attributes (e.g., callbacks)
+ * are not specified when this function is called; they are assigned manually
+ * after initialization.
+ *
+ * @param mpe The extended memory pool to initialize.
+ * @param blocks The number of blocks in the pool.
+ * @param block_size The size of each block, in bytes.
+ * @param membuf Pointer to memory to contain blocks.
+ * @param name Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
+ uint32_t block_size, void *membuf, const char *name);
+#define os_mempool_ext_init r_os_mempool_ext_init
+/**
+ * Removes the specified mempool from the list of initialized mempools.
+ *
+ * @param mp The mempool to unregister.
+ *
+ * @return 0 on success;
+ * OS_INVALID_PARM if the mempool is not
+ * registered.
+ */
+os_error_t r_os_mempool_unregister(struct os_mempool *mp);
+#define os_mempool_unregister r_os_mempool_unregister
+
+
+/**
+ * Clears a memory pool.
+ *
+ * @param mp The mempool to clear.
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_mempool_clear(struct os_mempool *mp);
+#define os_mempool_clear r_os_mempool_clear
+
+
+/**
+ * Performs an integrity check of the specified mempool. This function
+ * attempts to detect memory corruption in the specified memory pool.
+ *
+ * @param mp The mempool to check.
+ *
+ * @return true if the memory pool passes the integrity
+ * check;
+ * false if the memory pool is corrupt.
+ */
+bool r_os_mempool_is_sane(const struct os_mempool *mp);
+#define os_mempool_is_sane r_os_mempool_is_sane
+
+
+/**
+ * Checks if a memory block was allocated from the specified mempool.
+ *
+ * @param mp The mempool to check as parent.
+ * @param block_addr The memory block to check as child.
+ *
+ * @return 0 if the block does not belong to the mempool;
+ * 1 if the block does belong to the mempool.
+ */
+int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr);
+#define os_memblock_from r_os_memblock_from
+
+
+/**
+ * Get a memory block from a memory pool
+ *
+ * @param mp Pointer to the memory pool
+ *
+ * @return void* Pointer to block if available; NULL otherwise
+ */
+void *r_os_memblock_get(struct os_mempool *mp);
+#define os_memblock_get r_os_memblock_get
+/**
+ * Puts the memory block back into the pool, ignoring the put callback, if any.
+ * This function should only be called from a put callback to free a block
+ * without causing infinite recursion.
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
+#define os_memblock_put_from_cb r_os_memblock_put_from_cb
+
+
+/**
+ * Puts the memory block back into the pool
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr);
+#define os_memblock_put r_os_memblock_put
+
+#else
/**
* Initialize a memory pool.
*
@@ -189,6 +317,17 @@ os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks,
os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
+/**
+ * Removes the specified mempool from the list of initialized mempools.
+ *
+ * @param mp The mempool to unregister.
+ *
+ * @return 0 on success;
+ * OS_INVALID_PARM if the mempool is not
+ * registered.
+ */
+os_error_t os_mempool_unregister(struct os_mempool *mp);
+
/**
* Clears a memory pool.
*
@@ -260,6 +399,7 @@ os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
* @return os_error_t
*/
os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr);
+#endif
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_trace_api.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_trace_api.h
index 4f1aa03cf..70f88b699 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_trace_api.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/os_trace_api.h
@@ -20,7 +20,21 @@
#ifndef OS_TRACE_API_H
#define OS_TRACE_API_H
-#include
+#ifdef __ASSEMBLER__
+
+#define os_trace_isr_enter SEGGER_SYSVIEW_RecordEnterISR
+#define os_trace_isr_exit SEGGER_SYSVIEW_RecordExitISR
+#define os_trace_task_start_exec SEGGER_SYSVIEW_OnTaskStartExec
+
+#else
+
+#include
+#include
+#include "../syscfg/syscfg.h"
+#if MYNEWT_VAL(OS_SYSVIEW)
+#include "sysview/vendor/SEGGER_SYSVIEW.h"
+#endif
+#include "os.h"
#define OS_TRACE_ID_EVENTQ_PUT (40)
#define OS_TRACE_ID_EVENTQ_GET_NO_WAIT (41)
@@ -34,6 +48,163 @@
#define OS_TRACE_ID_SEM_INIT (60)
#define OS_TRACE_ID_SEM_RELEASE (61)
#define OS_TRACE_ID_SEM_PEND (62)
+#define OS_TRACE_ID_CALLOUT_INIT (70)
+#define OS_TRACE_ID_CALLOUT_STOP (71)
+#define OS_TRACE_ID_CALLOUT_RESET (72)
+#define OS_TRACE_ID_CALLOUT_TICK (73)
+#define OS_TRACE_ID_MEMBLOCK_GET (80)
+#define OS_TRACE_ID_MEMBLOCK_PUT_FROM_CB (81)
+#define OS_TRACE_ID_MEMBLOCK_PUT (82)
+#define OS_TRACE_ID_MBUF_GET (90)
+#define OS_TRACE_ID_MBUF_GET_PKTHDR (91)
+#define OS_TRACE_ID_MBUF_FREE (92)
+#define OS_TRACE_ID_MBUF_FREE_CHAIN (93)
+
+#if MYNEWT_VAL(OS_SYSVIEW)
+
+typedef struct SEGGER_SYSVIEW_MODULE_STRUCT os_trace_module_t;
+
+static inline uint32_t
+os_trace_module_register(os_trace_module_t *m, const char *name,
+ uint32_t num_events, void (* send_desc_func)(void))
+{
+ char *desc = "M=???";
+
+ asprintf(&desc, "M=%s", name);
+
+ memset(m, 0, sizeof(*m));
+ m->sModule = desc;
+ m->NumEvents = num_events;
+ m->pfSendModuleDesc = send_desc_func;
+
+ SEGGER_SYSVIEW_RegisterModule(m);
+
+ return m->EventOffset;
+}
+
+static inline void
+os_trace_module_desc(const os_trace_module_t *m, const char *desc)
+{
+ SEGGER_SYSVIEW_RecordModuleDescription(m, desc);
+}
+
+static inline void
+os_trace_isr_enter(void)
+{
+ SEGGER_SYSVIEW_RecordEnterISR();
+}
+
+static inline void
+os_trace_isr_exit(void)
+{
+ SEGGER_SYSVIEW_RecordExitISR();
+}
+
+static inline void
+os_trace_task_info(const struct ble_npl_task *t)
+{
+ SEGGER_SYSVIEW_TASKINFO ti;
+
+ ti.TaskID = (uint32_t)t;
+ ti.sName = t->t_name;
+ ti.Prio = t->t_prio;
+ ti.StackSize = t->t_stacksize * sizeof(os_stack_t);
+ ti.StackBase = (uint32_t)&t->t_stackbottom + ti.StackSize;
+
+ SEGGER_SYSVIEW_SendTaskInfo(&ti);
+}
+
+static inline void
+os_trace_task_create(const struct ble_npl_task *t)
+{
+ SEGGER_SYSVIEW_OnTaskCreate((uint32_t)t);
+}
+
+static inline void
+os_trace_task_start_exec(const struct ble_npl_task *t)
+{
+ SEGGER_SYSVIEW_OnTaskStartExec((uint32_t)t);
+}
+
+static inline void
+os_trace_task_stop_exec(void)
+{
+ SEGGER_SYSVIEW_OnTaskStopExec();
+}
+
+static inline void
+os_trace_task_start_ready(const struct ble_npl_task *t)
+{
+ SEGGER_SYSVIEW_OnTaskStartReady((uint32_t)t);
+}
+
+static inline void
+os_trace_task_stop_ready(const struct ble_npl_task *t, unsigned reason)
+{
+ SEGGER_SYSVIEW_OnTaskStopReady((uint32_t)t, reason);
+}
+
+static inline void
+os_trace_idle(void)
+{
+ SEGGER_SYSVIEW_OnIdle();
+}
+
+static inline void
+os_trace_user_start(unsigned id)
+{
+ SEGGER_SYSVIEW_OnUserStart(id);
+}
+
+static inline void
+os_trace_user_stop(unsigned id)
+{
+ SEGGER_SYSVIEW_OnUserStop(id);
+}
+
+#endif /* MYNEWT_VAL(OS_SYSVIEW) */
+
+#if MYNEWT_VAL(OS_SYSVIEW) && !defined(OS_TRACE_DISABLE_FILE_API)
+
+static inline void
+os_trace_api_void(unsigned id)
+{
+ SEGGER_SYSVIEW_RecordVoid(id);
+}
+
+static inline void
+os_trace_api_u32(unsigned id, uint32_t p0)
+{
+ SEGGER_SYSVIEW_RecordU32(id, p0);
+}
+
+static inline void
+os_trace_api_u32x2(unsigned id, uint32_t p0, uint32_t p1)
+{
+ SEGGER_SYSVIEW_RecordU32x2(id, p0, p1);
+}
+
+static inline void
+os_trace_api_u32x3(unsigned id, uint32_t p0, uint32_t p1, uint32_t p2)
+{
+ SEGGER_SYSVIEW_RecordU32x3(id, p0, p1, p2);
+}
+
+static inline void
+os_trace_api_ret(unsigned id)
+{
+ SEGGER_SYSVIEW_RecordEndCall(id);
+}
+
+static inline void
+os_trace_api_ret_u32(unsigned id, uint32_t ret)
+{
+ SEGGER_SYSVIEW_RecordEndCallU32(id, ret);
+}
+
+#endif /* MYNEWT_VAL(OS_SYSVIEW) && !defined(OS_TRACE_DISABLE_FILE_API) */
+
+#if !MYNEWT_VAL(OS_SYSVIEW)
static inline void
os_trace_isr_enter(void)
@@ -45,11 +216,30 @@ os_trace_isr_exit(void)
{
}
+static inline void
+os_trace_task_stop_exec(void)
+{
+}
+
static inline void
os_trace_idle(void)
{
}
+static inline void
+os_trace_user_start(unsigned id)
+{
+}
+
+static inline void
+os_trace_user_stop(unsigned id)
+{
+}
+
+#endif /* !MYNEWT_VAL(OS_SYSVIEW) */
+
+#if !MYNEWT_VAL(OS_SYSVIEW) || defined(OS_TRACE_DISABLE_FILE_API)
+
static inline void
os_trace_api_void(unsigned id)
{
@@ -80,4 +270,8 @@ os_trace_api_ret_u32(unsigned id, uint32_t return_value)
{
}
-#endif
+#endif /* !MYNEWT_VAL(OS_SYSVIEW) || defined(OS_TRACE_DISABLE_FILE_API) */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* OS_TRACE_API_H */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/queue.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/queue.h
index f20433ca5..c184a394e 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/queue.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/os/queue.h
@@ -112,7 +112,6 @@ extern "C" {
*
*/
-
/*
* Circular queue declarations.
*/
@@ -216,4 +215,4 @@ struct { \
}
#endif
-#endif /* !_QUEUE_H_ */
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h
index 3cb2b14ba..e97213127 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/syscfg/syscfg.h
@@ -1,14 +1,17 @@
/**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
*/
-#ifndef H_MYNEWT_SYSCFG_
-#define H_MYNEWT_SYSCFG_
+#ifndef H_SYSCFG_
+#define H_SYSCFG_
#ifdef ESP_PLATFORM
-#include "nimble/esp_port/port/include/esp_nimble_cfg.h"
+# include "nimble/esp_port/port/include/esp_nimble_cfg.h"
#else
-#include "ext_nimble_config.h"
+# include "ext_nimble_config.h"
+# ifndef CONFIG_BT_NIMBLE_ENABLED
+# define CONFIG_BT_NIMBLE_ENABLED 1
+# endif
#endif
#if 0
@@ -23,8 +26,6 @@
#define MYNEWT_VAL(_name) MYNEWT_VAL_ ## _name
#define MYNEWT_VAL_CHOICE(_name, _val) MYNEWT_VAL_ ## _name ## __ ## _val
-
-
/*** @apache-mynewt-core/crypto/tinycrypt */
#ifndef MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE
#define MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE (200)
@@ -375,6 +376,14 @@
#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
#endif
+#ifndef MYNEWT_VAL_BLE_ISO
+#define MYNEWT_VAL_BLE_ISO (0)
+#endif
+
+#ifndef MYNEWT_VAL_BLE_ISO_TEST
+#define MYNEWT_VAL_BLE_ISO_TEST (0)
+#endif
+
#ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS
#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (4)
#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysflash/sysflash.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysflash/sysflash.h
index 413cb2679..ab1341b25 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysflash/sysflash.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/include/sysflash/sysflash.h
@@ -1,5 +1,5 @@
/**
- * This file was generated by Apache newt version: 1.8.0-dev
+ * This file was generated by Apache newt version: 1.9.0-dev
*/
#ifndef H_MYNEWT_SYSFLASH_
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c
index c1b181dfe..f85639248 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/endian.c
@@ -145,9 +145,9 @@ put_be24(void *buf, uint32_t x)
uint8_t *u8ptr;
u8ptr = buf;
- u8ptr[0] = (uint8_t)(x >> 24);
- u8ptr[1] = (uint8_t)(x >> 16);
- u8ptr[2] = (uint8_t)(x >> 8);
+ u8ptr[0] = (uint8_t)(x >> 16);
+ u8ptr[1] = (uint8_t)(x >> 8);
+ u8ptr[2] = (uint8_t)x;
}
void
@@ -198,9 +198,9 @@ get_be24(const void *buf)
uint32_t x;
u8ptr = buf;
- x = (uint32_t)u8ptr[0] << 24;
- x |= (uint32_t)u8ptr[1] << 16;
- x |= (uint32_t)u8ptr[2] << 8;
+ x = (uint32_t)u8ptr[0] << 16;
+ x |= (uint32_t)u8ptr[1] << 8;
+ x |= (uint32_t)u8ptr[2];
return x;
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c
index 93dfc8df3..611a5fe2d 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_timer.c
@@ -23,8 +23,9 @@
#include
#include
#include "../include/os/os.h"
-#include "nrf.h"
+#include "nrfx.h"
#include "../include/hal/hal_timer.h"
+#include "../include/os/os_trace_api.h"
/* IRQ prototype */
typedef void (*hal_timer_irq_handler_t)(void);
@@ -75,34 +76,34 @@ struct nrf52_hal_timer nrf52_hal_timer5;
static const struct nrf52_hal_timer *nrf52_hal_timers[NRF52_HAL_TIMER_MAX] = {
#if MYNEWT_VAL(TIMER_0)
- &nrf52_hal_timer0,
+ &nrf52_hal_timer0,
#else
- NULL,
+ NULL,
#endif
#if MYNEWT_VAL(TIMER_1)
- &nrf52_hal_timer1,
+ &nrf52_hal_timer1,
#else
- NULL,
+ NULL,
#endif
#if MYNEWT_VAL(TIMER_2)
- &nrf52_hal_timer2,
+ &nrf52_hal_timer2,
#else
- NULL,
+ NULL,
#endif
#if MYNEWT_VAL(TIMER_3)
- &nrf52_hal_timer3,
+ &nrf52_hal_timer3,
#else
- NULL,
+ NULL,
#endif
#if MYNEWT_VAL(TIMER_4)
- &nrf52_hal_timer4,
+ &nrf52_hal_timer4,
#else
- NULL,
+ NULL,
#endif
#if MYNEWT_VAL(TIMER_5)
- &nrf52_hal_timer5
+ &nrf52_hal_timer5
#else
- NULL
+ NULL
#endif
};
@@ -164,14 +165,26 @@ nrf_timer_set_ocmp(struct nrf52_hal_timer *bsptimer, uint32_t expiry)
delta_t = (int32_t)(expiry - temp);
/*
- * The nrf documentation states that you must set the output
- * compare to 2 greater than the counter to guarantee an interrupt.
- * Since the counter can tick once while we check, we make sure
- * it is greater than 2.
+ * The nRF52xxx documentation states that COMPARE event is guaranteed
+ * only if value written to CC register is at least 2 greater than the
+ * current counter value. We also need to account for possible extra
+ * tick during calculations so effectively any delta less than 3 needs
+ * to be handled differently. TICK event is used to have interrupt on
+ * each subsequent tick so we won't miss any and in case we detected
+ * mentioned extra tick during calculations, interrupt is triggered
+ * immediately. Delta 0 or less means we should always fire immediately.
*/
- if (delta_t < 3) {
+ if (delta_t < 1) {
+ rtctimer->INTENCLR = RTC_INTENCLR_TICK_Msk;
NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
- } else {
+ } else if (delta_t < 3) {
+ rtctimer->INTENSET = RTC_INTENSET_TICK_Msk;
+ if (rtctimer->COUNTER != cntr) {
+ NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+ }
+ } else {
+ rtctimer->INTENCLR = RTC_INTENCLR_TICK_Msk;
+
if (delta_t < (1UL << 24)) {
rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry & 0x00ffffff;
} else {
@@ -213,6 +226,7 @@ static void
nrf_rtc_disable_ocmp(NRF_RTC_Type *rtctimer)
{
rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
+ rtctimer->INTENCLR = RTC_INTENCLR_TICK_Msk;
}
static uint32_t
@@ -251,7 +265,6 @@ hal_timer_read_bsptimer(struct nrf52_hal_timer *bsptimer)
static void
hal_timer_chk_queue(struct nrf52_hal_timer *bsptimer)
{
- int32_t delta;
uint32_t tcntr;
os_sr_t sr;
struct hal_timer *timer;
@@ -261,16 +274,10 @@ hal_timer_chk_queue(struct nrf52_hal_timer *bsptimer)
while ((timer = TAILQ_FIRST(&bsptimer->hal_timer_q)) != NULL) {
if (bsptimer->tmr_rtc) {
tcntr = hal_timer_read_bsptimer(bsptimer);
- /*
- * If we are within 3 ticks of RTC, we wont be able to set compare.
- * Thus, we have to service this timer early.
- */
- delta = -3;
} else {
tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
- delta = 0;
}
- if ((int32_t)(tcntr - timer->expiry) >= delta) {
+ if ((int32_t)(tcntr - timer->expiry) >= 0) {
TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
timer->link.tqe_prev = NULL;
timer->cb_func(timer->cb_arg);
@@ -316,7 +323,7 @@ hal_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
uint32_t compare;
NRF_TIMER_Type *hwtimer;
- os_trace_enter_isr();
+ os_trace_isr_enter();
/* Check interrupt source. If set, clear them */
hwtimer = bsptimer->tmr_reg;
@@ -344,7 +351,7 @@ hal_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
compare = hwtimer->EVENTS_COMPARE[NRF_TIMER_CC_INT];
}
- os_trace_exit_isr();
+ os_trace_isr_exit();
}
#endif
@@ -354,13 +361,21 @@ hal_rtc_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
{
uint32_t overflow;
uint32_t compare;
+ uint32_t tick;
NRF_RTC_Type *rtctimer;
+ os_trace_isr_enter();
+
/* Check interrupt source. If set, clear them */
rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT];
if (compare) {
- rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT] = 0;
+ rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT] = 0;
+ }
+
+ tick = rtctimer->EVENTS_TICK;
+ if (tick) {
+ rtctimer->EVENTS_TICK = 0;
}
overflow = rtctimer->EVENTS_OVRFLW;
@@ -385,6 +400,8 @@ hal_rtc_timer_irq_handler(struct nrf52_hal_timer *bsptimer)
/* Recommended by nordic to make sure interrupts are cleared */
compare = rtctimer->EVENTS_COMPARE[NRF_RTC_TIMER_CC_INT];
+
+ os_trace_isr_exit();
}
#endif
@@ -464,17 +481,52 @@ hal_timer_init(int timer_num, void *cfg)
}
switch (timer_num) {
-#if MYNEWT_VAL(TIMER_5)
- case 5:
- irq_num = RTC0_IRQn;
- hwtimer = NRF_RTC0;
- irq_isr = nrf52_timer5_irq_handler;
- bsptimer->tmr_rtc = 1;
+#if MYNEWT_VAL(TIMER_0)
+ case 0:
+ irq_num = TIMER0_IRQn;
+ hwtimer = NRF_TIMER0;
+ irq_isr = nrf52_timer0_irq_handler;
break;
#endif
- default:
- hwtimer = NULL;
+#if MYNEWT_VAL(TIMER_1)
+ case 1:
+ irq_num = TIMER1_IRQn;
+ hwtimer = NRF_TIMER1;
+ irq_isr = nrf52_timer1_irq_handler;
break;
+#endif
+#if MYNEWT_VAL(TIMER_2)
+ case 2:
+ irq_num = TIMER2_IRQn;
+ hwtimer = NRF_TIMER2;
+ irq_isr = nrf52_timer2_irq_handler;
+ break;
+#endif
+#if MYNEWT_VAL(TIMER_3)
+ case 3:
+ irq_num = TIMER3_IRQn;
+ hwtimer = NRF_TIMER3;
+ irq_isr = nrf52_timer3_irq_handler;
+ break;
+#endif
+#if MYNEWT_VAL(TIMER_4)
+ case 4:
+ irq_num = TIMER4_IRQn;
+ hwtimer = NRF_TIMER4;
+ irq_isr = nrf52_timer4_irq_handler;
+ break;
+#endif
+#if MYNEWT_VAL(TIMER_5)
+ case 5:
+ irq_num = RTC0_IRQn;
+ hwtimer = NRF_RTC0;
+ irq_isr = nrf52_timer5_irq_handler;
+ bsptimer->tmr_rtc = 1;
+ break;
+#endif
+ default:
+ hwtimer = NULL;
+ break;
}
if (hwtimer == NULL) {
@@ -496,7 +548,7 @@ hal_timer_init(int timer_num, void *cfg)
return 0;
-err:
+ err:
return rc;
}
@@ -514,8 +566,13 @@ int
hal_timer_config(int timer_num, uint32_t freq_hz)
{
int rc;
+ uint8_t prescaler;
os_sr_t sr;
+ uint32_t div;
+ uint32_t min_delta;
+ uint32_t max_delta;
struct nrf52_hal_timer *bsptimer;
+ NRF_TIMER_Type *hwtimer;
#if MYNEWT_VAL(TIMER_5)
NRF_RTC_Type *rtctimer;
#endif
@@ -540,6 +597,7 @@ hal_timer_config(int timer_num, uint32_t freq_hz)
/* Stop the timer first */
rtctimer->TASKS_STOP = 1;
+ rtctimer->TASKS_CLEAR = 1;
/* Always no prescaler */
rtctimer->PRESCALER = 0;
@@ -559,11 +617,70 @@ hal_timer_config(int timer_num, uint32_t freq_hz)
}
#endif
- assert(0);
+ /* Set timer to desired frequency */
+ div = NRF52_MAX_TIMER_FREQ / freq_hz;
+
+ /*
+ * Largest prescaler is 2^9 and must make sure frequency not too high.
+ * If hwtimer is NULL it means that the timer was not initialized prior
+ * to call.
+ */
+ if (bsptimer->tmr_enabled || (div == 0) || (div > 512) ||
+ (bsptimer->tmr_reg == NULL)) {
+ rc = EINVAL;
+ goto err;
+ }
+
+ if (div == 1) {
+ prescaler = 0;
+ } else {
+ /* Find closest prescaler */
+ for (prescaler = 1; prescaler < 10; ++prescaler) {
+ if (div <= (1 << prescaler)) {
+ min_delta = div - (1 << (prescaler - 1));
+ max_delta = (1 << prescaler) - div;
+ if (min_delta < max_delta) {
+ prescaler -= 1;
+ }
+ break;
+ }
+ }
+ }
+
+ /* Now set the actual frequency */
+ bsptimer->tmr_freq = NRF52_MAX_TIMER_FREQ / (1 << prescaler);
+ bsptimer->tmr_enabled = 1;
+
+ /* disable interrupts */
+ OS_ENTER_CRITICAL(sr);
+
+#if MYNEWT_VAL_CHOICE(MCU_HFCLK_SOURCE, HFXO)
+ /* Make sure HFXO is started */
+ nrf52_clock_hfxo_request();
+#endif
+ hwtimer = bsptimer->tmr_reg;
+
+ /* Stop the timer first */
+ hwtimer->TASKS_STOP = 1;
+ hwtimer->TASKS_CLEAR = 1;
+
+ /* Put the timer in timer mode using 32 bits. */
+ hwtimer->MODE = TIMER_MODE_MODE_Timer;
+ hwtimer->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
+
+ /* Set the pre-scalar */
+ hwtimer->PRESCALER = prescaler;
+
+ /* Start the timer */
+ hwtimer->TASKS_START = 1;
+
+ NVIC_EnableIRQ(bsptimer->tmr_irq_num);
+
+ OS_EXIT_CRITICAL(sr);
return 0;
-err:
+ err:
return rc;
}
@@ -596,13 +713,19 @@ hal_timer_deinit(int timer_num)
} else {
hwtimer = (NRF_TIMER_Type *)bsptimer->tmr_reg;
hwtimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_TIMER_CC_INT);
- hwtimer->TASKS_STOP = 1;
+ hwtimer->TASKS_SHUTDOWN = 1;
}
bsptimer->tmr_enabled = 0;
bsptimer->tmr_reg = NULL;
+
+#if MYNEWT_VAL_CHOICE(MCU_HFCLK_SOURCE, HFXO)
+ if (timer_num != 5) {
+ nrf52_clock_hfxo_release();
+ }
+#endif
OS_EXIT_CRITICAL(sr);
-err:
+ err:
return rc;
}
@@ -627,7 +750,7 @@ hal_timer_get_resolution(int timer_num)
resolution = 1000000000 / bsptimer->tmr_freq;
return resolution;
-err:
+ err:
rc = 0;
return rc;
}
@@ -658,7 +781,7 @@ hal_timer_read(int timer_num)
return tcntr;
/* Assert here since there is no invalid return code */
-err:
+ err:
assert(0);
rc = 0;
return rc;
@@ -712,7 +835,7 @@ hal_timer_set_cb(int timer_num, struct hal_timer *timer, hal_timer_cb cb_func,
rc = 0;
-err:
+ err:
return rc;
}
@@ -795,7 +918,7 @@ hal_timer_stop(struct hal_timer *timer)
return EINVAL;
}
- bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
+ bsptimer = (struct nrf52_hal_timer *)timer->bsp_timer;
OS_ENTER_CRITICAL(sr);
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_uart.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_uart.c
new file mode 100644
index 000000000..408301724
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/hal_uart.c
@@ -0,0 +1,388 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#if CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
+
+#include "freertos/FreeRTOS.h"
+#include "os/os.h"
+#include "hal/hal_uart.h"
+#include "soc/soc.h"
+#include "soc/system_reg.h"
+#include "driver/gpio.h"
+#include "esp_intr_alloc.h"
+#include "riscv/interrupt.h"
+#include "hal/uart_ll.h"
+#include "freertos/semphr.h"
+#include "rom/ets_sys.h"
+
+#include "driver/uart.h"
+#include "driver/periph_ctrl.h"
+
+struct hal_uart {
+ uint8_t u_open:1;
+ uint8_t u_rx_stall:1;
+ uint8_t u_tx_started:1;
+ uint8_t u_tx_buf;
+ hal_uart_rx_char u_rx_func;
+ hal_uart_tx_char u_tx_func;
+ hal_uart_tx_done u_tx_done;
+ SemaphoreHandle_t u_rx_sem;
+ void *u_func_arg;
+};
+static struct hal_uart uart;
+
+#define UART_FIFO_LEN (128)
+
+uint8_t rxbuffer[256];
+static uint16_t rd_ptr = 0;
+static uint16_t wr_ptr = 0;
+#define BUFFER_MASK (0xff)
+
+static TaskHandle_t hci_uart_task_h;
+
+void uart_init(uint32_t baud);
+void uart0_init(uint32_t baud);
+void uart0_tout_isr(void);
+void uart_tout_isr(void);
+void
+hal_uart_blocking_tx(int port, uint8_t data){
+
+}
+int hal_uart_init(int uart_no, void *cfg)
+{
+ // Uart_Init(uart_no, UART_CLK_FREQ_ROM);
+ return 0;
+}
+
+void hal_uart_start_rx(int uart)
+{
+ ets_printf("rx support???\n");
+}
+int hal_uart_init_cbs(int uart_no, hal_uart_tx_char tx_func,
+ hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg)
+{
+ struct hal_uart *u;
+
+ u = &uart;
+
+ if (u->u_open) {
+ return -1;
+ }
+
+ u->u_rx_func = rx_func;
+ u->u_tx_func = tx_func;
+ u->u_tx_done = tx_done;
+ u->u_func_arg = arg;
+ return 0;
+}
+
+int hal_uart_config(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits,
+ enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
+{
+ struct hal_uart *u;
+ u = &uart;
+
+ if (u->u_open) {
+ return -1;
+ }
+ if (uart_no) {
+ uart_init(speed);
+ } else {
+ uart0_init(speed);
+ }
+ u->u_open = 1;
+ return 0;
+}
+
+static int
+IRAM_ATTR_64MCPU hal_uart_tx_fill_buf(struct hal_uart *u, int uart_no)
+{
+ int data;
+ int i;
+ uart_dev_t *hw = &UART1;
+ if(!uart_no){
+ hw = &UART0;
+ }
+ i = 0;
+ while(hw->status.txfifo_cnt < UART_FIFO_LEN){
+ data = u->u_tx_func(u->u_func_arg);
+ if (data >= 0) {
+ hw->ahb_fifo.rw_byte = data;
+ i++;
+ }else{
+ break;
+ }
+ }
+ return i;
+}
+
+void hal_uart_start_tx(int uart_no)
+{
+ struct hal_uart *u;
+ os_sr_t sr;
+ uart_dev_t *hw = &UART1;
+ if(!uart_no){
+ hw = &UART0;
+ }
+ u = &uart;
+ OS_ENTER_CRITICAL(sr);
+ if (u->u_tx_started == 0) {
+ u->u_tx_started = 1;
+ hw->int_ena.tx_done = 1;
+ hal_uart_tx_fill_buf(u,uart_no);
+ }
+ OS_EXIT_CRITICAL(sr);
+}
+
+int hal_uart0_close(int uart_no)
+{
+ struct hal_uart *u;
+ u = &uart;
+ u->u_open = 0;
+
+ REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN);
+ REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST);
+ return 0;
+}
+
+int hal_uart_close(int uart_no)
+{
+ struct hal_uart *u;
+ u = &uart;
+ u->u_open = 0;
+
+ REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART1_CLK_EN);
+ REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART1_RST);
+ return 0;
+}
+
+IRAM_ATTR_64MCPU void uart0_tout_isr(void)
+{
+ struct hal_uart *u;
+ int rc;
+ uint32_t ch;
+ uart_dev_t *hw = &UART0;
+
+ u = &uart;
+ uint32_t uart_int_st = hw->int_st.val;
+ //clear
+ hw->int_clr.val = uart_int_st;
+ if (uart_int_st&UART_TX_DONE_INT_ST_M) {
+ rc = hal_uart_tx_fill_buf(u,0);
+ if (rc == 0) {
+ if (u->u_tx_done) {
+ u->u_tx_done(u->u_func_arg);
+ }
+ u->u_tx_started = 0;
+ hw->int_ena.tx_done = 0;
+ }
+ }
+
+ while (hw->status.rxfifo_cnt) {
+ int rd_len = hw->status.rxfifo_cnt;
+ for (int i = 0; i < rd_len; i++) {
+ ch = hw->ahb_fifo.rw_byte;
+ rc = u->u_rx_func(u->u_func_arg, ch);
+ if (rc < 0) {
+ u->u_rx_stall = 1;
+ }
+ }
+
+ }
+}
+
+IRAM_ATTR_64MCPU void uart_tout_isr(void)
+{
+ struct hal_uart *u;
+ int rc;
+ bool rx_update = false;
+ uart_dev_t *hw = &UART1;
+ u = &uart;
+ uint32_t uart_int_st = hw->int_st.val;
+ //clear
+ hw->int_clr.val = uart_int_st;
+ if (uart_int_st&UART_TX_DONE_INT_ST_M) {
+ rc = hal_uart_tx_fill_buf(u,1);
+ if (rc == 0) {
+ if (u->u_tx_done) {
+ u->u_tx_done(u->u_func_arg);
+ }
+ u->u_tx_started = 0;
+ hw->int_ena.tx_done = 0;
+ }
+ }
+ while (hw->status.rxfifo_cnt) {
+ rxbuffer[(wr_ptr++)&BUFFER_MASK] = hw->ahb_fifo.rw_byte;
+ rx_update = true;
+ }
+ if (rx_update) {
+ xSemaphoreGiveFromISR(u->u_rx_sem, 0);
+ }
+}
+
+void
+IRAM_ATTR uart_rx_task(void *arg){
+ int rc;
+ struct hal_uart *u;
+ u = &uart;
+ while (1) {
+ xSemaphoreTake(u->u_rx_sem, portMAX_DELAY);
+ while (rd_ptr != wr_ptr){
+ rc = u->u_rx_func(u->u_func_arg, rxbuffer[(rd_ptr++)&BUFFER_MASK]);
+ if (rc < 0) {
+ u->u_rx_stall = 1;
+ }
+ }
+ }
+}
+
+
+void uart0_init(uint32_t baud)
+{
+ REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST);
+ REG_CLR_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST);
+ REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN_M);
+ REG_SET_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN_M);
+
+ const int sclk_div = 1;
+ uint32_t sclk_freq = XTAL_CLK_FREQ;
+ uint32_t clk_div = ((sclk_freq) << 4) / baud;
+ uart_dev_t *hw = &UART0;
+ hw->clk_conf.sclk_en = 0;
+ hw->clk_conf.rx_sclk_en = 0;
+ hw->clk_conf.tx_sclk_en = 0;
+
+
+ hw->clk_conf.sclk_en = 1;
+ hw->clk_conf.rx_sclk_en = 1;
+ hw->clk_conf.tx_sclk_en = 1;
+
+ hw->clk_div.div_int = clk_div >> 4;
+ hw->clk_div.div_frag = clk_div & 0xf;
+ hw->clk_conf.sclk_div_num = sclk_div - 1;//7;//255;
+
+ hw->conf0.parity_en = 0;
+
+ hw->conf0.irda_en = 0;
+ hw->rs485_conf.en = 0;
+ hw->rs485_conf.tx_rx_en = 0;
+ hw->rs485_conf.rx_busy_tx_en = 0;
+
+ hw->conf0.bit_num = 3;
+ hw->conf0.stop_bit_num = 1;
+
+ hw->conf1.rxfifo_full_thrhd = 80;
+
+ hw->mem_conf.rx_tout_thrhd = 20;
+ hw->conf1.rx_tout_en = 1;
+
+ hw->conf1.rx_flow_en = 0;
+ hw->conf0.tx_flow_en = 0;
+
+ hw->conf0.rxfifo_rst = 1;
+ hw->conf0.rxfifo_rst = 0;
+ hw->conf0.txfifo_rst = 1;
+ hw->conf0.txfifo_rst = 0;
+ hw->int_ena.rxfifo_full = 1;
+ //enable rx fifo timeout interrupt
+ hw->int_ena.rxfifo_tout = 1;
+
+ uint8_t tx_pin = 21, rx_pin = 20, ISR_ID = ETS_UART0_INUM;
+
+ ets_isr_mask((1<clk_conf.sclk_en = 0;
+ hw->clk_conf.rx_sclk_en = 0;
+ hw->clk_conf.tx_sclk_en = 0;
+
+
+ hw->clk_conf.sclk_en = 1;
+ hw->clk_conf.rx_sclk_en = 1;
+ hw->clk_conf.tx_sclk_en = 1;
+
+ hw->clk_div.div_int = clk_div >> 4;
+ hw->clk_div.div_frag = clk_div & 0xf;
+ hw->clk_conf.sclk_div_num = sclk_div - 1;//7;//255;
+
+ hw->conf0.parity_en = 0;
+
+ hw->conf0.irda_en = 0;
+ hw->rs485_conf.en = 0;
+ hw->rs485_conf.tx_rx_en = 0;
+ hw->rs485_conf.rx_busy_tx_en = 0;
+
+ hw->conf0.bit_num = 3;
+ hw->conf0.stop_bit_num = 1;
+
+ //set full threshold to (2/3)*FIFO_LEN
+ hw->conf1.rxfifo_full_thrhd = 80;
+ hw->mem_conf.rx_tout_thrhd = 20;
+
+ hw->conf1.rx_tout_en = 1;
+
+ hw->conf0.rxfifo_rst = 1;
+ hw->conf0.rxfifo_rst = 0;
+ hw->conf0.txfifo_rst = 1;
+ hw->conf0.txfifo_rst = 0;
+ hw->int_ena.rxfifo_full = 1;
+ //enable rx fifo timeout interrupt
+ hw->int_ena.rxfifo_tout = 1;
+
+ u->u_rx_sem = xSemaphoreCreateBinary();
+
+ uint8_t TX_IO = CONFIG_BT_LE_HCI_UART_TX_PIN, RX_IO = CONFIG_BT_LE_HCI_UART_RX_PIN, ISR_ID = ETS_UART1_INUM;
+ printf("set nimble port tx:%d, rx:%d.\n", TX_IO, RX_IO);
+ printf("set baud:%d.\n", baud);
+ intr_handler_set(ISR_ID, (intr_handler_t)&uart_tout_isr, NULL);
+ intr_matrix_route(ETS_UART1_INTR_SOURCE, ISR_ID);
+ esprv_intc_int_enable(BIT(ISR_ID));
+ esprv_intc_int_set_type(BIT(ISR_ID), INTR_TYPE_LEVEL);
+ esprv_intc_int_set_priority(ISR_ID, 1);
+ // TODO ESP32-C3 IDF-2126, maybe can use interrupt allocation API for all of the above? unsure...
+ esp_intr_reserve(ISR_ID, xPortGetCoreID());
+
+ ESP_ERROR_CHECK(uart_set_pin(1, TX_IO, RX_IO, -1, -1));
+
+ //Enable hw flow control of UART1 for BQB test, which if not enabled, the tester takes quite long time to send a byte to DUT
+
+
+ // uart_ll_set_hw_flow_ctrl(hw, UART_HW_FLOWCTRL_CTS_RTS, 110);
+
+ xTaskCreate(uart_rx_task, "uart_rx", CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE,
+ NULL, 1, &hci_uart_task_h);
+}
+
+#endif // CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c
index bf1ae7ee3..4e41a2b72 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/mem.c
@@ -261,7 +261,7 @@ mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
* frag = mem_split_frag(&rsp, get_mtu(), frag_alloc, NULL);
* if (frag == NULL) {
* os_mbuf_free_chain(rsp);
- * return SYS_ENOMEM;
+ * return OS_ENOMEM;
* }
* send_packet(frag)
* }
@@ -320,3 +320,26 @@ err:
os_mbuf_free_chain(frag);
return NULL;
}
+
+/**
+ * Applies a pullup operation to the supplied mbuf and returns a pointer to the
+ * start of the mbuf data. This is simply a convenience function which allows
+ * the user to access the mbuf data without a cast. On failure, the provided
+ * mbuf is freed.
+ *
+ * @param om The mbuf to pull up.
+ * @param len The size of the object to pull up.
+ *
+ * @return The start of the pulled-up mbuf data.
+ */
+void *
+mem_pullup_obj(struct os_mbuf **om, uint16_t len)
+{
+ *om = os_mbuf_pullup(*om, len);
+ if (*om == NULL) {
+ return NULL;
+ }
+
+ return (*om)->om_data;
+
+}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c
index 98902ce60..d8914f2c5 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/nimble_port.c
@@ -20,69 +20,58 @@
#include
#include "../include/os/os.h"
#include "../include/sysinit/sysinit.h"
-#include "nimble/nimble/host/include/host/ble_hs.h"
-#include "../include/nimble/nimble_port.h"
+#if CONFIG_BT_NIMBLE_ENABLED
+#include "nimble/nimble/host/include/host/ble_hs.h"
+#endif //CONFIG_BT_NIMBLE_ENABLED
+
+#include "../include/nimble/nimble_port.h"
+#include "../../npl/freertos/include/nimble/nimble_port_freertos.h"
#if NIMBLE_CFG_CONTROLLER
#include "nimble/nimble/controller/include/controller/ble_ll.h"
+#include "nimble/nimble/transport/ram/include/transport/ram/ble_hci_ram.h"
#endif
+
#ifdef ESP_PLATFORM
#include "esp_log.h"
+# if defined __has_include
+# if __has_include ("soc/soc_caps.h")
+# include "soc/soc_caps.h"
+# endif
+# endif
#endif
+#if SOC_ESP_NIMBLE_CONTROLLER
+#if CONFIG_SW_COEXIST_ENABLE
+#include "esp_coexist_internal.h"
+#endif
+#endif
+
+#include "nimble/nimble/include/nimble/ble_hci_trans.h"
+
+#ifdef ESP_PLATFORM
+#include "esp_intr_alloc.h"
+#include "esp_bt.h"
+#include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h"
+#endif
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#define NIMBLE_PORT_LOG_TAG "BLE_INIT"
+
+extern void os_msys_init(void);
+
+#if CONFIG_BT_NIMBLE_ENABLED
+
+extern void ble_hs_deinit(void);
+static struct ble_hs_stop_listener stop_listener;
+
+#endif //CONFIG_BT_NIMBLE_ENABLED
+
static struct ble_npl_eventq g_eventq_dflt;
-static struct ble_hs_stop_listener stop_listener;
static struct ble_npl_sem ble_hs_stop_sem;
static struct ble_npl_event ble_hs_ev_stop;
-void
-nimble_port_init(void)
-{
- void os_msys_init(void);
-
-#if NIMBLE_CFG_CONTROLLER
- void ble_hci_ram_init(void);
-#endif
- /* Initialize default event queue */
- ble_npl_eventq_init(&g_eventq_dflt);
-
- os_msys_init();
-
- ble_hs_init();
-
-#if NIMBLE_CFG_CONTROLLER
- hal_timer_init(5, NULL);
-
- os_cputime_init(32768);
-
- ble_ll_init();
-
- ble_hci_ram_init();
-#endif
-}
-
-void
-nimble_port_deinit(void)
-{
- ble_npl_eventq_deinit(&g_eventq_dflt);
-
- ble_hs_deinit();
-}
-
-void
-nimble_port_run(void)
-{
- struct ble_npl_event *ev;
-
- while (1) {
- ev = ble_npl_eventq_get(&g_eventq_dflt, BLE_NPL_TIME_FOREVER);
- ble_npl_event_run(ev);
- if (ev == &ble_hs_ev_stop) {
- break;
- }
- }
-}
-
/**
* Called when the host stop procedure has completed.
*/
@@ -98,12 +87,150 @@ nimble_port_stop_cb(struct ble_npl_event *ev)
ble_npl_sem_release(&ble_hs_stop_sem);
}
+#ifdef ESP_PLATFORM
+/**
+ * @brief esp_nimble_init - Initialize the NimBLE host stack
+ *
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_init(void)
+{
+#if !SOC_ESP_NIMBLE_CONTROLLER
+#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS
+ /* Initialize the function pointers for OS porting */
+ npl_freertos_funcs_init();
+
+ npl_freertos_mempool_init();
+#endif
+#if false //need delete esp_nimble_hci_and_controller_init then can be use
+ if(esp_nimble_hci_init() != ESP_OK) {
+ ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci inits failed\n");
+ return ESP_FAIL;
+ }
+ printf("esp_nimble_hci_init\n");
+#endif
+
+ /* Initialize default event queue */
+ ble_npl_eventq_init(&g_eventq_dflt);
+
+ os_msys_init();
+
+#endif
+
+ /* Initialize the host */
+ ble_hs_init();
+ return ESP_OK;
+}
+
+/**
+ * @brief esp_nimble_deinit - Deinitialize the NimBLE host stack
+ *
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_deinit(void)
+{
+#if false && !SOC_ESP_NIMBLE_CONTROLLER //need delete esp_nimble_hci_and_controller_init then can be use
+ if(esp_nimble_hci_deinit() != ESP_OK) {
+ ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci deinit failed\n");
+ return ESP_FAIL;
+ }
+#endif
+#if !(SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED)
+ ble_npl_eventq_deinit(&g_eventq_dflt);
+#endif
+ ble_hs_deinit();
+ return ESP_OK;
+}
+#endif
+
+void
+nimble_port_init(void)
+{
+#ifdef ESP_PLATFORM
+#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
+ esp_bt_controller_config_t config_opts = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
+ if(esp_bt_controller_init(&config_opts) != ESP_OK) {
+ ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller init failed\n");
+ return;
+ }
+ if(esp_bt_controller_enable(ESP_BT_MODE_BLE) != ESP_OK) {
+ ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller enable failed\n");
+ return;
+ }
+#endif
+
+ if(esp_nimble_init() != 0) {
+ ESP_LOGE(NIMBLE_PORT_LOG_TAG, "nimble host init failed\n");
+ return;
+ }
+#else
+#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS
+ /* Initialize the function pointers for OS porting */
+ npl_freertos_funcs_init();
+
+ npl_freertos_mempool_init();
+#endif
+ /* Initialize default event queue */
+
+ ble_npl_eventq_init(&g_eventq_dflt);
+
+ os_msys_init();
+
+ ble_hs_init();
+
+#if NIMBLE_CFG_CONTROLLER
+ ble_hci_ram_init();
+ hal_timer_init(5, NULL);
+ os_cputime_init(32768);
+ ble_ll_init();
+#endif
+#endif // ESP_PLATFORM
+}
+
+void
+nimble_port_deinit(void)
+{
+#ifdef ESP_PLATFORM
+ if(esp_nimble_deinit() != 0) {
+ ESP_LOGE(NIMBLE_PORT_LOG_TAG, "nimble host deinit failed\n");
+ return;
+ }
+#if CONFIG_BT_CONTROLLER_ENABLED
+ if(esp_bt_controller_disable() != ESP_OK) {
+ ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller disable failed\n");
+ return;
+ }
+ if(esp_bt_controller_deinit() != ESP_OK) {
+ ESP_LOGE(NIMBLE_PORT_LOG_TAG, "controller deinit failed\n");
+ return;
+ }
+#endif
+#else
+ ble_npl_eventq_deinit(&g_eventq_dflt);
+ ble_hs_deinit();
+#endif // ESP_PLATFORM
+}
+
+
int
nimble_port_stop(void)
{
- int rc;
+#ifdef ESP_PLATFORM
+ esp_err_t err = ESP_OK;
+ ble_npl_sem_init(&ble_hs_stop_sem, 0);
+
+ /* Initiate a host stop procedure. */
+ err = ble_hs_stop(&stop_listener, ble_hs_stop_cb,
+ NULL);
+ if (err != 0) {
+ ble_npl_sem_deinit(&ble_hs_stop_sem);
+ return err;
+ }
+#else
+ int rc = 0;
ble_npl_sem_init(&ble_hs_stop_sem, 0);
+
/* Initiate a host stop procedure. */
rc = ble_hs_stop(&stop_listener, ble_hs_stop_cb,
NULL);
@@ -111,12 +238,13 @@ nimble_port_stop(void)
ble_npl_sem_deinit(&ble_hs_stop_sem);
return rc;
}
+#endif // ESP_PLATFORM
/* Wait till the host stop procedure is complete */
ble_npl_sem_pend(&ble_hs_stop_sem, BLE_NPL_TIME_FOREVER);
ble_npl_event_init(&ble_hs_ev_stop, nimble_port_stop_cb,
- NULL);
+ NULL);
ble_npl_eventq_put(&g_eventq_dflt, &ble_hs_ev_stop);
/* Wait till the event is serviced */
@@ -124,16 +252,35 @@ nimble_port_stop(void)
ble_npl_sem_deinit(&ble_hs_stop_sem);
+#ifdef ESP_PLATFORM
+ return ESP_OK;
+#else
return rc;
+#endif
}
+void
+IRAM_ATTR nimble_port_run(void)
+{
+ struct ble_npl_event *ev;
+
+ while (1) {
+ ev = ble_npl_eventq_get(&g_eventq_dflt, BLE_NPL_TIME_FOREVER);
+ ble_npl_event_run(ev);
+ if (ev == &ble_hs_ev_stop) {
+ break;
+ }
+
+ }
+}
struct ble_npl_eventq *
-nimble_port_get_dflt_eventq(void)
+IRAM_ATTR nimble_port_get_dflt_eventq(void)
{
return &g_eventq_dflt;
}
+#ifndef ESP_PLATFORM
#if NIMBLE_CFG_CONTROLLER
void
nimble_port_ll_task_func(void *arg)
@@ -143,3 +290,4 @@ nimble_port_ll_task_func(void *arg)
ble_ll_task(arg);
}
#endif
+#endif
\ No newline at end of file
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c
index 7a17aabc5..73870c4ef 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_cputime_pwr2.c
@@ -79,25 +79,11 @@ os_cputime_ticks_to_usecs(uint32_t ticks)
{
uint32_t usecs;
uint32_t shift;
- uint32_t freq;
- /* Given: `freq = 2^n`, calculate `n`. */
- /* Note: this looks like a lot of work, but gcc can optimize it away since
- * `freq` is known at compile time.
- */
- freq = MYNEWT_VAL(OS_CPUTIME_FREQ);
- shift = 0;
- while (freq != 0) {
- freq >>= 1;
- shift++;
- }
+ shift = __builtin_popcount(MYNEWT_VAL(OS_CPUTIME_FREQ) - 1) - 6;
- if (shift <= 7) {
- return 0;
- }
- shift -= 7;
-
- usecs = ((ticks >> shift) * 15625) + (((ticks & 0x1ff) * 15625) >> shift);
+ usecs = ((ticks >> shift) * 15625) +
+ (((ticks & ~(~0U << shift)) * 15625) >> shift);
return usecs;
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c
index 426bd47d8..a6bf04141 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mbuf.c
@@ -34,6 +34,7 @@
*/
#include "../include/os/os.h"
+#include "../include/os/os_trace_api.h"
#include
#include
@@ -243,13 +244,17 @@ os_mbuf_get(struct os_mbuf_pool *omp, uint16_t leadingspace)
{
struct os_mbuf *om;
+ os_trace_api_u32x2(OS_TRACE_ID_MBUF_GET, (uint32_t)omp,
+ (uint32_t)(uintptr_t)leadingspace);
+
if (leadingspace > omp->omp_databuf_len) {
- goto err;
+ om = NULL;
+ goto done;
}
om = os_memblock_get(omp->omp_pool);
if (!om) {
- goto err;
+ goto done;
}
SLIST_NEXT(om, om_next) = NULL;
@@ -259,9 +264,9 @@ os_mbuf_get(struct os_mbuf_pool *omp, uint16_t leadingspace)
om->om_data = (&om->om_databuf[0] + leadingspace);
om->om_omp = omp;
- return (om);
-err:
- return (NULL);
+done:
+ os_trace_api_ret_u32(OS_TRACE_ID_MBUF_GET, (uint32_t)(uintptr_t)om);
+ return om;
}
struct os_mbuf *
@@ -271,10 +276,14 @@ os_mbuf_get_pkthdr(struct os_mbuf_pool *omp, uint8_t user_pkthdr_len)
struct os_mbuf_pkthdr *pkthdr;
struct os_mbuf *om;
+ os_trace_api_u32x2(OS_TRACE_ID_MBUF_GET_PKTHDR, (uint32_t)(uintptr_t)omp,
+ (uint32_t)user_pkthdr_len);
+
/* User packet header must fit inside mbuf */
pkthdr_len = user_pkthdr_len + sizeof(struct os_mbuf_pkthdr);
if ((pkthdr_len > omp->omp_databuf_len) || (pkthdr_len > 255)) {
- return NULL;
+ om = NULL;
+ goto done;
}
om = os_mbuf_get(omp, 0);
@@ -288,6 +297,8 @@ os_mbuf_get_pkthdr(struct os_mbuf_pool *omp, uint8_t user_pkthdr_len)
STAILQ_NEXT(pkthdr, omp_next) = NULL;
}
+done:
+ os_trace_api_ret_u32(OS_TRACE_ID_MBUF_GET_PKTHDR, (uint32_t)(uintptr_t)om);
return om;
}
@@ -296,15 +307,19 @@ os_mbuf_free(struct os_mbuf *om)
{
int rc;
+ os_trace_api_u32(OS_TRACE_ID_MBUF_FREE, (uint32_t)(uintptr_t)om);
+
if (om->om_omp != NULL) {
rc = os_memblock_put(om->om_omp->omp_pool, om);
if (rc != 0) {
- goto err;
+ goto done;
}
}
- return (0);
-err:
+ rc = 0;
+
+done:
+ os_trace_api_ret_u32(OS_TRACE_ID_MBUF_FREE, (uint32_t)rc);
return (rc);
}
@@ -314,19 +329,23 @@ os_mbuf_free_chain(struct os_mbuf *om)
struct os_mbuf *next;
int rc;
+ os_trace_api_u32(OS_TRACE_ID_MBUF_FREE_CHAIN, (uint32_t)(uintptr_t)om);
+
while (om != NULL) {
next = SLIST_NEXT(om, om_next);
rc = os_mbuf_free(om);
if (rc != 0) {
- goto err;
+ goto done;
}
om = next;
}
- return (0);
-err:
+ rc = 0;
+
+done:
+ os_trace_api_ret_u32(OS_TRACE_ID_MBUF_FREE_CHAIN, (uint32_t)rc);
return (rc);
}
@@ -348,6 +367,22 @@ _os_mbuf_copypkthdr(struct os_mbuf *new_buf, struct os_mbuf *old_buf)
new_buf->om_data = new_buf->om_databuf + old_buf->om_pkthdr_len;
}
+uint16_t
+os_mbuf_len(const struct os_mbuf *om)
+{
+ uint16_t len;
+
+ len = 0;
+ while (om != NULL) {
+ len += om->om_len;
+ om = SLIST_NEXT(om, om_next);
+ }
+
+ return len;
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpointer-arith"
int
os_mbuf_append(struct os_mbuf *om, const void *data, uint16_t len)
{
@@ -385,10 +420,7 @@ os_mbuf_append(struct os_mbuf *om, const void *data, uint16_t len)
memcpy(OS_MBUF_DATA(last, uint8_t *) + last->om_len , data, space);
last->om_len += space;
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpointer-arith"
data += space;
-#pragma GCC diagnostic pop
remainder -= space;
}
@@ -403,10 +435,7 @@ os_mbuf_append(struct os_mbuf *om, const void *data, uint16_t len)
new->om_len = min(omp->omp_databuf_len, remainder);
memcpy(OS_MBUF_DATA(new, void *), data, new->om_len);
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpointer-arith"
data += new->om_len;
-#pragma GCC diagnostic pop
remainder -= new->om_len;
SLIST_NEXT(last, om_next) = new;
last = new;
@@ -427,6 +456,7 @@ os_mbuf_append(struct os_mbuf *om, const void *data, uint16_t len)
err:
return (rc);
}
+#pragma GCC diagnostic pop
int
os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
@@ -636,6 +666,9 @@ os_mbuf_adj(struct os_mbuf *mp, int req_len)
}
}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpointer-arith"
int
os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len)
{
@@ -657,13 +690,10 @@ os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len)
chunk_sz = min(om->om_len - om_off, len - data_off);
if (chunk_sz > 0) {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpointer-arith"
rc = memcmp(om->om_data + om_off, data + data_off, chunk_sz);
if (rc != 0) {
return rc;
}
-#pragma GCC diagnostic pop
}
data_off += chunk_sz;
@@ -679,6 +709,7 @@ os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len)
}
}
}
+#pragma GCC diagnostic pop
int
os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
@@ -1046,6 +1077,93 @@ os_mbuf_trim_front(struct os_mbuf *om)
return om;
}
+int
+os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len)
+{
+ struct os_mbuf *first_new;
+ struct os_mbuf *edge_om;
+ struct os_mbuf *prev;
+ struct os_mbuf *cur;
+ uint16_t rem_len;
+ uint16_t sub_off;
+ int rc;
+
+ /* Locate the mbuf and offset within the chain where the gap will be
+ * inserted.
+ */
+ edge_om = os_mbuf_off(om, off, &sub_off);
+ if (edge_om == NULL) {
+ return OS_EINVAL;
+ }
+
+ /* If the mbuf has sufficient capacity for the gap, just make room within
+ * the mbuf.
+ */
+ if (OS_MBUF_TRAILINGSPACE(edge_om) >= len) {
+ memmove(edge_om->om_data + sub_off + len,
+ edge_om->om_data + sub_off,
+ edge_om->om_len - sub_off);
+ edge_om->om_len += len;
+ if (OS_MBUF_IS_PKTHDR(om)) {
+ OS_MBUF_PKTHDR(om)->omp_len += len;
+ }
+ return 0;
+ }
+
+ /* Otherwise, allocate new mbufs until the chain has sufficient capacity
+ * for the gap.
+ */
+ rem_len = len;
+ first_new = NULL;
+ prev = NULL;
+ while (rem_len > 0) {
+ cur = os_mbuf_get(om->om_omp, 0);
+ if (cur == NULL) {
+ /* Free only the mbufs that this function allocated. */
+ os_mbuf_free_chain(first_new);
+ return OS_ENOMEM;
+ }
+
+ /* Remember the start of the chain of new mbufs. */
+ if (first_new == NULL) {
+ first_new = cur;
+ }
+
+ if (rem_len > OS_MBUF_TRAILINGSPACE(cur)) {
+ cur->om_len = OS_MBUF_TRAILINGSPACE(cur);
+ } else {
+ cur->om_len = rem_len;
+ }
+ rem_len -= cur->om_len;
+
+ if (prev != NULL) {
+ SLIST_NEXT(prev, om_next) = cur;
+ }
+ prev = cur;
+ }
+
+ /* Move the misplaced data from the edge mbuf over to the right side of the
+ * gap.
+ */
+ rc = os_mbuf_append(prev, edge_om->om_data + sub_off,
+ edge_om->om_len - sub_off);
+ if (rc != 0) {
+ os_mbuf_free_chain(first_new);
+ return OS_ENOMEM;
+ }
+ edge_om->om_len = sub_off;
+
+ /* Insert the gap into the chain. */
+ SLIST_NEXT(prev, om_next) = SLIST_NEXT(edge_om, om_next);
+ SLIST_NEXT(edge_om, om_next) = first_new;
+
+ if (OS_MBUF_IS_PKTHDR(om)) {
+ OS_MBUF_PKTHDR(om)->omp_len += len;
+ }
+
+ return 0;
+}
+
struct os_mbuf *
os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2)
{
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c
index a26099ef0..297a67017 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_mempool.c
@@ -18,54 +18,111 @@
*/
#include "../include/os/os.h"
+#include "../include/os/os_trace_api.h"
#include
#include
#include
+#include "../include/syscfg/syscfg.h"
+#if !MYNEWT_VAL(OS_SYSVIEW_TRACE_MEMPOOL)
+#define OS_TRACE_DISABLE_FILE_API
+#endif
#define OS_MEM_TRUE_BLOCK_SIZE(bsize) OS_ALIGN(bsize, OS_ALIGNMENT)
+#if MYNEWT_VAL(OS_MEMPOOL_GUARD)
+#define OS_MEMPOOL_TRUE_BLOCK_SIZE(mp) \
+ (((mp)->mp_flags & OS_MEMPOOL_F_EXT) ? \
+ OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size) : \
+ (OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size) + sizeof(os_membuf_t)))
+#else
#define OS_MEMPOOL_TRUE_BLOCK_SIZE(mp) OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size)
+#endif
-STAILQ_HEAD(, os_mempool) g_os_mempool_list =
- STAILQ_HEAD_INITIALIZER(g_os_mempool_list);
+STAILQ_HEAD(, os_mempool) g_os_mempool_list = STAILQ_HEAD_INITIALIZER(g_os_mempool_list);
#if MYNEWT_VAL(OS_MEMPOOL_POISON)
static uint32_t os_mem_poison = 0xde7ec7ed;
-static void
-os_mempool_poison(void *start, int sz)
-{
- int i;
- char *p = start;
+static_assert(sizeof(struct os_memblock) % 4 == 0, "sizeof(struct os_memblock) shall be aligned to 4");
+static_assert(sizeof(os_mem_poison) == 4, "sizeof(os_mem_poison) shall be 4");
- for (i = sizeof(struct os_memblock); i < sz;
- i = i + sizeof(os_mem_poison)) {
- memcpy(p + i, &os_mem_poison, min(sizeof(os_mem_poison), sz - i));
+static void
+os_mempool_poison(const struct os_mempool *mp, void *start)
+{
+ uint32_t *p;
+ uint32_t *end;
+ int sz;
+
+ sz = OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size);
+ p = start;
+ end = p + sz / 4;
+ p += sizeof(struct os_memblock) / 4;
+
+ while (p < end) {
+ *p = os_mem_poison;
+ p++;
}
}
static void
-os_mempool_poison_check(void *start, int sz)
+os_mempool_poison_check(const struct os_mempool *mp, void *start)
{
- int i;
- char *p = start;
+ uint32_t *p;
+ uint32_t *end;
+ int sz;
- for (i = sizeof(struct os_memblock); i < sz;
- i = i + sizeof(os_mem_poison)) {
- assert(!memcmp(p + i, &os_mem_poison,
- min(sizeof(os_mem_poison), sz - i)));
+ sz = OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size);
+ p = start;
+ end = p + sz / 4;
+ p += sizeof(struct os_memblock) / 4;
+
+ while (p < end) {
+ assert(*p == os_mem_poison);
+ p++;
}
}
#else
-#define os_mempool_poison(start, sz)
-#define os_mempool_poison_check(start, sz)
+#define os_mempool_poison(mp, start)
+#define os_mempool_poison_check(mp, start)
+#endif
+#if MYNEWT_VAL(OS_MEMPOOL_GUARD)
+#define OS_MEMPOOL_GUARD_PATTERN 0xBAFF1ED1
+
+static void
+os_mempool_guard(const struct os_mempool *mp, void *start)
+{
+ uint32_t *tgt;
+
+ if ((mp->mp_flags & OS_MEMPOOL_F_EXT) == 0) {
+ tgt = (uint32_t *)((uintptr_t)start +
+ OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size));
+ *tgt = OS_MEMPOOL_GUARD_PATTERN;
+ }
+}
+
+static void
+os_mempool_guard_check(const struct os_mempool *mp, void *start)
+{
+ uint32_t *tgt;
+
+ if ((mp->mp_flags & OS_MEMPOOL_F_EXT) == 0) {
+ tgt = (uint32_t *)((uintptr_t)start +
+ OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size));
+ assert(*tgt == OS_MEMPOOL_GUARD_PATTERN);
+ }
+}
+#else
+#define os_mempool_guard(mp, start)
+#define os_mempool_guard_check(mp, start)
#endif
-os_error_t
-os_mempool_init(struct os_mempool *mp, uint16_t blocks, uint32_t block_size,
- void *membuf, const char *name)
+static os_error_t
+os_mempool_init_internal(struct os_mempool *mp, uint16_t blocks,
+ uint32_t block_size, void *membuf, const char *name,
+ uint8_t flags)
{
int true_block_size;
+ int i;
uint8_t *block_addr;
struct os_memblock *block_ptr;
@@ -82,60 +139,109 @@ os_mempool_init(struct os_mempool *mp, uint16_t blocks, uint32_t block_size,
/* Blocks need to be sized properly and memory buffer should be
* aligned
*/
- if (((uintptr_t)membuf & (OS_ALIGNMENT - 1)) != 0) {
+ if (((uint32_t)(uintptr_t)membuf & (OS_ALIGNMENT - 1)) != 0) {
return OS_MEM_NOT_ALIGNED;
}
}
- true_block_size = OS_MEM_TRUE_BLOCK_SIZE(block_size);
/* Initialize the memory pool structure */
mp->mp_block_size = block_size;
mp->mp_num_free = blocks;
mp->mp_min_free = blocks;
- mp->mp_flags = 0;
+ mp->mp_flags = flags;
mp->mp_num_blocks = blocks;
- mp->mp_membuf_addr = (uintptr_t)membuf;
+ mp->mp_membuf_addr = (uint32_t)(uintptr_t)membuf;
mp->name = name;
- os_mempool_poison(membuf, true_block_size);
SLIST_FIRST(mp) = membuf;
- /* Chain the memory blocks to the free list */
- block_addr = (uint8_t *)membuf;
- block_ptr = (struct os_memblock *)block_addr;
- while (blocks > 1) {
- block_addr += true_block_size;
- os_mempool_poison(block_addr, true_block_size);
- SLIST_NEXT(block_ptr, mb_next) = (struct os_memblock *)block_addr;
- block_ptr = (struct os_memblock *)block_addr;
- --blocks;
- }
+ if (blocks > 0) {
+ os_mempool_poison(mp, membuf);
+ os_mempool_guard(mp, membuf);
+ true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
- /* Last one in the list should be NULL */
- SLIST_NEXT(block_ptr, mb_next) = NULL;
+ /* Chain the memory blocks to the free list */
+ block_addr = (uint8_t *)membuf;
+ block_ptr = (struct os_memblock *)block_addr;
+ for (i = 1; i < blocks; i++) {
+ block_addr += true_block_size;
+ os_mempool_poison(mp, block_addr);
+ os_mempool_guard(mp, block_addr);
+ SLIST_NEXT(block_ptr, mb_next) = (struct os_memblock *)block_addr;
+ block_ptr = (struct os_memblock *)block_addr;
+ }
+
+ /* Last one in the list should be NULL */
+ SLIST_NEXT(block_ptr, mb_next) = NULL;
+ }
STAILQ_INSERT_TAIL(&g_os_mempool_list, mp, mp_list);
return OS_OK;
}
+os_error_t
+os_mempool_init(struct os_mempool *mp, uint16_t blocks, uint32_t block_size,
+ void *membuf, const char *name)
+{
+ return os_mempool_init_internal(mp, blocks, block_size, membuf, name, 0);
+}
+
os_error_t
os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name)
{
int rc;
- rc = os_mempool_init(&mpe->mpe_mp, blocks, block_size, membuf, name);
+ rc = os_mempool_init_internal(&mpe->mpe_mp, blocks, block_size, membuf,
+ name, OS_MEMPOOL_F_EXT);
if (rc != 0) {
return rc;
}
- mpe->mpe_mp.mp_flags = OS_MEMPOOL_F_EXT;
mpe->mpe_put_cb = NULL;
mpe->mpe_put_arg = NULL;
return 0;
}
+os_error_t
+os_mempool_unregister(struct os_mempool *mp)
+{
+ struct os_mempool *prev;
+ struct os_mempool *next;
+ struct os_mempool *cur;
+
+ /* Remove the mempool from the global stailq. This is done manually rather
+ * than with `STAILQ_REMOVE` to allow for a graceful failure if the mempool
+ * isn't found.
+ */
+
+ prev = NULL;
+ STAILQ_FOREACH(cur, &g_os_mempool_list, mp_list) {
+ if (cur == mp) {
+ break;
+ }
+ prev = cur;
+ }
+
+ if (cur == NULL) {
+ return OS_INVALID_PARM;
+ }
+
+ if (prev == NULL) {
+ STAILQ_REMOVE_HEAD(&g_os_mempool_list, mp_list);
+ } else {
+ next = STAILQ_NEXT(cur, mp_list);
+ if (next == NULL) {
+ g_os_mempool_list.stqh_last = &STAILQ_NEXT(prev, mp_list);
+ }
+
+ STAILQ_NEXT(prev, mp_list) = next;
+ }
+
+ return 0;
+}
+
os_error_t
os_mempool_clear(struct os_mempool *mp)
{
@@ -148,22 +254,24 @@ os_mempool_clear(struct os_mempool *mp)
return OS_INVALID_PARM;
}
- true_block_size = OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size);
+ true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
/* cleanup the memory pool structure */
mp->mp_num_free = mp->mp_num_blocks;
mp->mp_min_free = mp->mp_num_blocks;
- os_mempool_poison((void *)mp->mp_membuf_addr, true_block_size);
- SLIST_FIRST(mp) = (void *)mp->mp_membuf_addr;
+ os_mempool_poison(mp, (void *)mp->mp_membuf_addr);
+ os_mempool_guard(mp, (void *)mp->mp_membuf_addr);
+ SLIST_FIRST(mp) = (void *)(uintptr_t)mp->mp_membuf_addr;
/* Chain the memory blocks to the free list */
- block_addr = (uint8_t *)mp->mp_membuf_addr;
+ block_addr = (uint8_t *)(uintptr_t)mp->mp_membuf_addr;
block_ptr = (struct os_memblock *)block_addr;
blocks = mp->mp_num_blocks;
while (blocks > 1) {
block_addr += true_block_size;
- os_mempool_poison(block_addr, true_block_size);
+ os_mempool_poison(mp, block_addr);
+ os_mempool_guard(mp, block_addr);
SLIST_NEXT(block_ptr, mb_next) = (struct os_memblock *)block_addr;
block_ptr = (struct os_memblock *)block_addr;
--blocks;
@@ -195,7 +303,8 @@ os_mempool_is_sane(const struct os_mempool *mp)
if (!os_memblock_from(mp, block)) {
return false;
}
- os_mempool_poison_check(block, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
+ os_mempool_poison_check(mp, block);
+ os_mempool_guard_check(mp, block);
}
return true;
@@ -204,24 +313,24 @@ os_mempool_is_sane(const struct os_mempool *mp)
int
os_memblock_from(const struct os_mempool *mp, const void *block_addr)
{
- uintptr_t true_block_size;
- uintptr_t baddr_ptr;
- uintptr_t end;
+ uint32_t true_block_size;
+ uintptr_t baddr32;
+ uint32_t end;
- _Static_assert(sizeof block_addr == sizeof baddr_ptr,
- "Pointer to void must be native word size.");
+ static_assert(sizeof block_addr == sizeof baddr32,
+ "Pointer to void must be 32-bits.");
- baddr_ptr = (uintptr_t)block_addr;
+ baddr32 = (uint32_t)(uintptr_t)block_addr;
true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
end = mp->mp_membuf_addr + (mp->mp_num_blocks * true_block_size);
/* Check that the block is in the memory buffer range. */
- if ((baddr_ptr < mp->mp_membuf_addr) || (baddr_ptr >= end)) {
+ if ((baddr32 < mp->mp_membuf_addr) || (baddr32 >= end)) {
return 0;
}
/* All freed blocks should be on true block size boundaries! */
- if (((baddr_ptr - mp->mp_membuf_addr) % true_block_size) != 0) {
+ if (((baddr32 - mp->mp_membuf_addr) % true_block_size) != 0) {
return 0;
}
@@ -234,6 +343,8 @@ os_memblock_get(struct os_mempool *mp)
os_sr_t sr;
struct os_memblock *block;
+ os_trace_api_u32(OS_TRACE_ID_MEMBLOCK_GET, (uint32_t)(uintptr_t)mp);
+
/* Check to make sure they passed in a memory pool (or something) */
block = NULL;
if (mp) {
@@ -255,10 +366,13 @@ os_memblock_get(struct os_mempool *mp)
OS_EXIT_CRITICAL(sr);
if (block) {
- os_mempool_poison_check(block, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
+ os_mempool_poison_check(mp, block);
+ os_mempool_guard_check(mp, block);
}
}
+ os_trace_api_ret_u32(OS_TRACE_ID_MEMBLOCK_GET, (uint32_t)(uintptr_t)block);
+
return (void *)block;
}
@@ -268,7 +382,11 @@ os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr)
os_sr_t sr;
struct os_memblock *block;
- os_mempool_poison(block_addr, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
+ os_trace_api_u32x2(OS_TRACE_ID_MEMBLOCK_PUT_FROM_CB, (uint32_t)(uintptr_t)mp,
+ (uint32_t)(uintptr_t)block_addr);
+
+ os_mempool_guard_check(mp, block_addr);
+ os_mempool_poison(mp, block_addr);
block = (struct os_memblock *)block_addr;
OS_ENTER_CRITICAL(sr);
@@ -283,6 +401,8 @@ os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr)
OS_EXIT_CRITICAL(sr);
+ os_trace_api_ret_u32(OS_TRACE_ID_MEMBLOCK_PUT_FROM_CB, (uint32_t)OS_OK);
+
return OS_OK;
}
@@ -290,14 +410,18 @@ os_error_t
os_memblock_put(struct os_mempool *mp, void *block_addr)
{
struct os_mempool_ext *mpe;
- int rc;
+ os_error_t ret;
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
struct os_memblock *block;
#endif
+ os_trace_api_u32x2(OS_TRACE_ID_MEMBLOCK_PUT, (uint32_t)(uintptr_t)mp,
+ (uint32_t)(uintptr_t)block_addr);
+
/* Make sure parameters are valid */
if ((mp == NULL) || (block_addr == NULL)) {
- return OS_INVALID_PARM;
+ ret = OS_INVALID_PARM;
+ goto done;
}
#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
@@ -311,20 +435,23 @@ os_memblock_put(struct os_mempool *mp, void *block_addr)
assert(block != (struct os_memblock *)block_addr);
}
#endif
-
/* If this is an extended mempool with a put callback, call the callback
* instead of freeing the block directly.
*/
if (mp->mp_flags & OS_MEMPOOL_F_EXT) {
mpe = (struct os_mempool_ext *)mp;
if (mpe->mpe_put_cb != NULL) {
- rc = mpe->mpe_put_cb(mpe, block_addr, mpe->mpe_put_arg);
- return rc;
+ ret = mpe->mpe_put_cb(mpe, block_addr, mpe->mpe_put_arg);
+ goto done;
}
}
/* No callback; free the block. */
- return os_memblock_put_from_cb(mp, block_addr);
+ ret = os_memblock_put_from_cb(mp, block_addr);
+
+done:
+ os_trace_api_ret_u32(OS_TRACE_ID_MEMBLOCK_PUT, (uint32_t)ret);
+ return ret;
}
struct os_mempool *
@@ -352,4 +479,8 @@ os_mempool_info_get_next(struct os_mempool *mp, struct os_mempool_info *omi)
return (cur);
}
-
+void
+os_mempool_module_init(void)
+{
+ STAILQ_INIT(&g_os_mempool_list);
+}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c
index 180e18d60..57262758f 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/nimble/src/os_msys_init.c
@@ -20,16 +20,35 @@
#include
#include "../include/os/os.h"
#include "../include/mem/mem.h"
+#include "../include/sysinit/sysinit.h"
#ifdef ESP_PLATFORM
#include "nimble/esp_port/port/include/esp_nimble_mem.h"
+#include "esp_err.h"
#endif
-#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
+static STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list =
+ STAILQ_HEAD_INITIALIZER(g_msys_pool_list);
+
+#if CONFIG_BT_NIMBLE_ENABLED
+#define OS_MSYS_1_BLOCK_COUNT MYNEWT_VAL(MSYS_1_BLOCK_COUNT)
+#define OS_MSYS_1_BLOCK_SIZE MYNEWT_VAL(MSYS_1_BLOCK_SIZE)
+#define OS_MSYS_2_BLOCK_COUNT MYNEWT_VAL(MSYS_2_BLOCK_COUNT)
+#define OS_MSYS_2_BLOCK_SIZE MYNEWT_VAL(MSYS_2_BLOCK_SIZE)
+#else
+#define OS_MSYS_1_BLOCK_COUNT CONFIG_BT_LE_MSYS_1_BLOCK_COUNT
+#define OS_MSYS_1_BLOCK_SIZE CONFIG_BT_LE_MSYS_1_BLOCK_SIZE
+#define OS_MSYS_2_BLOCK_COUNT CONFIG_BT_LE_MSYS_2_BLOCK_COUNT
+#define OS_MSYS_2_BLOCK_SIZE CONFIG_BT_LE_MSYS_2_BLOCK_SIZE
+#endif
+
+
+
+#if OS_MSYS_1_BLOCK_COUNT > 0
#define SYSINIT_MSYS_1_MEMBLOCK_SIZE \
- OS_ALIGN(MYNEWT_VAL(MSYS_1_BLOCK_SIZE), OS_ALIGNMENT)
+ OS_ALIGN(OS_MSYS_1_BLOCK_SIZE, 4)
#define SYSINIT_MSYS_1_MEMPOOL_SIZE \
- OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_1_BLOCK_COUNT), \
+ OS_MEMPOOL_SIZE(OS_MSYS_1_BLOCK_COUNT, \
SYSINIT_MSYS_1_MEMBLOCK_SIZE)
#ifdef ESP_PLATFORM
static os_membuf_t *os_msys_init_1_data;
@@ -40,11 +59,11 @@ static struct os_mbuf_pool os_msys_init_1_mbuf_pool;
static struct os_mempool os_msys_init_1_mempool;
#endif
-#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
+#if OS_MSYS_2_BLOCK_COUNT > 0
#define SYSINIT_MSYS_2_MEMBLOCK_SIZE \
- OS_ALIGN(MYNEWT_VAL(MSYS_2_BLOCK_SIZE), OS_ALIGNMENT)
+ OS_ALIGN(OS_MSYS_2_BLOCK_SIZE, 4)
#define SYSINIT_MSYS_2_MEMPOOL_SIZE \
- OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_2_BLOCK_COUNT), \
+ OS_MEMPOOL_SIZE(OS_MSYS_2_BLOCK_COUNT, \
SYSINIT_MSYS_2_MEMBLOCK_SIZE)
#ifdef ESP_PLATFORM
static os_membuf_t *os_msys_init_2_data;
@@ -55,6 +74,62 @@ static struct os_mbuf_pool os_msys_init_2_mbuf_pool;
static struct os_mempool os_msys_init_2_mempool;
#endif
+#define OS_MSYS_SANITY_ENABLED \
+ (MYNEWT_VAL(MSYS_1_SANITY_MIN_COUNT) > 0 || \
+ MYNEWT_VAL(MSYS_2_SANITY_MIN_COUNT) > 0)
+
+#if OS_MSYS_SANITY_ENABLED
+static struct os_sanity_check os_msys_sc;
+#endif
+
+#if OS_MSYS_SANITY_ENABLED
+
+/**
+ * Retrieves the minimum safe buffer count for an msys pool. That is, the
+ * lowest a pool's buffer count can be without causing the sanity check to
+ * fail.
+ *
+ * @param idx The index of the msys pool to query.
+ *
+ * @return The msys pool's minimum safe buffer count.
+ */
+static int
+IRAM_ATTR os_msys_sanity_min_count(int idx)
+{
+ switch (idx) {
+ case 0:
+ return MYNEWT_VAL(MSYS_1_SANITY_MIN_COUNT);
+
+ case 1:
+ return MYNEWT_VAL(MSYS_2_SANITY_MIN_COUNT);
+
+ default:
+ BLE_LL_ASSERT(0);
+ return ESP_OK;
+ }
+}
+
+static int
+IRAM_ATTR os_msys_sanity(struct os_sanity_check *sc, void *arg)
+{
+ const struct os_mbuf_pool *omp;
+ int min_count;
+ int idx;
+
+ idx = 0;
+ STAILQ_FOREACH(omp, &g_msys_pool_list, omp_next) {
+ min_count = os_msys_sanity_min_count(idx);
+ if (omp->omp_pool->mp_num_free < min_count) {
+ return OS_ENOMEM;
+ }
+
+ idx++;
+ }
+
+ return ESP_OK;
+}
+#endif
+
static void
os_msys_init_once(void *data, struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool,
@@ -64,42 +139,42 @@ os_msys_init_once(void *data, struct os_mempool *mempool,
rc = mem_init_mbuf_pool(data, mempool, mbuf_pool, block_count, block_size,
name);
- assert(rc == 0);
+ SYSINIT_PANIC_ASSERT(rc == 0);
rc = os_msys_register(mbuf_pool);
- assert(rc == 0);
+ SYSINIT_PANIC_ASSERT(rc == 0);
}
#ifdef ESP_PLATFORM
int
os_msys_buf_alloc(void)
{
-#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
+#if OS_MSYS_1_BLOCK_COUNT > 0
os_msys_init_1_data = (os_membuf_t *)nimble_platform_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_1_MEMPOOL_SIZE));
if (!os_msys_init_1_data) {
- return -1;
+ return ESP_FAIL;
}
#endif
-#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
+#if OS_MSYS_2_BLOCK_COUNT > 0
os_msys_init_2_data = (os_membuf_t *)nimble_platform_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_2_MEMPOOL_SIZE));
if (!os_msys_init_2_data) {
- return -1;
+ return ESP_FAIL;
}
#endif
- return 0;
+ return ESP_OK;
}
void
os_msys_buf_free(void)
{
-#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
+#if OS_MSYS_1_BLOCK_COUNT > 0
nimble_platform_mem_free(os_msys_init_1_data);
os_msys_init_1_data = NULL;
#endif
-#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
+#if OS_MSYS_2_BLOCK_COUNT > 0
nimble_platform_mem_free(os_msys_init_2_data);
os_msys_init_2_data = NULL;
#endif
@@ -107,27 +182,37 @@ os_msys_buf_free(void)
}
#endif
-void
-os_msys_init(void)
+void os_msys_init(void)
{
+#if OS_MSYS_SANITY_ENABLED
+ int rc;
+#endif
+
os_msys_reset();
- (void)os_msys_init_once;
-#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
+#if OS_MSYS_1_BLOCK_COUNT > 0
os_msys_init_once(os_msys_init_1_data,
&os_msys_init_1_mempool,
&os_msys_init_1_mbuf_pool,
- MYNEWT_VAL(MSYS_1_BLOCK_COUNT),
+ OS_MSYS_1_BLOCK_COUNT,
SYSINIT_MSYS_1_MEMBLOCK_SIZE,
"msys_1");
#endif
-#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
+#if OS_MSYS_2_BLOCK_COUNT > 0
os_msys_init_once(os_msys_init_2_data,
&os_msys_init_2_mempool,
&os_msys_init_2_mbuf_pool,
- MYNEWT_VAL(MSYS_2_BLOCK_COUNT),
+ OS_MSYS_2_BLOCK_COUNT,
SYSINIT_MSYS_2_MEMBLOCK_SIZE,
"msys_2");
#endif
+
+#if OS_MSYS_SANITY_ENABLED
+ os_msys_sc.sc_func = os_msys_sanity;
+ os_msys_sc.sc_checkin_itvl =
+ OS_TICKS_PER_SEC * MYNEWT_VAL(MSYS_SANITY_TIMEOUT) / 1000;
+ rc = os_sanity_check_register(&os_msys_sc);
+ SYSINIT_PANIC_ASSERT(rc == 0);
+#endif
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h
index 7321cd27a..b84507503 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h
@@ -19,6 +19,399 @@
#ifndef _NIMBLE_NPL_OS_H_
#define _NIMBLE_NPL_OS_H_
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+
+#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS
+
+#include
+#include
+#include
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+#include "freertos/task.h"
+#include "freertos/timers.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) \
+ (sizeof(array) / sizeof((array)[0]))
+#endif
+
+#ifdef ESP_PLATFORM
+extern int ets_printf(const char *fmt, ...);
+#else
+#define ets_printf printf
+#define IRAM_ATTR
+#define NIMBLE_CFG_CONTROLLER 1
+#endif
+
+#define PLATFORM_BLE_LL_ASSERT(con) \
+ do{ \
+ if(!(con)) { \
+ ets_printf("assertion:%s\n",#con); \
+ ets_printf("line:%d,function:%s\n", __LINE__, __func__);\
+ assert(0); \
+ } \
+ }while(0)
+
+#define BLE_NPL_OS_ALIGNMENT (4)/*ble_npl_get_os_alignment()*/
+
+#define BLE_NPL_TIME_FOREVER ble_npl_get_time_forever()
+
+/* This should be compatible with TickType_t */
+typedef uint32_t ble_npl_time_t;
+typedef int32_t ble_npl_stime_t;
+
+struct ble_npl_event;
+typedef void ble_npl_event_fn(struct ble_npl_event *ev);
+
+struct ble_npl_event {
+ void *event;
+};
+
+struct ble_npl_eventq {
+ void *eventq;
+};
+
+struct ble_npl_callout {
+ void *co;
+};
+
+struct ble_npl_mutex {
+ void *mutex;
+};
+
+struct ble_npl_sem {
+ void *sem;
+};
+
+/*
+ * Simple APIs are just defined as static inline below, but some are a bit more
+ * complex or require some global state variables and thus are defined in .c
+ * file instead and static inline wrapper just calls proper implementation.
+ * We need declarations of these functions and they are defined in header below.
+ */
+#include "npl_freertos.h"
+
+struct npl_funcs_t {
+ bool (*p_ble_npl_os_started)(void);
+ void *(*p_ble_npl_get_current_task_id)(void);
+ void (*p_ble_npl_eventq_init)(struct ble_npl_eventq *);
+ void (*p_ble_npl_eventq_deinit)(struct ble_npl_eventq *);
+ struct ble_npl_event * (*p_ble_npl_eventq_get)(struct ble_npl_eventq *, ble_npl_time_t);
+ void (*p_ble_npl_eventq_put)(struct ble_npl_eventq *, struct ble_npl_event *);
+ void (*p_ble_npl_eventq_remove)(struct ble_npl_eventq *, struct ble_npl_event *);
+ void (*p_ble_npl_event_run)(struct ble_npl_event *);
+ bool (*p_ble_npl_eventq_is_empty)(struct ble_npl_eventq *);
+ void (*p_ble_npl_event_init)(struct ble_npl_event *, ble_npl_event_fn *, void *);
+ void (*p_ble_npl_event_deinit)(struct ble_npl_event *);
+ void (*p_ble_npl_event_reset)(struct ble_npl_event *);
+ bool (*p_ble_npl_event_is_queued)(struct ble_npl_event *);
+ void * (*p_ble_npl_event_get_arg)(struct ble_npl_event *);
+ void (*p_ble_npl_event_set_arg)(struct ble_npl_event *, void *);
+ ble_npl_error_t (*p_ble_npl_mutex_init)(struct ble_npl_mutex *);
+ ble_npl_error_t (*p_ble_npl_mutex_deinit)(struct ble_npl_mutex *);
+ ble_npl_error_t (*p_ble_npl_mutex_pend)(struct ble_npl_mutex *, ble_npl_time_t);
+ ble_npl_error_t (*p_ble_npl_mutex_release)(struct ble_npl_mutex *);
+ ble_npl_error_t (*p_ble_npl_sem_init)(struct ble_npl_sem *, uint16_t);
+ ble_npl_error_t (*p_ble_npl_sem_deinit)(struct ble_npl_sem *);
+ ble_npl_error_t (*p_ble_npl_sem_pend)(struct ble_npl_sem *, ble_npl_time_t);
+ ble_npl_error_t (*p_ble_npl_sem_release)(struct ble_npl_sem *);
+ uint16_t (*p_ble_npl_sem_get_count)(struct ble_npl_sem *);
+ void (*p_ble_npl_callout_init)(struct ble_npl_callout *, struct ble_npl_eventq *, ble_npl_event_fn *, void *);
+ ble_npl_error_t (*p_ble_npl_callout_reset)(struct ble_npl_callout *, ble_npl_time_t);
+ void (*p_ble_npl_callout_stop)(struct ble_npl_callout *);
+ void (*p_ble_npl_callout_deinit)(struct ble_npl_callout *);
+ void (*p_ble_npl_callout_mem_reset)(struct ble_npl_callout *);
+ bool (*p_ble_npl_callout_is_active)(struct ble_npl_callout *);
+ ble_npl_time_t (*p_ble_npl_callout_get_ticks)(struct ble_npl_callout *);
+ uint32_t (*p_ble_npl_callout_remaining_ticks)(struct ble_npl_callout *, ble_npl_time_t);
+ void (*p_ble_npl_callout_set_arg)(struct ble_npl_callout *, void *);
+ uint32_t (*p_ble_npl_time_get)(void);
+ ble_npl_error_t (*p_ble_npl_time_ms_to_ticks)(uint32_t ms, ble_npl_time_t *);
+ ble_npl_error_t (*p_ble_npl_time_ticks_to_ms)(ble_npl_time_t, uint32_t *);
+ ble_npl_time_t (*p_ble_npl_time_ms_to_ticks32)(uint32_t);
+ uint32_t (*p_ble_npl_time_ticks_to_ms32)(ble_npl_time_t);
+ void (*p_ble_npl_time_delay)(ble_npl_time_t);
+#ifdef ESP_PLATFORM
+ void (*p_ble_npl_hw_set_isr)(int, uint32_t);
+#else
+ void (*p_ble_npl_hw_set_isr)(int, void (*addr)(void));
+#endif
+ uint32_t (*p_ble_npl_hw_enter_critical)(void);
+ void (*p_ble_npl_hw_exit_critical)(uint32_t);
+ uint32_t (*p_ble_npl_get_time_forever)(void);
+ uint8_t (*p_ble_npl_hw_is_in_critical)(void);
+};
+
+extern struct npl_funcs_t *npl_funcs;
+
+static inline bool
+IRAM_ATTR ble_npl_os_started(void)
+{
+ return npl_funcs->p_ble_npl_os_started();
+}
+
+static inline void *
+IRAM_ATTR ble_npl_get_current_task_id(void)
+{
+ return npl_funcs->p_ble_npl_get_current_task_id();
+}
+
+static inline void
+IRAM_ATTR ble_npl_eventq_init(struct ble_npl_eventq *evq)
+{
+ return npl_funcs->p_ble_npl_eventq_init(evq);
+}
+
+static inline void
+IRAM_ATTR ble_npl_eventq_deinit(struct ble_npl_eventq *evq)
+{
+ return npl_funcs->p_ble_npl_eventq_deinit(evq);
+}
+
+static inline struct ble_npl_event *
+IRAM_ATTR ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo)
+{
+ return npl_funcs->p_ble_npl_eventq_get(evq, tmo);
+}
+
+static inline void
+IRAM_ATTR ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
+{
+ return npl_funcs->p_ble_npl_eventq_put(evq, ev);
+}
+
+static inline void
+IRAM_ATTR ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
+{
+ return npl_funcs->p_ble_npl_eventq_remove(evq, ev);
+}
+
+static inline void
+IRAM_ATTR ble_npl_event_run(struct ble_npl_event *ev)
+{
+ return npl_funcs->p_ble_npl_event_run(ev);
+}
+
+static inline bool
+IRAM_ATTR ble_npl_eventq_is_empty(struct ble_npl_eventq *evq)
+{
+ return npl_funcs->p_ble_npl_eventq_is_empty(evq);
+}
+
+static inline void
+IRAM_ATTR ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
+ void *arg)
+{
+ return npl_funcs->p_ble_npl_event_init(ev, fn, arg);
+}
+
+static inline bool
+IRAM_ATTR ble_npl_event_is_queued(struct ble_npl_event *ev)
+{
+ return npl_funcs->p_ble_npl_event_is_queued(ev);
+}
+
+static inline void *
+IRAM_ATTR ble_npl_event_get_arg(struct ble_npl_event *ev)
+{
+ return npl_funcs->p_ble_npl_event_get_arg(ev);
+}
+
+static inline void
+IRAM_ATTR ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg)
+{
+ return npl_funcs->p_ble_npl_event_set_arg(ev, arg);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_mutex_init(struct ble_npl_mutex *mu)
+{
+ return npl_funcs->p_ble_npl_mutex_init(mu);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_mutex_deinit(struct ble_npl_mutex *mu)
+{
+ return npl_funcs->p_ble_npl_mutex_deinit(mu);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout)
+{
+ return npl_funcs->p_ble_npl_mutex_pend(mu, timeout);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_mutex_release(struct ble_npl_mutex *mu)
+{
+ return npl_funcs->p_ble_npl_mutex_release(mu);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
+{
+ return npl_funcs->p_ble_npl_sem_init(sem, tokens);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_sem_deinit(struct ble_npl_sem *sem)
+{
+ return npl_funcs->p_ble_npl_sem_deinit(sem);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout)
+{
+ return npl_funcs->p_ble_npl_sem_pend(sem, timeout);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_sem_release(struct ble_npl_sem *sem)
+{
+ return npl_funcs->p_ble_npl_sem_release(sem);
+}
+
+static inline uint16_t
+IRAM_ATTR ble_npl_sem_get_count(struct ble_npl_sem *sem)
+{
+ return npl_funcs->p_ble_npl_sem_get_count(sem);
+}
+
+static inline void
+IRAM_ATTR ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
+ ble_npl_event_fn *ev_cb, void *ev_arg)
+{
+ return npl_funcs->p_ble_npl_callout_init(co, evq, ev_cb, ev_arg);
+}
+static inline void
+IRAM_ATTR ble_npl_callout_deinit(struct ble_npl_callout *co)
+{
+ return npl_funcs->p_ble_npl_callout_deinit(co);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks)
+{
+ return npl_funcs->p_ble_npl_callout_reset(co, ticks);
+}
+
+static inline void
+IRAM_ATTR ble_npl_callout_stop(struct ble_npl_callout *co)
+{
+ return npl_funcs->p_ble_npl_callout_stop(co);
+}
+
+static inline bool
+IRAM_ATTR ble_npl_callout_is_active(struct ble_npl_callout *co)
+{
+ return npl_funcs->p_ble_npl_callout_is_active(co);
+}
+
+static inline ble_npl_time_t
+IRAM_ATTR ble_npl_callout_get_ticks(struct ble_npl_callout *co)
+{
+ return npl_funcs->p_ble_npl_callout_get_ticks(co);
+}
+
+static inline ble_npl_time_t
+IRAM_ATTR ble_npl_callout_remaining_ticks(struct ble_npl_callout *co,
+ ble_npl_time_t time)
+{
+ return npl_funcs->p_ble_npl_callout_remaining_ticks(co, time);
+}
+
+static inline void
+IRAM_ATTR ble_npl_callout_set_arg(struct ble_npl_callout *co, void *arg)
+{
+ return npl_funcs->p_ble_npl_callout_set_arg(co, arg);
+}
+
+static inline ble_npl_time_t
+IRAM_ATTR ble_npl_time_get(void)
+{
+ return npl_funcs->p_ble_npl_time_get();
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks)
+{
+ return npl_funcs->p_ble_npl_time_ms_to_ticks(ms, out_ticks);
+}
+
+static inline ble_npl_error_t
+IRAM_ATTR ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
+{
+ return npl_funcs->p_ble_npl_time_ticks_to_ms(ticks, out_ms);
+}
+
+static inline ble_npl_time_t
+IRAM_ATTR ble_npl_time_ms_to_ticks32(uint32_t ms)
+{
+ return npl_funcs->p_ble_npl_time_ms_to_ticks32(ms);
+}
+
+static inline uint32_t
+IRAM_ATTR ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks)
+{
+ return npl_funcs->p_ble_npl_time_ticks_to_ms32(ticks);
+}
+
+static inline void
+IRAM_ATTR ble_npl_time_delay(ble_npl_time_t ticks)
+{
+ return npl_funcs->p_ble_npl_time_delay(ticks);
+}
+
+#if NIMBLE_CFG_CONTROLLER
+#ifdef ESP_PLATFORM
+static inline void
+IRAM_ATTR ble_npl_hw_set_isr(int irqn, uint32_t addr)
+{
+ return npl_funcs->p_ble_npl_hw_set_isr(irqn, addr);
+}
+#else
+static inline void
+IRAM_ATTR ble_npl_hw_set_isr(int irqn, void (*addr)(void))
+{
+ return npl_funcs->p_ble_npl_hw_set_isr(irqn, addr);
+}
+#endif
+#endif
+
+//critical section
+static inline uint32_t
+IRAM_ATTR ble_npl_hw_enter_critical(void)
+{
+ return npl_funcs->p_ble_npl_hw_enter_critical();
+}
+
+static inline void
+IRAM_ATTR ble_npl_hw_exit_critical(uint32_t ctx)
+{
+ return npl_funcs->p_ble_npl_hw_exit_critical(ctx);
+}
+
+static inline bool IRAM_ATTR ble_npl_hw_is_in_critical(void)
+{
+ return npl_funcs->p_ble_npl_hw_is_in_critical();
+}
+
+#define ble_npl_get_time_forever (*npl_funcs->p_ble_npl_get_time_forever)
+#define ble_npl_callout_mem_reset (*npl_funcs->p_ble_npl_callout_mem_reset)
+#define ble_npl_event_deinit (*npl_funcs->p_ble_npl_event_deinit)
+#define ble_npl_event_reset (*npl_funcs->p_ble_npl_event_reset)
+
+#ifdef __cplusplus
+}
+#endif
+
+#else // Not using MEM Pools
#include
#include
@@ -38,6 +431,7 @@ extern "C" {
#define BLE_NPL_TIME_FOREVER portMAX_DELAY
#ifndef ESP_PLATFORM
+#define IRAM_ATTR
#define NIMBLE_CFG_CONTROLLER 1
#define NIMBLE_EVT_QUEUE_SIZE 4
#else
@@ -147,6 +541,12 @@ ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
ev->arg = arg;
}
+static inline void
+ble_npl_event_deinit(struct ble_npl_event *ev)
+{
+
+}
+
static inline bool
ble_npl_event_is_queued(struct ble_npl_event *ev)
{
@@ -355,4 +755,6 @@ ble_npl_hw_exit_critical(uint32_t ctx)
}
#endif
+#endif // CONFIG_NIMBLE_STACK_USE_MEM_POOLS
+
#endif /* _NPL_H_ */
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h
index 94d75f5a5..7d9c90be8 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h
@@ -21,17 +21,47 @@
#define _NIMBLE_PORT_FREERTOS_H
#include "nimble/nimble/include/nimble/nimble_npl.h"
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+
+#ifdef ESP_PLATFORM
+#include "esp_err.h"
+#endif
#ifdef __cplusplus
extern "C" {
#endif
+#ifdef ESP_PLATFORM
+/**
+ * @brief esp_nimble_enable - Initialize the NimBLE host task
+ *
+ * @param host_task
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_enable(void *host_task);
+
+/**
+ * @brief esp_nimble_disable - Disable the NimBLE host task
+ *
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_disable(void);
+#endif
+
void nimble_port_freertos_init(TaskFunction_t host_task_fn);
void nimble_port_freertos_deinit(void);
+
+#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS
+void npl_freertos_funcs_init(void);
+void npl_freertos_funcs_deinit(void);
+int npl_freertos_mempool_init(void);
+struct npl_funcs_t * npl_freertos_funcs_get(void);
+#endif
+
#ifndef ESP_PLATFORM
UBaseType_t nimble_port_freertos_get_ll_hwm(void);
-#endif
UBaseType_t nimble_port_freertos_get_hs_hwm(void);
+#endif
#ifdef __cplusplus
}
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h
index 69942773f..35f9c471a 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h
@@ -20,10 +20,46 @@
#ifndef _NPL_FREERTOS_H_
#define _NPL_FREERTOS_H_
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+
#ifdef __cplusplus
extern "C" {
#endif
+#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS
+typedef void ble_npl_event_fn(struct ble_npl_event *ev);
+
+struct ble_npl_event_freertos {
+ bool queued;
+ ble_npl_event_fn *fn;
+ void *arg;
+};
+
+struct ble_npl_eventq_freertos {
+ QueueHandle_t q;
+};
+
+struct ble_npl_callout_freertos {
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ esp_timer_handle_t handle;
+#else
+ TimerHandle_t handle;
+#endif
+ struct ble_npl_eventq *evq;
+ struct ble_npl_event ev;
+};
+
+struct ble_npl_mutex_freertos {
+ SemaphoreHandle_t handle;
+};
+
+struct ble_npl_sem_freertos {
+ SemaphoreHandle_t handle;
+};
+
+typedef void ble_npl_event_fn_freertos(struct ble_npl_event_freertos *ev);
+#endif
+
struct ble_npl_eventq *npl_freertos_eventq_dflt_get(void);
struct ble_npl_event *npl_freertos_eventq_get(struct ble_npl_eventq *evq,
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c
index 495ef445a..c2a970403 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c
@@ -21,24 +21,71 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "../../../nimble/include/nimble/nimble_port.h"
+#ifdef ESP_PLATFORM
+#include "esp_bt.h"
+#endif
+#ifndef ESP_PLATFORM
#if NIMBLE_CFG_CONTROLLER
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-#define NIMBLE_LL_TASK_STACK_SIZE (130)
+#define NIMBLE_LL_STACK_SIZE (130)
#else
-#define NIMBLE_LL_TASK_STACK_SIZE (100)
+#define NIMBLE_LL_STACK_SIZE (100)
#endif
-static StackType_t ll_xStack[ NIMBLE_LL_TASK_STACK_SIZE ];
+static StackType_t ll_xStack[ NIMBLE_LL_STACK_SIZE ];
static StaticTask_t ll_xTaskBuffer;
static TaskHandle_t ll_task_h;
#endif
-#ifndef ESP_PLATFORM
-static StackType_t hs_xStack[ NIMBLE_HS_TASK_STACK_SIZE ];
+static StackType_t hs_xStack[ NIMBLE_HS_STACK_SIZE ];
static StaticTask_t hs_xTaskBuffer;
#endif
-static TaskHandle_t host_task_h;
+static TaskHandle_t host_task_h = NULL;
+
+#ifdef ESP_PLATFORM
+/**
+ * @brief esp_nimble_enable - Initialize the NimBLE host
+ *
+ * @param host_task
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_enable(void *host_task)
+{
+ /*
+ * Create task where NimBLE host will run. It is not strictly necessary to
+ * have separate task for NimBLE host, but since something needs to handle
+ * default queue it is just easier to make separate task which does this.
+ */
+ xTaskCreatePinnedToCore(host_task, "nimble_host", NIMBLE_HS_STACK_SIZE,
+ NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE);
+ return ESP_OK;
+
+}
+
+/**
+ * @brief esp_nimble_disable - Disable the NimBLE host
+ *
+ * @return esp_err_t
+ */
+esp_err_t esp_nimble_disable(void)
+{
+ if (host_task_h) {
+ vTaskDelete(host_task_h);
+ host_task_h = NULL;
+ }
+ return ESP_OK;
+}
+
+// Compatibility wrappers for new functions
+void nimble_port_freertos_init(TaskFunction_t host_task_fn) {
+ esp_nimble_enable((void*)host_task_fn);
+}
+void nimble_port_freertos_deinit(void) {
+ esp_nimble_disable();
+}
+
+#else // ESP_PLATFORM
void
nimble_port_freertos_init(TaskFunction_t host_task_fn)
@@ -50,22 +97,16 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn)
* provided by NimBLE and in case of FreeRTOS it does not need to be wrapped
* since it has compatible prototype.
*/
- ll_task_h = xTaskCreateStatic(nimble_port_ll_task_func, "ll", NIMBLE_LL_TASK_STACK_SIZE,
+ ll_task_h = xTaskCreateStatic(nimble_port_ll_task_func, "ll", NIMBLE_LL_STACK_SIZE,
NULL, configMAX_PRIORITIES, ll_xStack, &ll_xTaskBuffer);
#endif
-
/*
* Create task where NimBLE host will run. It is not strictly necessary to
* have separate task for NimBLE host, but since something needs to handle
* default queue it is just easier to make separate task which does this.
*/
-#ifdef ESP_PLATFORM
- xTaskCreatePinnedToCore(host_task_fn, "ble", NIMBLE_STACK_SIZE,
- NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE);
-#else
- host_task_h = xTaskCreateStatic(host_task_fn, "ble", NIMBLE_HS_TASK_STACK_SIZE,
+ host_task_h = xTaskCreateStatic(host_task_fn, "ble", NIMBLE_HS_STACK_SIZE,
NULL, (configMAX_PRIORITIES - 1), hs_xStack, &hs_xTaskBuffer);
-#endif
}
void
@@ -89,3 +130,5 @@ nimble_port_freertos_get_hs_hwm(void)
{
return uxTaskGetStackHighWaterMark(host_task_h);
}
+
+#endif //ESP_PLATFORM
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c
index a37d4e1f1..a821841d5 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/porting/npl/freertos/src/npl_os_freertos.c
@@ -17,6 +17,1325 @@
* under the License.
*/
+#include "nimble/porting/nimble/include/syscfg/syscfg.h"
+
+#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS
+
+#include
+#include
+#include
+#include
+#include "nimble/console/console.h"
+
+#include "nimble/nimble/include/nimble/nimble_npl.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+#include "freertos/task.h"
+#include "freertos/timers.h"
+#include "freertos/portable.h"
+#include "../include/nimble/npl_freertos.h"
+
+#include "nimble/porting/nimble/include/os/os_mempool.h"
+
+#ifdef ESP_PLATFORM
+#include "esp_log.h"
+
+#include "soc/soc_caps.h"
+
+portMUX_TYPE ble_port_mutex = portMUX_INITIALIZER_UNLOCKED;
+
+#else
+#include "nrf.h"
+
+static void *radio_isr_addr;
+static void *rng_isr_addr;
+static void *rtc0_isr_addr;
+#endif
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+static const char *TAG = "Timer";
+#endif
+
+#define OS_MEM_ALLOC (1)
+
+#if CONFIG_BT_NIMBLE_ENABLED
+#define BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT)
+#define BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT)
+#define BT_LE_MAX_EXT_ADV_INSTANCES MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)
+#define BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS)
+#else
+#include "esp_bt.h"
+#define BT_LE_HCI_EVT_HI_BUF_COUNT DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT
+#define BT_LE_HCI_EVT_LO_BUF_COUNT DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT
+#define BT_LE_MAX_EXT_ADV_INSTANCES DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES
+#define BT_LE_MAX_CONNECTIONS DEFAULT_BT_LE_MAX_CONNECTIONS
+#endif
+
+#define BLE_HS_HCI_EVT_COUNT \
+ (BT_LE_HCI_EVT_HI_BUF_COUNT + \
+ BT_LE_HCI_EVT_LO_BUF_COUNT)
+
+
+#define LL_NPL_BASE_EVENT_COUNT (11)
+#define LL_SCAN_EXT_AUX_EVT_CNT (MYNEWT_VAL(BLE_LL_EXT_ADV_AUX_PTR_CNT))
+#define HCI_LL_NPL_EVENT_COUNT (1)
+#define ADV_LL_NPL_EVENT_COUNT ((BT_LE_MAX_EXT_ADV_INSTANCES+1)*3)
+#define SCAN_LL_NPL_EVENT_COUNT (2)
+#define RL_LL_NPL_EVENT_COUNT (1)
+#define SYNC_LL_NPL_EVENT_COUNT (7)
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
+#define LL_CTRL_TO_HOST_FLOW_CTRL_EVT (1)
+#else
+#define LL_CTRL_TO_HOST_FLOW_CTRL_EVT (0)
+#endif
+
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
+#define LL_CFG_FEAT_LE_PING_EVT (1)
+#else
+#define LL_CFG_FEAT_LE_PING_EVT (0)
+#endif
+
+#define CONN_MODULE_NPL_EVENT_COUNT (((LL_CFG_FEAT_LE_PING_EVT+2)*BT_LE_MAX_CONNECTIONS)+LL_CTRL_TO_HOST_FLOW_CTRL_EVT)
+
+
+#define BLE_LL_EV_COUNT (LL_NPL_BASE_EVENT_COUNT + \
+ LL_SCAN_EXT_AUX_EVT_CNT + \
+ HCI_LL_NPL_EVENT_COUNT + \
+ ADV_LL_NPL_EVENT_COUNT + \
+ SCAN_LL_NPL_EVENT_COUNT + \
+ RL_LL_NPL_EVENT_COUNT + \
+ SYNC_LL_NPL_EVENT_COUNT + \
+ CONN_MODULE_NPL_EVENT_COUNT)
+
+#define BLE_TOTAL_EV_COUNT (BLE_LL_EV_COUNT + BLE_HS_HCI_EVT_COUNT)
+
+#define BLE_TOTAL_EVQ_COUNT (10)
+
+#define BLE_TOTAL_CO_COUNT (40)
+
+#define BLE_TOTAL_SEM_COUNT (10)
+
+#define BLE_TOTAL_MUTEX_COUNT (10)
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+
+struct os_mempool ble_freertos_ev_pool;
+static os_membuf_t *ble_freertos_ev_buf = NULL;
+
+struct os_mempool ble_freertos_evq_pool;
+static os_membuf_t *ble_freertos_evq_buf = NULL;
+
+struct os_mempool ble_freertos_co_pool;
+static os_membuf_t *ble_freertos_co_buf = NULL;
+
+struct os_mempool ble_freertos_sem_pool;
+static os_membuf_t *ble_freertos_sem_buf = NULL;
+
+struct os_mempool ble_freertos_mutex_pool;
+static os_membuf_t *ble_freertos_mutex_buf = NULL;
+
+#else
+
+struct os_mempool ble_freertos_ev_pool;
+static os_membuf_t ble_freertos_ev_buf[
+ OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos))
+];
+
+struct os_mempool ble_freertos_evq_pool;
+static os_membuf_t ble_freertos_evq_buf[
+ OS_MEMPOOL_SIZE(BLE_TOTAL_EVQ_COUNT, sizeof (struct ble_npl_eventq_freertos))
+];
+
+struct os_mempool ble_freertos_co_pool;
+static os_membuf_t ble_freertos_co_buf[
+ OS_MEMPOOL_SIZE(BLE_TOTAL_CO_COUNT, sizeof (struct ble_npl_callout_freertos))
+];
+
+struct os_mempool ble_freertos_sem_pool;
+static os_membuf_t ble_freertos_sem_buf[
+ OS_MEMPOOL_SIZE(BLE_TOTAL_SEM_COUNT, sizeof (struct ble_npl_sem_freertos))
+];
+
+struct os_mempool ble_freertos_mutex_pool;
+static os_membuf_t ble_freertos_mutex_buf[
+ OS_MEMPOOL_SIZE(BLE_TOTAL_MUTEX_COUNT, sizeof (struct ble_npl_mutex_freertos))
+];
+
+#endif
+
+bool
+IRAM_ATTR npl_freertos_os_started(void)
+{
+ return xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
+}
+
+void *
+IRAM_ATTR npl_freertos_get_current_task_id(void)
+{
+ return xTaskGetCurrentTaskHandle();
+}
+
+void
+IRAM_ATTR npl_freertos_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
+ void *arg)
+{
+ struct ble_npl_event_freertos *event = NULL;
+#if OS_MEM_ALLOC
+ if (!os_memblock_from(&ble_freertos_ev_pool,ev->event)) {
+ ev->event = os_memblock_get(&ble_freertos_ev_pool);
+ }
+#else
+ if(!ev->event) {
+ ev->event = malloc(sizeof(struct ble_npl_event_freertos));
+ }
+#endif
+ event = (struct ble_npl_event_freertos *)ev->event;
+ PLATFORM_BLE_LL_ASSERT(event);
+
+ memset(event, 0, sizeof(*event));
+ event->fn = fn;
+ event->arg = arg;
+}
+
+void
+IRAM_ATTR npl_freertos_event_deinit(struct ble_npl_event *ev)
+{
+ PLATFORM_BLE_LL_ASSERT(ev->event);
+#if OS_MEM_ALLOC
+ os_memblock_put(&ble_freertos_ev_pool,ev->event);
+#else
+ free(ev->event);
+#endif
+ ev->event = NULL;
+}
+
+void
+IRAM_ATTR npl_freertos_event_reset(struct ble_npl_event *ev)
+{
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+ PLATFORM_BLE_LL_ASSERT(event);
+ event->queued = 0;
+}
+
+void
+IRAM_ATTR npl_freertos_eventq_init(struct ble_npl_eventq *evq)
+{
+ struct ble_npl_eventq_freertos *eventq = NULL;
+#if OS_MEM_ALLOC
+ if (!os_memblock_from(&ble_freertos_evq_pool,evq->eventq)) {
+ evq->eventq = os_memblock_get(&ble_freertos_evq_pool);
+ eventq = (struct ble_npl_eventq_freertos*)evq->eventq;
+ PLATFORM_BLE_LL_ASSERT(eventq);
+
+ memset(eventq, 0, sizeof(*eventq));
+ eventq->q = xQueueCreate(BLE_TOTAL_EV_COUNT, sizeof(struct ble_npl_eventq *));
+ PLATFORM_BLE_LL_ASSERT(eventq->q);
+ }
+#else
+ if(!evq->eventq) {
+ evq->eventq = malloc(sizeof(struct ble_npl_eventq_freertos));
+ eventq = (struct ble_npl_eventq_freertos*)evq->eventq;
+ PLATFORM_BLE_LL_ASSERT(eventq);
+
+ memset(eventq, 0, sizeof(*eventq));
+ eventq->q = xQueueCreate(BLE_TOTAL_EV_COUNT, sizeof(struct ble_npl_eventq *));
+ PLATFORM_BLE_LL_ASSERT(eventq->q);
+ }
+#endif
+}
+
+void
+IRAM_ATTR npl_freertos_eventq_deinit(struct ble_npl_eventq *evq)
+{
+ struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+
+ PLATFORM_BLE_LL_ASSERT(eventq);
+ vQueueDelete(eventq->q);
+#if OS_MEM_ALLOC
+ os_memblock_put(&ble_freertos_evq_pool,eventq);
+#else
+ free((void *)eventq);
+#endif
+ evq->eventq = NULL;
+}
+
+void
+IRAM_ATTR npl_freertos_callout_mem_reset(struct ble_npl_callout *co)
+{
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+
+ PLATFORM_BLE_LL_ASSERT(callout);
+ PLATFORM_BLE_LL_ASSERT(callout->handle);
+
+ ble_npl_event_reset(&callout->ev);
+}
+
+#ifdef ESP_PLATFORM
+static inline bool
+IRAM_ATTR in_isr(void)
+{
+ /* XXX hw specific! */
+ return xPortInIsrContext() != 0;
+}
+
+#else
+static inline bool
+in_isr(void)
+{
+ /* XXX hw specific! */
+ return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
+}
+
+void
+RADIO_IRQHandler(void)
+{
+ ((void (*)(void))radio_isr_addr)();
+}
+
+void
+RNG_IRQHandler(void)
+{
+ ((void (*)(void))rng_isr_addr)();
+}
+
+void
+RTC0_IRQHandler(void)
+{
+ ((void (*)(void))rtc0_isr_addr)();
+}
+
+/* This is called by NimBLE radio driver to set interrupt handlers */
+void
+npl_freertos_hw_set_isr(int irqn, void (*addr)(void))
+{
+ switch (irqn) {
+ case RADIO_IRQn:
+ radio_isr_addr = addr;
+ break;
+ case RNG_IRQn:
+ rng_isr_addr = addr;
+ break;
+ case RTC0_IRQn:
+ rtc0_isr_addr = addr;
+ break;
+ }
+}
+#endif
+
+struct ble_npl_event *
+IRAM_ATTR npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo)
+{
+ struct ble_npl_event *ev = NULL;
+ struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+ BaseType_t woken;
+ BaseType_t ret;
+
+ if (in_isr()) {
+ PLATFORM_BLE_LL_ASSERT(tmo == 0);
+ ret = xQueueReceiveFromISR(eventq->q, &ev, &woken);
+#ifdef ESP_PLATFORM
+
+ if( woken == pdTRUE ) {
+ portYIELD_FROM_ISR();
+ }
+#else
+ portYIELD_FROM_ISR(woken);
+#endif
+ } else {
+ ret = xQueueReceive(eventq->q, &ev, tmo);
+ }
+ PLATFORM_BLE_LL_ASSERT(ret == pdPASS || ret == errQUEUE_EMPTY);
+
+ if (ev) {
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+ if (event) {
+ event->queued = false;
+ }
+ }
+
+ return ev;
+}
+
+void
+IRAM_ATTR npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
+{
+ BaseType_t woken;
+ BaseType_t ret;
+ struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+
+ if (event->queued) {
+ return;
+ }
+
+ event->queued = true;
+
+ if (in_isr()) {
+ ret = xQueueSendToBackFromISR(eventq->q, &ev, &woken);
+#ifdef ESP_PLATFORM
+ if( woken == pdTRUE ) {
+ portYIELD_FROM_ISR();
+ }
+#else
+ portYIELD_FROM_ISR(woken);
+#endif
+ } else {
+ ret = xQueueSendToBack(eventq->q, &ev, portMAX_DELAY);
+ }
+
+ PLATFORM_BLE_LL_ASSERT(ret == pdPASS);
+}
+
+void
+IRAM_ATTR npl_freertos_eventq_remove(struct ble_npl_eventq *evq,
+ struct ble_npl_event *ev)
+{
+ struct ble_npl_event *tmp_ev;
+ BaseType_t ret;
+ int i;
+ int count;
+ BaseType_t woken, woken2;
+ struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+
+ if (!event->queued) {
+ return;
+ }
+
+ /*
+ * XXX We cannot extract element from inside FreeRTOS queue so as a quick
+ * workaround we'll just remove all elements and add them back except the
+ * one we need to remove. This is silly, but works for now - we probably
+ * better use counting semaphore with os_queue to handle this in future.
+ */
+
+ if (in_isr()) {
+ woken = pdFALSE;
+
+ count = uxQueueMessagesWaitingFromISR(eventq->q);
+ for (i = 0; i < count; i++) {
+ ret = xQueueReceiveFromISR(eventq->q, &tmp_ev, &woken2);
+ PLATFORM_BLE_LL_ASSERT(ret == pdPASS);
+ woken |= woken2;
+
+ if (tmp_ev == ev) {
+ continue;
+ }
+
+ ret = xQueueSendToBackFromISR(eventq->q, &tmp_ev, &woken2);
+ PLATFORM_BLE_LL_ASSERT(ret == pdPASS);
+ woken |= woken2;
+ }
+
+#ifdef ESP_PLATFORM
+ if( woken == pdTRUE ) {
+ portYIELD_FROM_ISR();
+ }
+#else
+ portYIELD_FROM_ISR(woken);
+#endif
+ } else {
+#ifdef ESP_PLATFORM
+ portMUX_TYPE ble_npl_mut = portMUX_INITIALIZER_UNLOCKED;
+ portENTER_CRITICAL(&ble_npl_mut);
+
+ count = uxQueueMessagesWaiting(eventq->q);
+#else
+ vPortEnterCritical();
+ count = uxQueueMessagesWaiting(eventq->q);
+#endif
+ for (i = 0; i < count; i++) {
+ ret = xQueueReceive(eventq->q, &tmp_ev, 0);
+ PLATFORM_BLE_LL_ASSERT(ret == pdPASS);
+
+ if (tmp_ev == ev) {
+ continue;
+ }
+
+ ret = xQueueSendToBack(eventq->q, &tmp_ev, 0);
+ PLATFORM_BLE_LL_ASSERT(ret == pdPASS);
+ }
+#ifdef ESP_PLATFORM
+ portEXIT_CRITICAL(&ble_npl_mut);
+#else
+ vPortExitCritical();
+#endif
+ }
+
+ event->queued = 0;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_mutex_init(struct ble_npl_mutex *mu)
+{
+ struct ble_npl_mutex_freertos *mutex = NULL;
+#if OS_MEM_ALLOC
+ if (!os_memblock_from(&ble_freertos_mutex_pool,mu->mutex)) {
+ mu->mutex = os_memblock_get(&ble_freertos_mutex_pool);
+ mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+ if (!mutex) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ memset(mutex, 0, sizeof(*mutex));
+ mutex->handle = xSemaphoreCreateRecursiveMutex();
+ PLATFORM_BLE_LL_ASSERT(mutex->handle);
+ }
+#else
+ if(!mu->mutex) {
+ mu->mutex = malloc(sizeof(struct ble_npl_mutex_freertos));
+ mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+ if (!mutex) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ memset(mutex, 0, sizeof(*mutex));
+ mutex->handle = xSemaphoreCreateRecursiveMutex();
+ PLATFORM_BLE_LL_ASSERT(mutex->handle);
+ }
+#endif
+
+ return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_mutex_deinit(struct ble_npl_mutex *mu)
+{
+ struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+ if (!mutex) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ PLATFORM_BLE_LL_ASSERT(mutex->handle);
+ vSemaphoreDelete(mutex->handle);
+
+#if OS_MEM_ALLOC
+ os_memblock_put(&ble_freertos_mutex_pool,mutex);
+#else
+ free((void *)mutex);
+#endif
+ mu->mutex = NULL;
+
+ return BLE_NPL_OK;
+}
+
+void
+IRAM_ATTR npl_freertos_event_run(struct ble_npl_event *ev)
+{
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+ event->fn(ev);
+}
+
+bool
+IRAM_ATTR npl_freertos_eventq_is_empty(struct ble_npl_eventq *evq)
+{
+ struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq;
+ return xQueueIsQueueEmptyFromISR(eventq->q);
+}
+
+bool
+IRAM_ATTR npl_freertos_event_is_queued(struct ble_npl_event *ev)
+{
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+ return event->queued;
+}
+
+void *
+IRAM_ATTR npl_freertos_event_get_arg(struct ble_npl_event *ev)
+{
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+ return event->arg;
+}
+
+void
+IRAM_ATTR npl_freertos_event_set_arg(struct ble_npl_event *ev, void *arg)
+{
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event;
+ event->arg = arg;
+}
+
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout)
+{
+ BaseType_t ret;
+ struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+ if (!mutex) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ PLATFORM_BLE_LL_ASSERT(mutex->handle);
+
+ if (in_isr()) {
+ ret = pdFAIL;
+ PLATFORM_BLE_LL_ASSERT(0);
+ } else {
+ ret = xSemaphoreTakeRecursive(mutex->handle, timeout);
+ }
+
+ return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_mutex_release(struct ble_npl_mutex *mu)
+{
+ struct ble_npl_mutex_freertos *mutex = (struct ble_npl_mutex_freertos *)mu->mutex;
+
+ if (!mutex) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ PLATFORM_BLE_LL_ASSERT(mutex->handle);
+
+ if (in_isr()) {
+ PLATFORM_BLE_LL_ASSERT(0);
+ } else {
+ if (xSemaphoreGiveRecursive(mutex->handle) != pdPASS) {
+ return BLE_NPL_BAD_MUTEX;
+ }
+ }
+
+ return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
+{
+ struct ble_npl_sem_freertos *semaphor = NULL;
+#if OS_MEM_ALLOC
+ if (!os_memblock_from(&ble_freertos_sem_pool,sem->sem)) {
+ sem->sem = os_memblock_get(&ble_freertos_sem_pool);
+ semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+ if (!semaphor) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ memset(semaphor, 0, sizeof(*semaphor));
+ semaphor->handle = xSemaphoreCreateCounting(128, tokens);
+ PLATFORM_BLE_LL_ASSERT(semaphor->handle);
+ }
+#else
+ if(!sem->sem) {
+ sem->sem = malloc(sizeof(struct ble_npl_sem_freertos));
+ semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+ if (!semaphor) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ memset(semaphor, 0, sizeof(*semaphor));
+ semaphor->handle = xSemaphoreCreateCounting(128, tokens);
+ PLATFORM_BLE_LL_ASSERT(semaphor->handle);
+ }
+#endif
+
+ return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_sem_deinit(struct ble_npl_sem *sem)
+{
+ struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+ if (!semaphor) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ PLATFORM_BLE_LL_ASSERT(semaphor->handle);
+ vSemaphoreDelete(semaphor->handle);
+
+#if OS_MEM_ALLOC
+ os_memblock_put(&ble_freertos_sem_pool,semaphor);
+#else
+ free((void *)semaphor);
+#endif
+ sem->sem = NULL;
+
+ return BLE_NPL_OK;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout)
+{
+ BaseType_t woken;
+ BaseType_t ret;
+ struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+ if (!semaphor) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ PLATFORM_BLE_LL_ASSERT(semaphor->handle);
+
+ if (in_isr()) {
+ PLATFORM_BLE_LL_ASSERT(timeout == 0);
+ ret = xSemaphoreTakeFromISR(semaphor->handle, &woken);
+#ifdef ESP_PLATFORM
+ if( woken == pdTRUE ) {
+ portYIELD_FROM_ISR();
+ }
+#else
+ portYIELD_FROM_ISR(woken);
+#endif
+ } else {
+ ret = xSemaphoreTake(semaphor->handle, timeout);
+ }
+
+ return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_sem_release(struct ble_npl_sem *sem)
+{
+ BaseType_t ret;
+ BaseType_t woken;
+ struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+
+ if (!semaphor) {
+ return BLE_NPL_INVALID_PARAM;
+ }
+
+ PLATFORM_BLE_LL_ASSERT(semaphor->handle);
+
+ if (in_isr()) {
+ ret = xSemaphoreGiveFromISR(semaphor->handle, &woken);
+#ifdef ESP_PLATFORM
+ if( woken == pdTRUE ) {
+ portYIELD_FROM_ISR();
+ }
+#else
+ portYIELD_FROM_ISR(woken);
+#endif
+ } else {
+ ret = xSemaphoreGive(semaphor->handle);
+ }
+
+ PLATFORM_BLE_LL_ASSERT(ret == pdPASS);
+ return BLE_NPL_OK;
+}
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+static void
+IRAM_ATTR ble_npl_event_fn_wrapper(void *arg)
+{
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)arg;
+ PLATFORM_BLE_LL_ASSERT(callout);
+
+ if (callout->evq) {
+ ble_npl_eventq_put(callout->evq, &callout->ev);
+ } else {
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event;
+ event->fn(&callout->ev);
+ }
+}
+
+static
+IRAM_ATTR ble_npl_error_t esp_err_to_npl_error(esp_err_t err)
+{
+ switch(err) {
+ case ESP_ERR_INVALID_ARG:
+ return BLE_NPL_INVALID_PARAM;
+
+ case ESP_ERR_INVALID_STATE:
+ return BLE_NPL_EINVAL;
+
+ case ESP_OK:
+ return BLE_NPL_OK;
+
+ default:
+ return BLE_NPL_ERROR;
+ }
+}
+#else
+
+static void
+IRAM_ATTR os_callout_timer_cb(TimerHandle_t timer)
+{
+ struct ble_npl_callout_freertos *callout;
+
+ callout = pvTimerGetTimerID(timer);
+ PLATFORM_BLE_LL_ASSERT(callout);
+
+ if (callout->evq) {
+ ble_npl_eventq_put(callout->evq, &callout->ev);
+ } else {
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event;
+ event->fn(&callout->ev);
+ }
+}
+#endif
+
+void
+IRAM_ATTR npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
+ ble_npl_event_fn *ev_cb, void *ev_arg)
+{
+ struct ble_npl_callout_freertos *callout = NULL;
+
+#if OS_MEM_ALLOC
+ if (!os_memblock_from(&ble_freertos_co_pool, co->co)) {
+ co->co = os_memblock_get(&ble_freertos_co_pool);
+ callout = (struct ble_npl_callout_freertos *)co->co;
+ PLATFORM_BLE_LL_ASSERT(callout);
+
+ memset(callout, 0, sizeof(*callout));
+ ble_npl_event_init(&callout->ev, ev_cb, ev_arg);
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ callout->evq = evq;
+
+ esp_timer_create_args_t create_args = {
+ .callback = ble_npl_event_fn_wrapper,
+ .arg = callout,
+ .name = "nimble_timer"
+ };
+
+ ESP_ERROR_CHECK(esp_timer_create(&create_args, &callout->handle));
+
+#else
+ callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb);
+#endif
+
+ PLATFORM_BLE_LL_ASSERT(callout->handle);
+ } else {
+ callout = (struct ble_npl_callout_freertos *)co->co;
+ PLATFORM_BLE_LL_ASSERT(callout);
+ callout->evq = evq;
+ ble_npl_event_init(&callout->ev, ev_cb, ev_arg);
+ }
+#else
+
+ if(!co->co) {
+ co->co = malloc(sizeof(struct ble_npl_callout_freertos));
+ callout = (struct ble_npl_callout_freertos *)co->co;
+ PLATFORM_BLE_LL_ASSERT(callout);
+
+ memset(callout, 0, sizeof(*callout));
+ ble_npl_event_init(&callout->ev, ev_cb, ev_arg);
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ callout->evq = evq;
+
+ esp_timer_create_args_t create_args = {
+ .callback = ble_npl_event_fn_wrapper,
+ .arg = callout,
+ .name = "nimble_timer"
+ };
+
+ ESP_ERROR_CHECK(esp_timer_create(&create_args, &callout->handle));
+#else
+ callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb);
+#endif
+
+ PLATFORM_BLE_LL_ASSERT(callout->handle);
+ }
+ else {
+ callout = (struct ble_npl_callout_freertos *)co->co;
+ PLATFORM_BLE_LL_ASSERT(callout);
+ callout->evq = evq;
+ ble_npl_event_init(&callout->ev, ev_cb, ev_arg);
+ }
+#endif
+
+}
+
+void
+IRAM_ATTR npl_freertos_callout_deinit(struct ble_npl_callout *co)
+{
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+
+ /* Since we dynamically deinit timers, function can be called for NULL timers. Return for such scenarios */
+ if (!callout) {
+ return;
+ }
+
+ PLATFORM_BLE_LL_ASSERT(callout->handle);
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ if(esp_timer_stop(callout->handle))
+ ESP_LOGW(TAG, "Timer not stopped");
+
+ if(esp_timer_delete(callout->handle))
+ ESP_LOGW(TAG, "Timer not deleted");
+
+#else
+
+ xTimerDelete(callout->handle, portMAX_DELAY);
+ ble_npl_event_deinit(&callout->ev);
+
+#if OS_MEM_ALLOC
+ os_memblock_put(&ble_freertos_co_pool,callout);
+#else
+ free((void *)callout);
+#endif
+
+#endif
+ co->co = NULL;
+ memset(co, 0, sizeof(struct ble_npl_callout));
+}
+
+uint16_t
+IRAM_ATTR npl_freertos_sem_get_count(struct ble_npl_sem *sem)
+{
+ struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
+ return uxSemaphoreGetCount(semaphor->handle);
+}
+
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks)
+{
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ esp_timer_stop(callout->handle);
+
+ return esp_err_to_npl_error(esp_timer_start_once(callout->handle, ticks*1000));
+#else
+
+ BaseType_t woken1, woken2, woken3;
+
+ if (ticks == 0) {
+ ticks = 1;
+ }
+ if (in_isr()) {
+ xTimerStopFromISR(callout->handle, &woken1);
+ xTimerChangePeriodFromISR(callout->handle, ticks, &woken2);
+ xTimerResetFromISR(callout->handle, &woken3);
+#ifdef ESP_PLATFORM
+ if( woken1 == pdTRUE || woken2 == pdTRUE || woken3 == pdTRUE) {
+ portYIELD_FROM_ISR();
+ }
+#else
+ portYIELD_FROM_ISR(woken1 || woken2 || woken3);
+#endif
+ } else {
+ xTimerStop(callout->handle, portMAX_DELAY);
+ xTimerChangePeriod(callout->handle, ticks, portMAX_DELAY);
+ xTimerReset(callout->handle, portMAX_DELAY);
+ }
+
+ return BLE_NPL_OK;
+#endif
+}
+
+void
+IRAM_ATTR npl_freertos_callout_stop(struct ble_npl_callout *co)
+{
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+
+ if (!callout) {
+ return;
+ }
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ esp_timer_stop(callout->handle);
+#else
+ xTimerStop(callout->handle, portMAX_DELAY);
+#endif
+}
+
+bool
+IRAM_ATTR npl_freertos_callout_is_active(struct ble_npl_callout *co)
+{
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ return esp_timer_is_active(callout->handle);
+#else
+ /* Workaround for bug in xTimerIsTimerActive with FreeRTOS V10.2.0, fixed in V10.4.4
+ * See: https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/305
+ * Sometimes xTimerIsTimerActive returns pdTRUE even though the timer has expired, so we double check.
+ */
+ return xTimerIsTimerActive(callout->handle) == pdTRUE &&
+ xTimerGetExpiryTime(callout->handle) > xTaskGetTickCountFromISR();
+#endif
+}
+
+ble_npl_time_t
+IRAM_ATTR npl_freertos_callout_get_ticks(struct ble_npl_callout *co)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ /* Currently, esp_timer does not support an API which gets the expiry time for
+ * current timer.
+ * Returning 0 from here should not cause any effect.
+ * Drawback of this approach is that existing code to reset timer would be called
+ * more often (since the if condition to invoke reset timer would always succeed if
+ * timer is active).
+ */
+
+ return 0;
+#else
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+ return xTimerGetExpiryTime(callout->handle);
+#endif
+}
+
+ble_npl_time_t
+IRAM_ATTR npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co,
+ ble_npl_time_t now)
+{
+ ble_npl_time_t rt;
+ uint32_t exp = 0;
+
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
+ uint64_t expiry = 0;
+ esp_err_t err;
+
+ //Fetch expiry time in microseconds
+ err = esp_timer_get_expiry_time((esp_timer_handle_t)(callout->handle), &expiry);
+ if (err != ESP_OK) {
+ //Error. Could not fetch the expiry time
+ return 0;
+ }
+
+ //Convert microseconds to ticks
+ npl_freertos_time_ms_to_ticks((uint32_t)(expiry / 1000), &exp);
+#else
+ //esp_timer_get_expiry_time() is only available from IDF 5.0 onwards
+ //Set expiry to 0
+ exp = 0;
+#endif //ESP_IDF_VERSION
+#else
+ exp = xTimerGetExpiryTime(callout->handle);
+#endif
+
+ if (exp > now) {
+ rt = exp - now;
+ } else {
+ rt = 0;
+ }
+
+ return rt;
+}
+
+void
+IRAM_ATTR npl_freertos_callout_set_arg(struct ble_npl_callout *co, void *arg)
+{
+ struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
+ struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)callout->ev.event;
+ event->arg = arg;
+}
+
+uint32_t
+IRAM_ATTR npl_freertos_time_get(void)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ return esp_timer_get_time() / 1000;
+#else
+ return xTaskGetTickCountFromISR();
+#endif
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks)
+{
+ uint64_t ticks;
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ ticks = (uint64_t)ms;
+#else
+ ticks = ((uint64_t)ms * configTICK_RATE_HZ) / 1000;
+#endif
+ if (ticks > UINT32_MAX) {
+ return BLE_NPL_EINVAL;
+ }
+
+ *out_ticks = ticks;
+
+ return 0;
+}
+
+ble_npl_error_t
+IRAM_ATTR npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
+{
+ uint64_t ms;
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ ms = ((uint64_t)ticks);
+#else
+ ms = ((uint64_t)ticks * 1000) / configTICK_RATE_HZ;
+#endif
+ if (ms > UINT32_MAX) {
+ return BLE_NPL_EINVAL;
+ }
+
+ *out_ms = ms;
+
+ return 0;
+}
+
+ble_npl_time_t
+IRAM_ATTR npl_freertos_time_ms_to_ticks32(uint32_t ms)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ return ms;
+#else
+ return ms * configTICK_RATE_HZ / 1000;
+#endif
+}
+
+uint32_t
+IRAM_ATTR npl_freertos_time_ticks_to_ms32(ble_npl_time_t ticks)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ return ticks;
+#else
+ return ticks * 1000 / configTICK_RATE_HZ;
+#endif
+}
+
+void
+IRAM_ATTR npl_freertos_time_delay(ble_npl_time_t ticks)
+{
+#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
+ vTaskDelay(ticks / portTICK_PERIOD_MS);
+#else
+ vTaskDelay(ticks);
+#endif
+}
+
+#ifdef ESP_PLATFORM
+#if NIMBLE_CFG_CONTROLLER || CONFIG_NIMBLE_CONTROLLER_MODE
+void
+IRAM_ATTR npl_freertos_hw_set_isr(int irqn, uint32_t addr)
+{
+ //Do nothing
+}
+#endif
+#endif
+
+
+uint8_t hw_critical_state_status = 0;
+
+uint32_t
+IRAM_ATTR npl_freertos_hw_enter_critical(void)
+{
+ ++hw_critical_state_status;
+#ifdef ESP_PLATFORM
+ portENTER_CRITICAL(&ble_port_mutex);
+#else
+ portENTER_CRITICAL();
+#endif
+ return 0;
+}
+
+uint8_t
+IRAM_ATTR npl_freertos_hw_is_in_critical(void)
+{
+ return hw_critical_state_status;
+}
+
+void
+IRAM_ATTR npl_freertos_hw_exit_critical(uint32_t ctx)
+{
+ --hw_critical_state_status;
+#ifdef ESP_PLATFORM
+ portEXIT_CRITICAL(&ble_port_mutex);
+#else
+ portEXIT_CRITICAL();
+#endif
+
+
+}
+
+uint32_t
+IRAM_ATTR npl_freertos_get_time_forever(void)
+{
+ return portMAX_DELAY;
+}
+
+const struct npl_funcs_t npl_funcs_ro = {
+ .p_ble_npl_os_started = npl_freertos_os_started,
+ .p_ble_npl_get_current_task_id = npl_freertos_get_current_task_id,
+ .p_ble_npl_eventq_init = npl_freertos_eventq_init,
+ .p_ble_npl_eventq_deinit = npl_freertos_eventq_deinit,
+ .p_ble_npl_eventq_get = npl_freertos_eventq_get,
+ .p_ble_npl_eventq_put = npl_freertos_eventq_put,
+ .p_ble_npl_eventq_remove = npl_freertos_eventq_remove,
+ .p_ble_npl_event_run = npl_freertos_event_run,
+ .p_ble_npl_eventq_is_empty = npl_freertos_eventq_is_empty,
+ .p_ble_npl_event_init = npl_freertos_event_init,
+ .p_ble_npl_event_deinit = npl_freertos_event_deinit,
+ .p_ble_npl_event_reset = npl_freertos_event_reset,
+ .p_ble_npl_event_is_queued = npl_freertos_event_is_queued,
+ .p_ble_npl_event_get_arg = npl_freertos_event_get_arg,
+ .p_ble_npl_event_set_arg = npl_freertos_event_set_arg,
+ .p_ble_npl_mutex_init = npl_freertos_mutex_init,
+ .p_ble_npl_mutex_deinit = npl_freertos_mutex_deinit,
+ .p_ble_npl_mutex_pend = npl_freertos_mutex_pend,
+ .p_ble_npl_mutex_release = npl_freertos_mutex_release,
+ .p_ble_npl_sem_init = npl_freertos_sem_init,
+ .p_ble_npl_sem_deinit = npl_freertos_sem_deinit,
+ .p_ble_npl_sem_pend = npl_freertos_sem_pend,
+ .p_ble_npl_sem_release = npl_freertos_sem_release,
+ .p_ble_npl_sem_get_count = npl_freertos_sem_get_count,
+ .p_ble_npl_callout_init = npl_freertos_callout_init,
+ .p_ble_npl_callout_reset = npl_freertos_callout_reset,
+ .p_ble_npl_callout_stop = npl_freertos_callout_stop,
+ .p_ble_npl_callout_deinit = npl_freertos_callout_deinit,
+ .p_ble_npl_callout_mem_reset = npl_freertos_callout_mem_reset,
+ .p_ble_npl_callout_is_active = npl_freertos_callout_is_active,
+ .p_ble_npl_callout_get_ticks = npl_freertos_callout_get_ticks,
+ .p_ble_npl_callout_remaining_ticks = npl_freertos_callout_remaining_ticks,
+ .p_ble_npl_callout_set_arg = npl_freertos_callout_set_arg,
+ .p_ble_npl_time_get = npl_freertos_time_get,
+ .p_ble_npl_time_ms_to_ticks = npl_freertos_time_ms_to_ticks,
+ .p_ble_npl_time_ticks_to_ms = npl_freertos_time_ticks_to_ms,
+ .p_ble_npl_time_ms_to_ticks32 = npl_freertos_time_ms_to_ticks32,
+ .p_ble_npl_time_ticks_to_ms32 = npl_freertos_time_ticks_to_ms32,
+ .p_ble_npl_time_delay = npl_freertos_time_delay,
+#if NIMBLE_CFG_CONTROLLER || CONFIG_NIMBLE_CONTROLLER_MODE
+ .p_ble_npl_hw_set_isr = npl_freertos_hw_set_isr,
+#endif
+ .p_ble_npl_hw_enter_critical = npl_freertos_hw_enter_critical,
+ .p_ble_npl_hw_exit_critical = npl_freertos_hw_exit_critical,
+ .p_ble_npl_get_time_forever = npl_freertos_get_time_forever,
+ .p_ble_npl_hw_is_in_critical = npl_freertos_hw_is_in_critical
+};
+
+struct npl_funcs_t *npl_funcs = NULL;
+
+struct npl_funcs_t * npl_freertos_funcs_get(void)
+{
+ return npl_funcs;
+}
+
+void npl_freertos_funcs_init(void)
+{
+ npl_funcs = (struct npl_funcs_t *)malloc(sizeof(struct npl_funcs_t));
+ if(!npl_funcs) {
+ printf("npl funcs init failed\n");
+ assert(0);
+ }
+ memcpy(npl_funcs, &npl_funcs_ro, sizeof(struct npl_funcs_t));
+}
+
+int npl_freertos_mempool_init(void)
+{
+ int rc = -1;
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+ ble_freertos_ev_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos)) * sizeof(os_membuf_t));
+ if(!ble_freertos_ev_buf) {
+ goto _error;
+ }
+ ble_freertos_evq_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EVQ_COUNT, sizeof (struct ble_npl_eventq_freertos)) * sizeof(os_membuf_t));
+ if(!ble_freertos_evq_buf) {
+ goto _error;
+ }
+ ble_freertos_co_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_CO_COUNT, sizeof (struct ble_npl_callout_freertos)) * sizeof(os_membuf_t));
+ if(!ble_freertos_co_buf) {
+ goto _error;
+ }
+ ble_freertos_sem_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_SEM_COUNT, sizeof (struct ble_npl_sem_freertos)) * sizeof(os_membuf_t));
+ if(!ble_freertos_sem_buf) {
+ goto _error;
+ }
+ ble_freertos_mutex_buf = malloc( OS_MEMPOOL_SIZE(BLE_TOTAL_MUTEX_COUNT, sizeof (struct ble_npl_mutex_freertos)) * sizeof(os_membuf_t));
+ if(!ble_freertos_mutex_buf) {
+ goto _error;
+ }
+
+#endif
+
+ rc = os_mempool_init(&ble_freertos_ev_pool, BLE_TOTAL_EV_COUNT,
+ sizeof (struct ble_npl_event_freertos), ble_freertos_ev_buf,
+ "ble_freertos_ev_pool");
+ if(rc != 0) {
+ goto _error;
+ }
+
+ rc = os_mempool_init(&ble_freertos_evq_pool, BLE_TOTAL_EVQ_COUNT,
+ sizeof (struct ble_npl_eventq_freertos), ble_freertos_evq_buf,
+ "ble_freertos_evq_pool");
+ if(rc != 0) {
+ goto _error;
+ }
+
+ rc = os_mempool_init(&ble_freertos_co_pool, BLE_TOTAL_CO_COUNT,
+ sizeof (struct ble_npl_callout_freertos), ble_freertos_co_buf,
+ "ble_freertos_co_pool");
+ if(rc != 0) {
+ goto _error;
+ }
+
+ rc = os_mempool_init(&ble_freertos_sem_pool, BLE_TOTAL_SEM_COUNT,
+ sizeof (struct ble_npl_sem_freertos), ble_freertos_sem_buf,
+ "ble_freertos_sem_pool");
+ if(rc != 0) {
+ goto _error;
+ }
+
+ rc = os_mempool_init(&ble_freertos_mutex_pool, BLE_TOTAL_MUTEX_COUNT,
+ sizeof (struct ble_npl_mutex_freertos), ble_freertos_mutex_buf,
+ "ble_freertos_mutex_pool");
+ if(rc == 0) {
+ return rc;
+ }
+_error:
+
+#if SOC_ESP_NIMBLE_CONTROLLER
+ if(ble_freertos_ev_buf) {
+ free(ble_freertos_ev_buf);
+ }
+ if(ble_freertos_evq_buf) {
+ free(ble_freertos_evq_buf);
+ }
+ if(ble_freertos_co_buf) {
+ free(ble_freertos_co_buf);
+ }
+ if(ble_freertos_sem_buf) {
+ free(ble_freertos_sem_buf);
+ }
+ if(ble_freertos_mutex_buf) {
+ free(ble_freertos_mutex_buf);
+ }
+ return -1;
+#else
+
+ PLATFORM_BLE_LL_ASSERT(rc == 0);
+ return rc;
+#endif
+}
+
+void npl_freertos_mempool_deinit(void)
+{
+#if SOC_ESP_NIMBLE_CONTROLLER
+ if(ble_freertos_ev_buf) {
+ free(ble_freertos_ev_buf);
+ }
+ if(ble_freertos_evq_buf) {
+ free(ble_freertos_evq_buf);
+ }
+ if(ble_freertos_co_buf) {
+ free(ble_freertos_co_buf);
+ }
+ if(ble_freertos_sem_buf) {
+ free(ble_freertos_sem_buf);
+ }
+ if(ble_freertos_mutex_buf) {
+ free(ble_freertos_mutex_buf);
+ }
+#endif
+}
+
+void npl_freertos_funcs_deinit(void)
+{
+ if (npl_funcs) {
+ free(npl_funcs);
+ }
+ npl_funcs = NULL;
+}
+
+#else // Not using MEM pools
+
#include
#include
#include
@@ -27,7 +1346,9 @@
#include "freertos/portable.h"
#include "esp_log.h"
portMUX_TYPE ble_port_mutex = portMUX_INITIALIZER_UNLOCKED;
+# if CONFIG_BT_NIMBLE_USE_ESP_TIMER
static const char *TAG = "Timer";
+# endif
#else
#include "nrf.h"
@@ -450,6 +1771,10 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq
void
npl_freertos_callout_deinit(struct ble_npl_callout *co)
{
+ if (!co->handle) {
+ return;
+ }
+
#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
if(esp_timer_stop(co->handle))
ESP_LOGW(TAG, "Timer not stopped");
@@ -457,9 +1782,8 @@ npl_freertos_callout_deinit(struct ble_npl_callout *co)
if(esp_timer_delete(co->handle))
ESP_LOGW(TAG, "Timer not deleted");
#else
- if (co->handle) {
- xTimerDelete(co->handle, portMAX_DELAY);
- }
+ xTimerDelete(co->handle, portMAX_DELAY);
+ ble_npl_event_deinit(&co->ev);
#endif
memset(co, 0, sizeof(struct ble_npl_callout));
}
@@ -503,6 +1827,9 @@ npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks)
void
npl_freertos_callout_stop(struct ble_npl_callout *co)
{
+ if (!co->handle) {
+ return;
+ }
#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
esp_timer_stop(co->handle);
#else
@@ -610,3 +1937,5 @@ npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
return 0;
}
+
+#endif // CONFIG_NIMBLE_STACK_USE_MEM_POOLS
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h b/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h
index 03335d8ee..8214e1d9b 100644
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimconfig.h
@@ -25,12 +25,38 @@
/** @brief Uncomment to set the default allocation size (bytes) for each attribute if\n
* not specified when the constructor is called. This is also the size used when a remote\n
- * characteristic or descriptor is constructed before a value is read/notifed.\n
+ * characteristic or descriptor is constructed before a value is read/notified.\n
* Increasing this will reduce reallocations but increase memory footprint.\n
* Default value is 20. Range: 1 : 512 (BLE_ATT_ATTR_MAX_LEN)
*/
// #define CONFIG_NIMBLE_CPP_ATT_VALUE_INIT_LENGTH 20
+
+/****************************************************
+ * Extended advertising settings *
+ * For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
+ ***************************************************/
+
+/** @brief Un-comment to enable extended advertising */
+// #define CONFIG_BT_NIMBLE_EXT_ADV 1
+
+/** @brief Un-comment to set the max number of extended advertising instances (Range: 0 - 4) */
+// #define CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES 1
+
+/** @brief Un-comment to set the max extended advertising data size (Range: 31 - 1650) */
+// #define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN 251
+
+/** @brief Un-comment to enable periodic advertising */
+// #define CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV 1
+
+/** @brief Un-comment to change the maximum number of periodically synced devices */
+// #define CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS 1
+
+/****************************************************
+ * END For use with ESP32C3, ESP32S3, ESP32H2 ONLY! *
+ ***************************************************/
+
+
/** @brief Un-comment to change the default MTU size */
// #define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 255
@@ -49,11 +75,6 @@
*/
// #define CONFIG_NIMBLE_CPP_LOG_LEVEL 0
- /** @brief Un-comment to use timestamps with characteristic / descriptor values
- * If not enabled the `::get/readValue()` calls with a timestamp parameter will set the timestamp to 0.
- */
-// #define NIMBLE_ATT_VALUE_TIMESTAMP_ENABLED
-
/** @brief Un-comment to see NimBLE host return codes as text debug log messages.
* Uses approx. 7kB of flash memory.
*/
@@ -64,10 +85,10 @@
*/
// #define CONFIG_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
-/** @brief Un-comment to see advertisment types as text while scanning in debug log messages.
+/** @brief Un-comment to see advertisement types as text while scanning in debug log messages.
* Uses approx. 250 bytes of flash memory.
*/
-// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISMENT_TYPE_TEXT
+// #define CONFIG_NIMBLE_CPP_ENABLE_ADVERTISEMENT_TYPE_TEXT
/** @brief Un-comment to change the default GAP appearance */
// #define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0
@@ -116,7 +137,13 @@
// #define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
/** @brief Un-comment to change the stack size for the NimBLE host task */
-// #define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
+// #define CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE 4096
+
+/**
+ * @brief Un-comment to use memory pools for stack operations
+ * @details this will use slightly more RAM but may provide more stability.
+ */
+// #define CONFIG_NIMBLE_STACK_USE_MEM_POOLS 1
/**********************************
End Arduino user-config
@@ -143,8 +170,8 @@
#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0
#endif
-#ifndef CONFIG_BT_NIMBLE_TASK_STACK_SIZE
-#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE 4096
+#ifndef CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE
+#define CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE 4096
#endif
#ifndef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
@@ -187,6 +214,9 @@
#define CONFIG_BT_NIMBLE_LOG_LEVEL 5
#endif
+#ifndef CONFIG_NIMBLE_STACK_USE_MEM_POOLS
+#define CONFIG_NIMBLE_STACK_USE_MEM_POOLS 0
+#endif
/** @brief Set if CCCD's and bond data should be stored in NVS */
#define CONFIG_BT_NIMBLE_NVS_PERSIST 0
@@ -207,7 +237,11 @@
#define CONFIG_BT_NIMBLE_ACL_BUF_SIZE 255
/** @brief HCI Event Buffer size */
-#define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 70
+#if CONFIG_BT_NIMBLE_EXT_ADV || CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV
+# define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 257
+#else
+# define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 70
+#endif
/** @brief Number of high priority HCI event buffers */
#define CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT 30
@@ -229,6 +263,10 @@
#define CONFIG_BT_ENABLED
#endif
+#ifndef CONFIG_BT_NIMBLE_ENABLED
+#define CONFIG_BT_NIMBLE_ENABLED 1
+#endif
+
#ifdef ESP_PLATFORM
#ifndef CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY
@@ -249,6 +287,31 @@
#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
#define CONFIG_IDF_TARGET_ESP32 1
#endif
+
+#if CONFIG_BT_NIMBLE_EXT_ADV || CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV
+# if defined(CONFIG_IDF_TARGET_ESP32)
+# error Extended advertising is not supported on ESP32.
+# endif
+#endif
+#endif
+
+#if CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV && !CONFIG_BT_NIMBLE_EXT_ADV
+# error Extended advertising must be enabled to use periodic advertising.
+#endif
+
+/* Must have max instances and data length set if extended advertising is enabled */
+#if CONFIG_BT_NIMBLE_EXT_ADV
+# if !defined(CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES)
+# define CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES 1
+# endif
+# if !defined(CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN)
+# define CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN 251
+# endif
+#endif
+
+/* Must set max number of syncs if periodic advertising is enabled */
+#if CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV && !defined(CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS)
+# define CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS 1
#endif
/* Cannot use client without scan */
diff --git a/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md b/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
index ec9cfcc80..24048605f 100644
--- a/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
+++ b/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
@@ -24,15 +24,3 @@ Change in nimconfig.h
`#define CONFIG_BT_NIMBLE_NVS_PERSIST 1`
to
`#define CONFIG_BT_NIMBLE_NVS_PERSIST 0`
-
-and line 249 from
-
-`
-#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
-`
-
-to
-
-`
-#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
-`
From cdc00f20767b045f815394aff8f44a57f5fb2a02 Mon Sep 17 00:00:00 2001
From: Jason2866 <24528715+Jason2866@users.noreply.github.com>
Date: Thu, 18 Aug 2022 10:08:53 +0200
Subject: [PATCH 2/3] missing PSRAM fix
---
.../nimble/esp_port/port/src/esp_nimble_mem.c | 44 --------------
.../esp_port/port/src/esp_nimble_mem.cpp | 53 ++++++++++++++++
.../NimBLE-Arduino/tasmota_lib_changes.md | 60 +++++++++++++++++++
3 files changed, 113 insertions(+), 44 deletions(-)
delete mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c
create mode 100644 lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.cpp
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c
deleted file mode 100644
index 7e1899db6..000000000
--- a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#ifdef ESP_PLATFORM
-
-#include "esp_attr.h"
-#include "esp_heap_caps.h"
-#include "nimconfig.h"
-#include "../include/esp_nimble_mem.h"
-
-IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
-{
-#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
- return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
- return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
-#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
- return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-#else
- return malloc(size);
-#endif
-}
-
-IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
-{
-#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
- return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
- return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
-#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
- return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
-#else
- return calloc(n, size);
-#endif
-}
-
-IRAM_ATTR void nimble_platform_mem_free(void *ptr)
-{
- heap_caps_free(ptr);
-}
-#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.cpp b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.cpp
new file mode 100644
index 000000000..407091c7f
--- /dev/null
+++ b/lib/libesp32_div/NimBLE-Arduino/src/nimble/esp_port/port/src/esp_nimble_mem.cpp
@@ -0,0 +1,53 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef ESP_PLATFORM
+
+#include "esp_attr.h"
+#include "esp_heap_caps.h"
+#include "nimconfig.h"
+#include "../include/esp_nimble_mem.h"
+
+//Tasmota Patch
+extern void *special_malloc(uint32_t size);
+extern void *special_calloc(size_t num, size_t size);
+
+
+extern "C" {
+IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
+{
+ return special_malloc((uint32_t)size);
+// #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
+// return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
+// return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
+// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
+// return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+// #else
+// return malloc(size);
+// #endif
+}
+
+IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
+{
+ return special_calloc(n,size);
+// #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
+// return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
+// return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
+// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
+// return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+// #else
+// return calloc(n, size);
+// #endif
+}
+
+IRAM_ATTR void nimble_platform_mem_free(void *ptr)
+{
+ heap_caps_free(ptr);
+}
+} //extern "C"
+#endif
diff --git a/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md b/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
index 24048605f..1455c8138 100644
--- a/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
+++ b/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
@@ -24,3 +24,63 @@ Change in nimconfig.h
`#define CONFIG_BT_NIMBLE_NVS_PERSIST 1`
to
`#define CONFIG_BT_NIMBLE_NVS_PERSIST 0`
+
+Rename /src/nimble/esp_port/port/src/esp_nimble_mem.c to esp_nimble_mem.c
+
+and replace all in the file with
+
+```
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef ESP_PLATFORM
+
+#include "esp_attr.h"
+#include "esp_heap_caps.h"
+#include "nimconfig.h"
+#include "../include/esp_nimble_mem.h"
+
+//Tasmota Patch
+extern void *special_malloc(uint32_t size);
+extern void *special_calloc(size_t num, size_t size);
+
+
+extern "C" {
+IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
+{
+ return special_malloc((uint32_t)size);
+// #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
+// return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
+// return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
+// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
+// return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+// #else
+// return malloc(size);
+// #endif
+}
+
+IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
+{
+ return special_calloc(n,size);
+// #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
+// return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
+// return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
+// #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
+// return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+// #else
+// return calloc(n, size);
+// #endif
+}
+
+IRAM_ATTR void nimble_platform_mem_free(void *ptr)
+{
+ heap_caps_free(ptr);
+}
+} //extern "C"
+#endif
+```
From 39d14ab6333a8ad8737fb71a721d05d6b8c269de Mon Sep 17 00:00:00 2001
From: Jason2866 <24528715+Jason2866@users.noreply.github.com>
Date: Thu, 18 Aug 2022 10:11:53 +0200
Subject: [PATCH 3/3] cpp
---
lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md b/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
index 1455c8138..c10753fcf 100644
--- a/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
+++ b/lib/libesp32_div/NimBLE-Arduino/tasmota_lib_changes.md
@@ -25,7 +25,7 @@ Change in nimconfig.h
to
`#define CONFIG_BT_NIMBLE_NVS_PERSIST 0`
-Rename /src/nimble/esp_port/port/src/esp_nimble_mem.c to esp_nimble_mem.c
+Rename /src/nimble/esp_port/port/src/esp_nimble_mem.c to esp_nimble_mem.cpp
and replace all in the file with