From ce41f64665a25af91d2aef1259821747f242e1e1 Mon Sep 17 00:00:00 2001 From: h2zero Date: Wed, 4 Mar 2026 14:27:16 -0700 Subject: [PATCH] Update to Mynewt-NimBLE version 1.9 This will update to the mainline Mynewt-nimble repo and pull in esp device support from the esp-nimble fork. Doing this allows for simplified maintenance and avoids having too much additional/unsupported upstream changes. This also allows for using more recent NimBLE versions and being able to pull in important updates that are not in esp-nimble. --- src/NimBLEUtils.cpp | 8 + src/nimble/CODING_STANDARDS.md | 267 -- src/nimble/LICENSE | 3 + src/nimble/NOTICE | 3 +- src/nimble/RELEASE_NOTES.md | 9 +- .../esp_port/esp-hci/src/esp_nimble_hci.c | 3 + .../esp_ipc/src/hci_esp_ipc.c | 2 +- .../esp_ipc_legacy/src/hci_esp_ipc_legacy.c | 5 +- .../tinycrypt/include/tinycrypt/cbc_mode.h | 2 +- .../tinycrypt/include/tinycrypt/ccm_mode.h | 2 +- .../tinycrypt/include/tinycrypt/cmac_mode.h | 2 +- .../tinycrypt/include/tinycrypt/ctr_mode.h | 4 +- .../tinycrypt/include/tinycrypt/ctr_prng.h | 2 +- .../ext/tinycrypt/include/tinycrypt/ecc_dh.h | 2 +- .../ext/tinycrypt/include/tinycrypt/ecc_dsa.h | 2 +- .../ext/tinycrypt/include/tinycrypt/hmac.h | 2 +- .../tinycrypt/include/tinycrypt/hmac_prng.h | 4 +- src/nimble/ext/tinycrypt/src/aes_decrypt.c | 6 +- src/nimble/ext/tinycrypt/src/aes_encrypt.c | 6 +- src/nimble/ext/tinycrypt/src/cbc_mode.c | 6 +- src/nimble/ext/tinycrypt/src/ccm_mode.c | 6 +- src/nimble/ext/tinycrypt/src/cmac_mode.c | 8 +- src/nimble/ext/tinycrypt/src/ctr_mode.c | 6 +- src/nimble/ext/tinycrypt/src/ctr_prng.c | 6 +- src/nimble/ext/tinycrypt/src/ecc.c | 4 +- src/nimble/ext/tinycrypt/src/ecc_dh.c | 6 +- src/nimble/ext/tinycrypt/src/ecc_dsa.c | 6 +- src/nimble/ext/tinycrypt/src/hmac.c | 6 +- src/nimble/ext/tinycrypt/src/hmac_prng.c | 8 +- src/nimble/ext/tinycrypt/src/sha256.c | 6 +- src/nimble/ext/tinycrypt/src/utils.c | 4 +- .../controller/include/controller/ble_ll.h | 99 +- .../include/controller/ble_ll_adv.h | 10 +- .../include/controller/ble_ll_conn.h | 18 +- .../controller/include/controller/ble_ll_cs.h | 51 + .../include/controller/ble_ll_ctrl.h | 6 +- .../include/controller/ble_ll_iso.h | 76 +- .../include/controller/ble_ll_iso_big.h | 6 - .../include/controller/ble_ll_isoal.h | 56 +- .../include/controller/ble_ll_resolv.h | 11 + .../include/controller/ble_ll_scan.h | 25 +- .../include/controller/ble_ll_sched.h | 2 +- .../include/controller/ble_ll_sync.h | 2 +- .../include/controller/ble_ll_tmr.h | 8 + .../controller/include/controller/ble_phy.h | 3 + src/nimble/nimble/controller/src/ble_ll.c | 70 +- src/nimble/nimble/controller/src/ble_ll_adv.c | 495 ++- .../nimble/controller/src/ble_ll_conn.c | 259 +- .../nimble/controller/src/ble_ll_conn_hci.c | 154 +- .../nimble/controller/src/ble_ll_conn_priv.h | 15 +- .../nimble/controller/src/ble_ll_crypto.c | 14 +- src/nimble/nimble/controller/src/ble_ll_cs.c | 123 + .../nimble/controller/src/ble_ll_cs_drbg.c | 686 +++ .../controller/src/ble_ll_cs_drbg_priv.h | 125 + .../nimble/controller/src/ble_ll_ctrl.c | 285 +- src/nimble/nimble/controller/src/ble_ll_dtm.c | 32 +- src/nimble/nimble/controller/src/ble_ll_hci.c | 162 +- .../nimble/controller/src/ble_ll_hci_ev.c | 14 +- .../controller/src/ble_ll_hci_supp_cmd.c | 44 +- .../nimble/controller/src/ble_ll_hci_vs.c | 72 +- src/nimble/nimble/controller/src/ble_ll_iso.c | 428 +- .../nimble/controller/src/ble_ll_iso_big.c | 495 ++- .../nimble/controller/src/ble_ll_isoal.c | 547 ++- src/nimble/nimble/controller/src/ble_ll_pdu.c | 8 +- .../nimble/controller/src/ble_ll_priv.h | 2 +- .../nimble/controller/src/ble_ll_rand.c | 5 +- .../nimble/controller/src/ble_ll_resolv.c | 134 +- .../nimble/controller/src/ble_ll_rfmgmt.c | 6 +- .../nimble/controller/src/ble_ll_scan.c | 162 +- .../nimble/controller/src/ble_ll_scan_aux.c | 123 +- .../nimble/controller/src/ble_ll_sched.c | 43 +- .../nimble/controller/src/ble_ll_sync.c | 82 +- .../nimble/controller/src/ble_ll_trace.c | 7 +- .../nimble/controller/src/ble_ll_utils.c | 6 +- .../nimble/controller/src/ble_ll_whitelist.c | 6 +- src/nimble/nimble/drivers/nrf51/src/ble_hw.c | 8 +- src/nimble/nimble/drivers/nrf51/src/ble_phy.c | 6 +- .../nimble/drivers/nrf5x/include/ble/xcvr.h | 3 - src/nimble/nimble/drivers/nrf5x/src/ble_hw.c | 10 +- src/nimble/nimble/drivers/nrf5x/src/ble_phy.c | 180 +- .../nimble/drivers/nrf5x/src/ble_phy_trace.c | 6 +- .../nimble/drivers/nrf5x/src/nrf52/phy.c | 33 +- .../nimble/drivers/nrf5x/src/nrf52/phy_ppi.h | 3 - .../nimble/drivers/nrf5x/src/nrf53/phy.c | 317 -- .../nimble/drivers/nrf5x/src/nrf53/phy_ppi.h | 159 - .../nimble/drivers/nrf5x/src/phy_priv.h | 4 +- .../nimble/host/include/host/ble_aes_ccm.h | 6 - src/nimble/nimble/host/include/host/ble_att.h | 37 +- src/nimble/nimble/host/include/host/ble_cs.h | 57 + .../nimble/host/include/host/ble_eddystone.h | 51 +- .../nimble/host/include/host/ble_esp_gap.h | 306 -- .../nimble/host/include/host/ble_esp_gatt.h | 24 - .../nimble/host/include/host/ble_esp_hs.h | 56 - src/nimble/nimble/host/include/host/ble_gap.h | 1528 ++----- .../nimble/host/include/host/ble_gatt.h | 506 +-- src/nimble/nimble/host/include/host/ble_hs.h | 21 +- .../nimble/host/include/host/ble_hs_adv.h | 291 +- .../nimble/host/include/host/ble_hs_hci.h | 2 +- .../nimble/host/include/host/ble_hs_log.h | 21 +- src/nimble/nimble/host/include/host/ble_iso.h | 509 +++ .../nimble/host/include/host/ble_l2cap.h | 21 +- src/nimble/nimble/host/include/host/ble_sm.h | 240 +- .../nimble/host/include/host/ble_store.h | 464 ++- .../nimble/host/include/host/ble_uuid.h | 37 +- .../nimble/host/mesh/include/mesh/access.h | 628 --- .../nimble/host/mesh/include/mesh/atomic.h | 409 -- .../nimble/host/mesh/include/mesh/cdb.h | 265 -- .../nimble/host/mesh/include/mesh/cfg.h | 491 --- .../nimble/host/mesh/include/mesh/cfg_cli.h | 345 -- .../nimble/host/mesh/include/mesh/cfg_srv.h | 40 - .../nimble/host/mesh/include/mesh/glue.h | 699 ---- .../host/mesh/include/mesh/health_cli.h | 77 - .../host/mesh/include/mesh/health_srv.h | 100 - .../nimble/host/mesh/include/mesh/heartbeat.h | 123 - .../nimble/host/mesh/include/mesh/main.h | 589 --- .../nimble/host/mesh/include/mesh/mesh.h | 33 - .../nimble/host/mesh/include/mesh/model_cli.h | 49 - .../nimble/host/mesh/include/mesh/model_srv.h | 67 - .../nimble/host/mesh/include/mesh/msg.h | 225 - .../nimble/host/mesh/include/mesh/porting.h | 27 - .../nimble/host/mesh/include/mesh/proxy.h | 43 - .../nimble/host/mesh/include/mesh/slist.h | 468 --- .../nimble/host/mesh/include/mesh/testing.h | 105 - src/nimble/nimble/host/mesh/src/access.c | 1317 ------ src/nimble/nimble/host/mesh/src/access.h | 88 - src/nimble/nimble/host/mesh/src/adv.c | 261 -- src/nimble/nimble/host/mesh/src/adv.h | 131 - src/nimble/nimble/host/mesh/src/adv_ext.c | 345 -- src/nimble/nimble/host/mesh/src/adv_legacy.c | 257 -- src/nimble/nimble/host/mesh/src/aes-ccm.c | 229 - src/nimble/nimble/host/mesh/src/app_keys.c | 722 ---- src/nimble/nimble/host/mesh/src/app_keys.h | 68 - src/nimble/nimble/host/mesh/src/atomic.h | 409 -- src/nimble/nimble/host/mesh/src/beacon.c | 476 --- src/nimble/nimble/host/mesh/src/beacon.h | 27 - src/nimble/nimble/host/mesh/src/cdb.c | 1147 ----- src/nimble/nimble/host/mesh/src/cdb_priv.h | 12 - src/nimble/nimble/host/mesh/src/cfg.c | 393 -- src/nimble/nimble/host/mesh/src/cfg.h | 10 - src/nimble/nimble/host/mesh/src/cfg_cli.c | 2714 ------------ src/nimble/nimble/host/mesh/src/cfg_srv.c | 2649 ------------ src/nimble/nimble/host/mesh/src/crypto.c | 609 --- src/nimble/nimble/host/mesh/src/crypto.h | 171 - src/nimble/nimble/host/mesh/src/foundation.h | 137 - src/nimble/nimble/host/mesh/src/friend.c | 1791 -------- src/nimble/nimble/host/mesh/src/friend.h | 56 - src/nimble/nimble/host/mesh/src/glue.c | 1041 ----- src/nimble/nimble/host/mesh/src/health_cli.c | 529 --- src/nimble/nimble/host/mesh/src/health_srv.c | 479 --- src/nimble/nimble/host/mesh/src/heartbeat.c | 469 --- src/nimble/nimble/host/mesh/src/heartbeat.h | 43 - src/nimble/nimble/host/mesh/src/light_model.c | 65 - src/nimble/nimble/host/mesh/src/light_model.h | 19 - src/nimble/nimble/host/mesh/src/lpn.c | 1101 ----- src/nimble/nimble/host/mesh/src/lpn.h | 59 - src/nimble/nimble/host/mesh/src/mesh.c | 420 -- src/nimble/nimble/host/mesh/src/mesh_priv.h | 53 - src/nimble/nimble/host/mesh/src/model_cli.c | 307 -- src/nimble/nimble/host/mesh/src/model_srv.c | 286 -- src/nimble/nimble/host/mesh/src/msg.c | 89 - src/nimble/nimble/host/mesh/src/net.c | 1227 ------ src/nimble/nimble/host/mesh/src/net.h | 328 -- src/nimble/nimble/host/mesh/src/pb_adv.c | 922 ---- src/nimble/nimble/host/mesh/src/pb_gatt.c | 174 - src/nimble/nimble/host/mesh/src/pb_gatt_srv.c | 465 --- src/nimble/nimble/host/mesh/src/pb_gatt_srv.h | 31 - src/nimble/nimble/host/mesh/src/prov.c | 463 --- src/nimble/nimble/host/mesh/src/prov.h | 177 - src/nimble/nimble/host/mesh/src/prov_bearer.h | 116 - src/nimble/nimble/host/mesh/src/prov_device.c | 641 --- src/nimble/nimble/host/mesh/src/provisioner.c | 756 ---- src/nimble/nimble/host/mesh/src/provisioner.h | 10 - src/nimble/nimble/host/mesh/src/proxy.c | 1576 ------- src/nimble/nimble/host/mesh/src/proxy.h | 51 - src/nimble/nimble/host/mesh/src/proxy_msg.c | 235 -- src/nimble/nimble/host/mesh/src/proxy_msg.h | 67 - src/nimble/nimble/host/mesh/src/proxy_srv.c | 1020 ----- src/nimble/nimble/host/mesh/src/rpl.c | 385 -- src/nimble/nimble/host/mesh/src/rpl.h | 32 - src/nimble/nimble/host/mesh/src/settings.c | 216 - src/nimble/nimble/host/mesh/src/settings.h | 26 - src/nimble/nimble/host/mesh/src/shell.c | 3690 ----------------- src/nimble/nimble/host/mesh/src/shell.h | 12 - src/nimble/nimble/host/mesh/src/subnet.c | 889 ---- src/nimble/nimble/host/mesh/src/subnet.h | 206 - src/nimble/nimble/host/mesh/src/testing.c | 210 - src/nimble/nimble/host/mesh/src/testing.h | 23 - src/nimble/nimble/host/mesh/src/transport.c | 1937 --------- src/nimble/nimble/host/mesh/src/transport.h | 106 - .../gap/include/services/gap/ble_svc_gap.h | 14 +- .../host/services/gap/src/ble_svc_gap.c | 74 - .../gatt/include/services/gatt/ble_svc_gatt.h | 18 +- .../host/services/gatt/src/ble_svc_gatt.c | 116 +- src/nimble/nimble/host/src/ble_aes_ccm.c | 42 +- src/nimble/nimble/host/src/ble_att.c | 110 +- src/nimble/nimble/host/src/ble_att_clt.c | 141 +- src/nimble/nimble/host/src/ble_att_cmd.c | 7 +- src/nimble/nimble/host/src/ble_att_cmd_priv.h | 17 +- src/nimble/nimble/host/src/ble_att_priv.h | 23 +- src/nimble/nimble/host/src/ble_att_svr.c | 620 +-- .../nimble/host/src/ble_audio_codec_priv.h | 25 + src/nimble/nimble/host/src/ble_cs.c | 736 ++++ src/nimble/nimble/host/src/ble_cs_priv.h | 31 + src/nimble/nimble/host/src/ble_dtm.c | 6 +- src/nimble/nimble/host/src/ble_ead.c | 2 +- src/nimble/nimble/host/src/ble_eatt.c | 180 +- src/nimble/nimble/host/src/ble_eatt_priv.h | 1 - src/nimble/nimble/host/src/ble_gap.c | 3022 ++------------ src/nimble/nimble/host/src/ble_gap_priv.h | 29 +- src/nimble/nimble/host/src/ble_gatt_priv.h | 66 +- src/nimble/nimble/host/src/ble_gattc.c | 504 +-- .../nimble/host/src/ble_gattc_cache_priv.h | 148 +- src/nimble/nimble/host/src/ble_gatts.c | 1196 +----- src/nimble/nimble/host/src/ble_gatts_lcl.c | 7 +- src/nimble/nimble/host/src/ble_hs.c | 115 +- src/nimble/nimble/host/src/ble_hs_adv.c | 194 +- src/nimble/nimble/host/src/ble_hs_cfg.c | 2 - src/nimble/nimble/host/src/ble_hs_conn.c | 17 +- src/nimble/nimble/host/src/ble_hs_conn_priv.h | 19 +- src/nimble/nimble/host/src/ble_hs_flow.c | 8 +- src/nimble/nimble/host/src/ble_hs_flow_priv.h | 2 +- src/nimble/nimble/host/src/ble_hs_hci.c | 319 +- src/nimble/nimble/host/src/ble_hs_hci_cmd.c | 53 +- src/nimble/nimble/host/src/ble_hs_hci_evt.c | 648 +-- src/nimble/nimble/host/src/ble_hs_hci_priv.h | 11 - src/nimble/nimble/host/src/ble_hs_hci_util.c | 85 +- src/nimble/nimble/host/src/ble_hs_id.c | 8 +- src/nimble/nimble/host/src/ble_hs_id_priv.h | 1 + src/nimble/nimble/host/src/ble_hs_log.c | 2 - src/nimble/nimble/host/src/ble_hs_mbuf.c | 1 + src/nimble/nimble/host/src/ble_hs_mqueue.c | 12 +- .../nimble/host/src/ble_hs_periodic_sync.c | 3 - src/nimble/nimble/host/src/ble_hs_priv.h | 7 +- src/nimble/nimble/host/src/ble_hs_pvcy.c | 207 +- src/nimble/nimble/host/src/ble_hs_pvcy_priv.h | 5 +- src/nimble/nimble/host/src/ble_hs_resolv.c | 8 +- src/nimble/nimble/host/src/ble_hs_startup.c | 53 +- src/nimble/nimble/host/src/ble_hs_stop.c | 21 +- src/nimble/nimble/host/src/ble_iso.c | 981 +++++ src/nimble/nimble/host/src/ble_iso_priv.h | 47 + src/nimble/nimble/host/src/ble_l2cap.c | 368 +- src/nimble/nimble/host/src/ble_l2cap_coc.c | 180 +- .../nimble/host/src/ble_l2cap_coc_priv.h | 33 +- src/nimble/nimble/host/src/ble_l2cap_priv.h | 36 +- src/nimble/nimble/host/src/ble_l2cap_sig.c | 603 +-- .../nimble/host/src/ble_l2cap_sig_cmd.c | 16 +- .../nimble/host/src/ble_l2cap_sig_priv.h | 44 +- src/nimble/nimble/host/src/ble_sm.c | 449 +- src/nimble/nimble/host/src/ble_sm_alg.c | 243 +- src/nimble/nimble/host/src/ble_sm_lgcy.c | 6 +- src/nimble/nimble/host/src/ble_sm_priv.h | 45 +- src/nimble/nimble/host/src/ble_sm_sc.c | 36 +- src/nimble/nimble/host/src/ble_store_util.c | 148 +- .../host/store/config/src/ble_store_config.c | 5 +- .../store/config/src/ble_store_config_priv.h | 4 +- .../host/store/config/src/ble_store_nvs.c | 147 +- .../nimble/host/store/ram/src/ble_store_ram.c | 251 +- src/nimble/nimble/host/util/src/addr.c | 15 +- src/nimble/nimble/include/nimble/ble.h | 130 +- src/nimble/nimble/include/nimble/hci_common.h | 641 +-- src/nimble/nimble/include/nimble/nimble_npl.h | 6 - .../nimble/include/nimble/nimble_npl_log.h | 57 + .../nimble/include/nimble/nimble_opt_auto.h | 9 +- .../hci_h4/include/nimble/transport/hci_h4.h | 70 - .../transport/common/hci_h4/src/hci_h4.c | 332 -- .../include/nimble/transport/hci_ipc.h | 99 - .../transport/common/hci_ipc/src/hci_ipc.c | 238 -- .../transport/include/nimble/transport.h | 176 +- .../transport/include/nimble/transport_impl.h | 3 +- .../transport/nrf5340/src/nrf5340_ble_hci.c | 235 -- src/nimble/nimble/transport/src/transport.c | 223 +- .../porting/nimble/include/hal/hal_gpio.h | 170 - .../porting/nimble/include/hal/hal_os_tick.h | 53 - .../porting/nimble/include/hal/hal_system.h | 96 - .../porting/nimble/include/hal/hal_uart.h | 146 - .../porting/nimble/include/hal/hal_watchdog.h | 55 - .../porting/nimble/include/logcfg/logcfg.h | 176 - .../nimble/include/sysflash/sysflash.h | 47 - src/nimble/porting/nimble/src/nimble_port.c | 26 +- .../include/nimble/nimble_npl_os_log.h | 66 + .../npl/freertos/src/nimble_port_freertos.c | 2 +- .../nrf_store}/ble_store_config_conf.c | 2 +- src/syscfg/syscfg.h | 18 + 283 files changed, 11248 insertions(+), 54463 deletions(-) delete mode 100644 src/nimble/CODING_STANDARDS.md rename src/nimble/{nimble/transport => esp_port}/esp_ipc/src/hci_esp_ipc.c (96%) rename src/nimble/{nimble/transport => esp_port}/esp_ipc_legacy/src/hci_esp_ipc_legacy.c (84%) create mode 100644 src/nimble/nimble/controller/include/controller/ble_ll_cs.h create mode 100644 src/nimble/nimble/controller/src/ble_ll_cs.c create mode 100644 src/nimble/nimble/controller/src/ble_ll_cs_drbg.c create mode 100644 src/nimble/nimble/controller/src/ble_ll_cs_drbg_priv.h delete mode 100644 src/nimble/nimble/drivers/nrf5x/src/nrf53/phy.c delete mode 100644 src/nimble/nimble/drivers/nrf5x/src/nrf53/phy_ppi.h create mode 100644 src/nimble/nimble/host/include/host/ble_cs.h delete mode 100644 src/nimble/nimble/host/include/host/ble_esp_gap.h delete mode 100644 src/nimble/nimble/host/include/host/ble_esp_gatt.h delete mode 100644 src/nimble/nimble/host/include/host/ble_esp_hs.h create mode 100644 src/nimble/nimble/host/include/host/ble_iso.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/access.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/atomic.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/cdb.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/cfg.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/glue.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/health_cli.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/health_srv.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/heartbeat.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/main.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/mesh.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/model_cli.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/model_srv.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/msg.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/porting.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/proxy.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/slist.h delete mode 100644 src/nimble/nimble/host/mesh/include/mesh/testing.h delete mode 100644 src/nimble/nimble/host/mesh/src/access.c delete mode 100644 src/nimble/nimble/host/mesh/src/access.h delete mode 100644 src/nimble/nimble/host/mesh/src/adv.c delete mode 100644 src/nimble/nimble/host/mesh/src/adv.h delete mode 100644 src/nimble/nimble/host/mesh/src/adv_ext.c delete mode 100644 src/nimble/nimble/host/mesh/src/adv_legacy.c delete mode 100644 src/nimble/nimble/host/mesh/src/aes-ccm.c delete mode 100644 src/nimble/nimble/host/mesh/src/app_keys.c delete mode 100644 src/nimble/nimble/host/mesh/src/app_keys.h delete mode 100644 src/nimble/nimble/host/mesh/src/atomic.h delete mode 100644 src/nimble/nimble/host/mesh/src/beacon.c delete mode 100644 src/nimble/nimble/host/mesh/src/beacon.h delete mode 100644 src/nimble/nimble/host/mesh/src/cdb.c delete mode 100644 src/nimble/nimble/host/mesh/src/cdb_priv.h delete mode 100644 src/nimble/nimble/host/mesh/src/cfg.c delete mode 100644 src/nimble/nimble/host/mesh/src/cfg.h delete mode 100644 src/nimble/nimble/host/mesh/src/cfg_cli.c delete mode 100644 src/nimble/nimble/host/mesh/src/cfg_srv.c delete mode 100644 src/nimble/nimble/host/mesh/src/crypto.c delete mode 100644 src/nimble/nimble/host/mesh/src/crypto.h delete mode 100644 src/nimble/nimble/host/mesh/src/foundation.h delete mode 100644 src/nimble/nimble/host/mesh/src/friend.c delete mode 100644 src/nimble/nimble/host/mesh/src/friend.h delete mode 100644 src/nimble/nimble/host/mesh/src/glue.c delete mode 100644 src/nimble/nimble/host/mesh/src/health_cli.c delete mode 100644 src/nimble/nimble/host/mesh/src/health_srv.c delete mode 100644 src/nimble/nimble/host/mesh/src/heartbeat.c delete mode 100644 src/nimble/nimble/host/mesh/src/heartbeat.h delete mode 100644 src/nimble/nimble/host/mesh/src/light_model.c delete mode 100644 src/nimble/nimble/host/mesh/src/light_model.h delete mode 100644 src/nimble/nimble/host/mesh/src/lpn.c delete mode 100644 src/nimble/nimble/host/mesh/src/lpn.h delete mode 100644 src/nimble/nimble/host/mesh/src/mesh.c delete mode 100644 src/nimble/nimble/host/mesh/src/mesh_priv.h delete mode 100644 src/nimble/nimble/host/mesh/src/model_cli.c delete mode 100644 src/nimble/nimble/host/mesh/src/model_srv.c delete mode 100644 src/nimble/nimble/host/mesh/src/msg.c delete mode 100644 src/nimble/nimble/host/mesh/src/net.c delete mode 100644 src/nimble/nimble/host/mesh/src/net.h delete mode 100644 src/nimble/nimble/host/mesh/src/pb_adv.c delete mode 100644 src/nimble/nimble/host/mesh/src/pb_gatt.c delete mode 100644 src/nimble/nimble/host/mesh/src/pb_gatt_srv.c delete mode 100644 src/nimble/nimble/host/mesh/src/pb_gatt_srv.h delete mode 100644 src/nimble/nimble/host/mesh/src/prov.c delete mode 100644 src/nimble/nimble/host/mesh/src/prov.h delete mode 100644 src/nimble/nimble/host/mesh/src/prov_bearer.h delete mode 100644 src/nimble/nimble/host/mesh/src/prov_device.c delete mode 100644 src/nimble/nimble/host/mesh/src/provisioner.c delete mode 100644 src/nimble/nimble/host/mesh/src/provisioner.h delete mode 100644 src/nimble/nimble/host/mesh/src/proxy.c delete mode 100644 src/nimble/nimble/host/mesh/src/proxy.h delete mode 100644 src/nimble/nimble/host/mesh/src/proxy_msg.c delete mode 100644 src/nimble/nimble/host/mesh/src/proxy_msg.h delete mode 100644 src/nimble/nimble/host/mesh/src/proxy_srv.c delete mode 100644 src/nimble/nimble/host/mesh/src/rpl.c delete mode 100644 src/nimble/nimble/host/mesh/src/rpl.h delete mode 100644 src/nimble/nimble/host/mesh/src/settings.c delete mode 100644 src/nimble/nimble/host/mesh/src/settings.h delete mode 100644 src/nimble/nimble/host/mesh/src/shell.c delete mode 100644 src/nimble/nimble/host/mesh/src/shell.h delete mode 100644 src/nimble/nimble/host/mesh/src/subnet.c delete mode 100644 src/nimble/nimble/host/mesh/src/subnet.h delete mode 100644 src/nimble/nimble/host/mesh/src/testing.c delete mode 100644 src/nimble/nimble/host/mesh/src/testing.h delete mode 100644 src/nimble/nimble/host/mesh/src/transport.c delete mode 100644 src/nimble/nimble/host/mesh/src/transport.h create mode 100644 src/nimble/nimble/host/src/ble_audio_codec_priv.h create mode 100644 src/nimble/nimble/host/src/ble_cs.c create mode 100644 src/nimble/nimble/host/src/ble_cs_priv.h create mode 100644 src/nimble/nimble/host/src/ble_iso.c create mode 100644 src/nimble/nimble/host/src/ble_iso_priv.h create mode 100644 src/nimble/nimble/include/nimble/nimble_npl_log.h delete mode 100644 src/nimble/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h delete mode 100644 src/nimble/nimble/transport/common/hci_h4/src/hci_h4.c delete mode 100644 src/nimble/nimble/transport/common/hci_ipc/include/nimble/transport/hci_ipc.h delete mode 100644 src/nimble/nimble/transport/common/hci_ipc/src/hci_ipc.c delete mode 100644 src/nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c delete mode 100644 src/nimble/porting/nimble/include/hal/hal_gpio.h delete mode 100644 src/nimble/porting/nimble/include/hal/hal_os_tick.h delete mode 100644 src/nimble/porting/nimble/include/hal/hal_system.h delete mode 100644 src/nimble/porting/nimble/include/hal/hal_uart.h delete mode 100644 src/nimble/porting/nimble/include/hal/hal_watchdog.h delete mode 100644 src/nimble/porting/nimble/include/logcfg/logcfg.h delete mode 100644 src/nimble/porting/nimble/include/sysflash/sysflash.h create mode 100644 src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os_log.h rename src/nimble/{nimble/host/store/config/src => porting/nrf_store}/ble_store_config_conf.c (99%) diff --git a/src/NimBLEUtils.cpp b/src/NimBLEUtils.cpp index 1156eb88e..e5ca4daf1 100644 --- a/src/NimBLEUtils.cpp +++ b/src/NimBLEUtils.cpp @@ -542,14 +542,22 @@ const char* NimBLEUtils::gapEventToString(uint8_t eventType) { return "BLE_GAP_EVENT_PARING_COMPLETE"; case BLE_GAP_EVENT_SUBRATE_CHANGE: // 28 return "BLE_GAP_EVENT_SUBRATE_CHANGE"; +# ifdef BLE_GAP_EVENT_VS_HCI case BLE_GAP_EVENT_VS_HCI: // 29 return "BLE_GAP_EVENT_VS_HCI"; +# endif +# ifdef BLE_GAP_EVENT_REATTEMPT_COUNT case BLE_GAP_EVENT_REATTEMPT_COUNT: // 31 return "BLE_GAP_EVENT_REATTEMPT_COUNT"; +# endif +# ifdef BLE_GAP_EVENT_AUTHORIZE case BLE_GAP_EVENT_AUTHORIZE: // 32 return "BLE_GAP_EVENT_AUTHORIZE"; +# endif +# ifdef BLE_GAP_EVENT_TEST_UPDATE case BLE_GAP_EVENT_TEST_UPDATE: // 33 return "BLE_GAP_EVENT_TEST_UPDATE"; +# endif # ifdef BLE_GAP_EVENT_DATA_LEN_CHG case BLE_GAP_EVENT_DATA_LEN_CHG: // 34 return "BLE_GAP_EVENT_DATA_LEN_CHG"; diff --git a/src/nimble/CODING_STANDARDS.md b/src/nimble/CODING_STANDARDS.md deleted file mode 100644 index d14b9fdb1..000000000 --- a/src/nimble/CODING_STANDARDS.md +++ /dev/null @@ -1,267 +0,0 @@ -# Coding Style for Apache NimBLE - -Apache NimBLE project is part of Apache Mynewt projct and follows its coding -style. - -# Coding Style for Apache Mynewt Core - -This document is meant to define the coding style for Apache Mynewt, and -all subprojects of Apache Mynewt. This covers C and Assembly coding -conventions, *only*. Other languages (such as Go), have their own -coding conventions. - -## Headers - -* All files that are newly written, should have the Apache License clause -at the top of them. - -* For files that are copied from another source, but contain an Apache -compatible license, the original license header shall be maintained. - -* For more information on applying the Apache license, the definitive -source is here: http://www.apache.org/dev/apply-license.html - -* The Apache License clause for the top of files is as follows: - -```no-highlight -/* - * 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. - */ -``` - -## Whitespace and Braces - -* Code must be indented to 4 spaces, tabs should not be used. - -* Do not add whitespace at the end of a line. - -* Put space after keywords (for, if, return, switch, while). - -* for, else, if, while statements must have braces around their -code blocks, i.e., do: - -``` - if (x) { - assert(0); - } else { - assert(0); - } -``` - -Not: - -``` - if (x) - assert(0); - else - assert(0); -``` - -* Braces for statements must be on the same line as the statement. Good: - -``` - for (i = 0; i < 10; i++) { - if (i == 5) { - break; - } else { - continue; - } - } -``` - -Not: - -``` - for (i = 0; i < 10; i++) - { <-- brace must be on same line as for - if (i == 5) { - break; - } <-- no new line between else - else { - continue; - } - } -``` - -* After a function declaration, the braces should be on a newline, i.e. do: - -``` - static void * - function(int var1, int var2) - { -``` - -not: - -``` - static void * - function(int var1, int var2) { -``` - -## Line Length and Wrap - -* Line length should never exceed 79 columns. - -* When you have to wrap a long statement, put the operator at the end of the - line. i.e.: - -``` - if (x && - y == 10 && - b) -``` - -Not: - -``` - if (x - && y == 10 - && b) -``` - -## Comments - -* No C++ style comments allowed. - -* When using a single line comment, put it above the line of code that you -intend to comment, i.e., do: - -``` - /* check variable */ - if (a) { -``` - -Not: - -``` - if (a) { /* check variable */ -``` - - -* All public APIs should be commented with Doxygen style comments describing -purpose, parameters and return values. Private APIs need not be documented. - - -## Header files - -* Header files must contain the following structure: - * Apache License (see above) - * ```#ifdef``` aliasing, to prevent multiple includes - * ```#include``` directives for other required header files - * ```#ifdef __cplusplus``` wrappers to maintain C++ friendly APIs - * Contents of the header file - -* ```#ifdef``` aliasing, shall be in the following format, where -the package name is "os" and the file name is "callout.h": - -```no-highlight -#ifndef _OS_CALLOUT_H -#define _OS_CALLOUT_H -``` - -* ```#include``` directives must happen prior to the cplusplus -wrapper. - -* The cplusplus wrapper must have the following format, and precedes -any contents of the header file: - -```no-highlight -#ifdef __cplusplus -#extern "C" { -##endif -``` - -## Naming - -* Names of functions, structures and variables must be in all lowercase. - -* Names should be as short as possible, but no shorter. - -* Globally visible names must be prefixed with the name of the module, -followed by the '_' character, i.e.: - -``` - os_callout_init(&c) -``` - -Not: - -``` - callout_init(c) -``` - -## Functions - -* No spaces after function names when calling a function, i.e, do: - -``` - rc = function(a) -``` - -Not: - -``` - rc = function (a) -``` - - -* Arguments to function calls should have spaces between the comma, i.e. do: - -``` - rc = function(a, b) -``` - -Not: - -``` - rc = function(a,b) -``` - -* The function type must be on a line by itself preceding the function, i.e. do: - -``` - static void * - function(int var1, int var2) - { -``` - -Not: - -``` - static void *function(int var1, int var2) - { -``` - -* In general, for functions that return values that denote success or error, 0 -shall be success, and non-zero shall be the failure code. - -## Variables and Macros - -* Do not use typedefs for structures. This makes it impossible for -applications to use pointers to those structures opaquely. - -* typedef may be used for non-structure types, where it is beneficial to -hide or alias the underlying type used (e.g. ```os_time_t```.) Indicate -typedefs by applying the ```_t``` marker to them. - -* Place all function-local variable definitions at the top of the function body, before any statements. - -## Compiler Directives - -* Code must compile cleanly with -Wall enabled. - diff --git a/src/nimble/LICENSE b/src/nimble/LICENSE index 960e8257e..ca697aee3 100644 --- a/src/nimble/LICENSE +++ b/src/nimble/LICENSE @@ -225,3 +225,6 @@ missing licensing information. The BSD license was subsequently added to these files in later releases. These files are: * babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h +This product bundles part of linker scripts from Nordic Semiconductor, +which is available under the "modified Tcl/Tk" license. Bundled files are: + * targets/auracast_usb/nrf5340-mcu.ld diff --git a/src/nimble/NOTICE b/src/nimble/NOTICE index 3f9a1c8c7..8f970cbce 100644 --- a/src/nimble/NOTICE +++ b/src/nimble/NOTICE @@ -1,6 +1,5 @@ Apache Mynewt NimBLE -Copyright 2015-2022 The Apache Software Foundation -Modifications Copyright 2017-2022 Espressif Systems (Shanghai) CO., LTD. +Copyright 2015-2025 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/src/nimble/RELEASE_NOTES.md b/src/nimble/RELEASE_NOTES.md index afd5e92a8..141f8944f 100644 --- a/src/nimble/RELEASE_NOTES.md +++ b/src/nimble/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # RELEASE NOTES -09 August 2023 - Apache NimBLE v1.6.0 +15 December 2025 - Apache NimBLE v1.9.0 For full release notes, please visit the [Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes). @@ -10,11 +10,8 @@ replaces the proprietary SoftDevice on Nordic chipsets. New features in this version of NimBLE include: -* Initial support for ISO broacaster -* Support for Bluetooth Core Specification 5.4 -* FEM antenna control -* nRF PHY driver unification -* IPC HCI transport improvements +* Characteristic Extended Properties descriptor in GATT server +* Framed PDUs in ISO Adaptation Layer 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/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c b/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c index 4f13e2525..6114d6939 100644 --- a/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c +++ b/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c @@ -32,6 +32,9 @@ #define BLE_HCI_EVENT_HDR_LEN (2) #define BLE_HCI_CMD_HDR_LEN (3) +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); + static ble_hci_trans_rx_cmd_fn *ble_hci_rx_cmd_hs_cb; static void *ble_hci_rx_cmd_hs_arg; diff --git a/src/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c b/src/nimble/esp_port/esp_ipc/src/hci_esp_ipc.c similarity index 96% rename from src/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c rename to src/nimble/esp_port/esp_ipc/src/hci_esp_ipc.c index 0ff29d26d..e80f3018e 100644 --- a/src/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c +++ b/src/nimble/esp_port/esp_ipc/src/hci_esp_ipc.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/porting/nimble/include/os/os_mbuf.h" #include "nimble/nimble/transport/include/nimble/transport.h" #include "nimble/esp_port/port/transport/include/esp_hci_transport.h" diff --git a/src/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c b/src/nimble/esp_port/esp_ipc_legacy/src/hci_esp_ipc_legacy.c similarity index 84% rename from src/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c rename to src/nimble/esp_port/esp_ipc_legacy/src/hci_esp_ipc_legacy.c index d112f1fb3..6f4ee4002 100644 --- a/src/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c +++ b/src/nimble/esp_port/esp_ipc_legacy/src/hci_esp_ipc_legacy.c @@ -10,10 +10,13 @@ #include #include #include -#include +#include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/nimble/transport/include/nimble/transport.h" #include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h" +extern int ble_hci_trans_hs_acl_tx(struct os_mbuf *om); +extern int ble_hci_trans_hs_cmd_tx(void *buf); + /* This file is only used by ESP32, ESP32C3 and ESP32S3. */ int ble_transport_to_ll_cmd_impl(void *buf) diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h b/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h index d857505c6..a5a77747c 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h @@ -74,7 +74,7 @@ #ifndef __TC_CBC_MODE_H__ #define __TC_CBC_MODE_H__ -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h index 31a85b090..2d3b2b9e9 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h @@ -74,7 +74,7 @@ #ifndef __TC_CCM_MODE_H__ #define __TC_CCM_MODE_H__ -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #include #ifdef __cplusplus diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h b/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h index 9a943cad1..f99221229 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h @@ -97,7 +97,7 @@ #ifndef __TC_CMAC_MODE_H__ #define __TC_CMAC_MODE_H__ -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #include diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h index 68cc8567d..5773a71d0 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h @@ -67,8 +67,8 @@ #ifndef __TC_CTR_MODE_H__ #define __TC_CTR_MODE_H__ -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h index b809ac86a..def74a31f 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h @@ -59,7 +59,7 @@ #ifndef __TC_CTR_PRNG_H__ #define __TC_CTR_PRNG_H__ -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #define TC_CTR_PRNG_RESEED_REQ -1 diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h index f1f9efb95..90dabc5c2 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h @@ -69,7 +69,7 @@ #ifndef __TC_ECC_DH_H__ #define __TC_ECC_DH_H__ -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h index 1bb209e1b..dda52c9a4 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h @@ -78,7 +78,7 @@ #ifndef __TC_ECC_DSA_H__ #define __TC_ECC_DSA_H__ -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h b/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h index 9a796bd36..77af86f9a 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h @@ -63,7 +63,7 @@ #ifndef __TC_HMAC_H__ #define __TC_HMAC_H__ -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/sha256.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h b/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h index 976816dde..d8ef82c53 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h @@ -68,8 +68,8 @@ #ifndef __TC_HMAC_PRNG_H__ #define __TC_HMAC_PRNG_H__ -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/sha256.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/hmac.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/src/aes_decrypt.c b/src/nimble/ext/tinycrypt/src/aes_decrypt.c index 2944af9d2..0828e36cf 100644 --- a/src/nimble/ext/tinycrypt/src/aes_decrypt.c +++ b/src/nimble/ext/tinycrypt/src/aes_decrypt.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" static const uint8_t inv_sbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, diff --git a/src/nimble/ext/tinycrypt/src/aes_encrypt.c b/src/nimble/ext/tinycrypt/src/aes_encrypt.c index 877c43547..4c1e088a1 100644 --- a/src/nimble/ext/tinycrypt/src/aes_encrypt.c +++ b/src/nimble/ext/tinycrypt/src/aes_encrypt.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" static const uint8_t sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, diff --git a/src/nimble/ext/tinycrypt/src/cbc_mode.c b/src/nimble/ext/tinycrypt/src/cbc_mode.c index 5264eb487..54c614066 100644 --- a/src/nimble/ext/tinycrypt/src/cbc_mode.c +++ b/src/nimble/ext/tinycrypt/src/cbc_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, const uint8_t *iv, diff --git a/src/nimble/ext/tinycrypt/src/ccm_mode.c b/src/nimble/ext/tinycrypt/src/ccm_mode.c index d291a8398..0bbecebe6 100644 --- a/src/nimble/ext/tinycrypt/src/ccm_mode.c +++ b/src/nimble/ext/tinycrypt/src/ccm_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" #include diff --git a/src/nimble/ext/tinycrypt/src/cmac_mode.c b/src/nimble/ext/tinycrypt/src/cmac_mode.c index 603de204c..dcd259dd6 100644 --- a/src/nimble/ext/tinycrypt/src/cmac_mode.c +++ b/src/nimble/ext/tinycrypt/src/cmac_mode.c @@ -30,10 +30,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" /* max number of calls until change the key (2^48).*/ static const uint64_t MAX_CALLS = ((uint64_t)1 << 48); diff --git a/src/nimble/ext/tinycrypt/src/ctr_mode.c b/src/nimble/ext/tinycrypt/src/ctr_mode.c index 2b5f45c8a..e01557f6f 100644 --- a/src/nimble/ext/tinycrypt/src/ctr_mode.c +++ b/src/nimble/ext/tinycrypt/src/ctr_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) diff --git a/src/nimble/ext/tinycrypt/src/ctr_prng.c b/src/nimble/ext/tinycrypt/src/ctr_prng.c index da90b8301..6a6927139 100644 --- a/src/nimble/ext/tinycrypt/src/ctr_prng.c +++ b/src/nimble/ext/tinycrypt/src/ctr_prng.c @@ -27,9 +27,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" #include /* diff --git a/src/nimble/ext/tinycrypt/src/ecc.c b/src/nimble/ext/tinycrypt/src/ecc.c index 81f0fd881..19f46d1b1 100644 --- a/src/nimble/ext/tinycrypt/src/ecc.c +++ b/src/nimble/ext/tinycrypt/src/ecc.c @@ -52,8 +52,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h" #include /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform diff --git a/src/nimble/ext/tinycrypt/src/ecc_dh.c b/src/nimble/ext/tinycrypt/src/ecc_dh.c index c33f8a619..1f5cdfbd5 100644 --- a/src/nimble/ext/tinycrypt/src/ecc_dh.c +++ b/src/nimble/ext/tinycrypt/src/ecc_dh.c @@ -54,9 +54,9 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h" #include #if default_RNG_defined diff --git a/src/nimble/ext/tinycrypt/src/ecc_dsa.c b/src/nimble/ext/tinycrypt/src/ecc_dsa.c index 7068363b8..1a14fe457 100644 --- a/src/nimble/ext/tinycrypt/src/ecc_dsa.c +++ b/src/nimble/ext/tinycrypt/src/ecc_dsa.c @@ -53,9 +53,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h" #if default_RNG_defined static uECC_RNG_Function g_rng_function = &default_CSPRNG; diff --git a/src/nimble/ext/tinycrypt/src/hmac.c b/src/nimble/ext/tinycrypt/src/hmac.c index f9ef8d64e..6f8bb87ca 100644 --- a/src/nimble/ext/tinycrypt/src/hmac.c +++ b/src/nimble/ext/tinycrypt/src/hmac.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/hmac.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) { diff --git a/src/nimble/ext/tinycrypt/src/hmac_prng.c b/src/nimble/ext/tinycrypt/src/hmac_prng.c index fd14f70e5..d925344ea 100644 --- a/src/nimble/ext/tinycrypt/src/hmac_prng.c +++ b/src/nimble/ext/tinycrypt/src/hmac_prng.c @@ -30,10 +30,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/hmac.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" /* * min bytes in the seed string. diff --git a/src/nimble/ext/tinycrypt/src/sha256.c b/src/nimble/ext/tinycrypt/src/sha256.c index ab2170c25..6e2f8953a 100644 --- a/src/nimble/ext/tinycrypt/src/sha256.c +++ b/src/nimble/ext/tinycrypt/src/sha256.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/sha256.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" static void compress(unsigned int *iv, const uint8_t *data); diff --git a/src/nimble/ext/tinycrypt/src/utils.c b/src/nimble/ext/tinycrypt/src/utils.c index d00155944..33c86d2a3 100644 --- a/src/nimble/ext/tinycrypt/src/utils.c +++ b/src/nimble/ext/tinycrypt/src/utils.c @@ -30,8 +30,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" #include diff --git a/src/nimble/nimble/controller/include/controller/ble_ll.h b/src/nimble/nimble/controller/include/controller/ble_ll.h index 4bed7924b..58084f172 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll.h @@ -27,7 +27,7 @@ #ifdef MYNEWT #include "nimble/nimble/controller/include/controller/ble_ll_ctrl.h" -#include "nimble/porting/nimble/include/hal/hal_system.h" + #endif #ifdef RIOT_VERSION #include "nimble/porting/nimble/include/hal/hal_timer.h" @@ -53,12 +53,6 @@ void ble_ll_assert(const char *file, unsigned line) __attribute((noreturn)); #define BLE_LL_ASSERT(cond) assert(cond) #endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) -#define BLE_LL_BT5_PHY_SUPPORTED (1) -#else -#define BLE_LL_BT5_PHY_SUPPORTED (0) -#endif - /* Controller revision. */ #define BLE_LL_SUB_VERS_NR (0x0000) @@ -179,6 +173,7 @@ STATS_SECT_START(ble_ll_stats) STATS_SECT_ENTRY(rx_connect_reqs) STATS_SECT_ENTRY(rx_scan_ind) STATS_SECT_ENTRY(rx_aux_connect_rsp) + STATS_SECT_ENTRY(rx_pdu_on_scan_disabled) STATS_SECT_ENTRY(adv_txg) STATS_SECT_ENTRY(adv_late_starts) STATS_SECT_ENTRY(adv_resched_pdu_fail) @@ -250,46 +245,51 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; #endif /* LL Features */ -#define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001) -#define BLE_LL_FEAT_CONN_PARM_REQ (0x0000000002) -#define BLE_LL_FEAT_EXTENDED_REJ (0x0000000004) -#define BLE_LL_FEAT_PERIPH_INIT (0x0000000008) -#define BLE_LL_FEAT_LE_PING (0x0000000010) -#define BLE_LL_FEAT_DATA_LEN_EXT (0x0000000020) -#define BLE_LL_FEAT_LL_PRIVACY (0x0000000040) -#define BLE_LL_FEAT_EXT_SCAN_FILT (0x0000000080) -#define BLE_LL_FEAT_LE_2M_PHY (0x0000000100) -#define BLE_LL_FEAT_STABLE_MOD_ID_TX (0x0000000200) -#define BLE_LL_FEAT_STABLE_MOD_ID_RX (0x0000000400) -#define BLE_LL_FEAT_LE_CODED_PHY (0x0000000800) -#define BLE_LL_FEAT_EXT_ADV (0x0000001000) -#define BLE_LL_FEAT_PERIODIC_ADV (0x0000002000) -#define BLE_LL_FEAT_CSA2 (0x0000004000) -#define BLE_LL_FEAT_LE_POWER_CLASS_1 (0x0000008000) -#define BLE_LL_FEAT_MIN_USED_CHAN (0x0000010000) -#define BLE_LL_FEAT_CTE_REQ (0x0000020000) -#define BLE_LL_FEAT_CTE_RSP (0x0000040000) -#define BLE_LL_FEAT_CTE_TX (0x0000080000) -#define BLE_LL_FEAT_CTE_RX (0x0000100000) -#define BLE_LL_FEAT_CTE_AOD (0x0000200000) -#define BLE_LL_FEAT_CTE_AOA (0x0000400000) -#define BLE_LL_FEAT_CTE_RECV (0x0000800000) -#define BLE_LL_FEAT_SYNC_TRANS_SEND (0x0001000000) -#define BLE_LL_FEAT_SYNC_TRANS_RECV (0x0002000000) -#define BLE_LL_FEAT_SCA_UPDATE (0x0004000000) -#define BLE_LL_FEAT_REM_PKEY (0x0008000000) -#define BLE_LL_FEAT_CIS_CENTRAL (0x0010000000) -#define BLE_LL_FEAT_CIS_PERIPH (0x0020000000) -#define BLE_LL_FEAT_ISO_BROADCASTER (0x0040000000) -#define BLE_LL_FEAT_SYNC_RECV (0x0080000000) -#define BLE_LL_FEAT_CIS_HOST (0x0100000000) -#define BLE_LL_FEAT_POWER_CTRL_REQ (0x0200000000) -#define BLE_LL_FEAT_POWER_CHANGE_IND (0x0400000000) -#define BLE_LL_FEAT_PATH_LOSS_MON (0x0800000000) -#define BLE_LL_FEAT_PERIODIC_ADV_ADI (0x1000000000) -#define BLE_LL_FEAT_CONN_SUBRATING (0x2000000000) -#define BLE_LL_FEAT_CONN_SUBRATING_HOST (0x4000000000) -#define BLE_LL_FEAT_CHANNEL_CLASS (0x8000000000) +#define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000000001) +#define BLE_LL_FEAT_CONN_PARM_REQ (0x0000000000002) +#define BLE_LL_FEAT_EXTENDED_REJ (0x0000000000004) +#define BLE_LL_FEAT_PERIPH_INIT (0x0000000000008) +#define BLE_LL_FEAT_LE_PING (0x0000000000010) +#define BLE_LL_FEAT_DATA_LEN_EXT (0x0000000000020) +#define BLE_LL_FEAT_LL_PRIVACY (0x0000000000040) +#define BLE_LL_FEAT_EXT_SCAN_FILT (0x0000000000080) +#define BLE_LL_FEAT_LE_2M_PHY (0x0000000000100) +#define BLE_LL_FEAT_STABLE_MOD_ID_TX (0x0000000000200) +#define BLE_LL_FEAT_STABLE_MOD_ID_RX (0x0000000000400) +#define BLE_LL_FEAT_LE_CODED_PHY (0x0000000000800) +#define BLE_LL_FEAT_EXT_ADV (0x0000000001000) +#define BLE_LL_FEAT_PERIODIC_ADV (0x0000000002000) +#define BLE_LL_FEAT_CSA2 (0x0000000004000) +#define BLE_LL_FEAT_LE_POWER_CLASS_1 (0x0000000008000) +#define BLE_LL_FEAT_MIN_USED_CHAN (0x0000000010000) +#define BLE_LL_FEAT_CTE_REQ (0x0000000020000) +#define BLE_LL_FEAT_CTE_RSP (0x0000000040000) +#define BLE_LL_FEAT_CTE_TX (0x0000000080000) +#define BLE_LL_FEAT_CTE_RX (0x0000000100000) +#define BLE_LL_FEAT_CTE_AOD (0x0000000200000) +#define BLE_LL_FEAT_CTE_AOA (0x0000000400000) +#define BLE_LL_FEAT_CTE_RECV (0x0000000800000) +#define BLE_LL_FEAT_SYNC_TRANS_SEND (0x0000001000000) +#define BLE_LL_FEAT_SYNC_TRANS_RECV (0x0000002000000) +#define BLE_LL_FEAT_SCA_UPDATE (0x0000004000000) +#define BLE_LL_FEAT_REM_PKEY (0x0000008000000) +#define BLE_LL_FEAT_CIS_CENTRAL (0x0000010000000) +#define BLE_LL_FEAT_CIS_PERIPH (0x0000020000000) +#define BLE_LL_FEAT_ISO_BROADCASTER (0x0000040000000) +#define BLE_LL_FEAT_SYNC_RECV (0x0000080000000) +#define BLE_LL_FEAT_CIS_HOST (0x0000100000000) +#define BLE_LL_FEAT_POWER_CTRL_REQ (0x0000200000000) +#define BLE_LL_FEAT_POWER_CHANGE_IND (0x0000400000000) +#define BLE_LL_FEAT_PATH_LOSS_MON (0x0000800000000) +#define BLE_LL_FEAT_PERIODIC_ADV_ADI (0x0001000000000) +#define BLE_LL_FEAT_CONN_SUBRATING (0x0002000000000) +#define BLE_LL_FEAT_CONN_SUBRATING_HOST (0x0004000000000) +#define BLE_LL_FEAT_CHANNEL_CLASS (0x0008000000000) +#define BLE_LL_FEAT_ADV_CODING_SEL (0x0010000000000) +#define BLE_LL_FEAT_ADV_CODING_SEL_HOST (0x0020000000000) +#define BLE_LL_FEAT_CS (0x0400000000000) +#define BLE_LL_FEAT_CS_HOST_SUPPORT (0x0800000000000) +#define BLE_LL_FEAT_CS_PCT_QUALITY_IND (0x1000000000000) /* This is initial mask, so if feature exchange will not happen, * but host will want to use this procedure, we will try. If not @@ -300,8 +300,9 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; #define BLE_LL_CONN_CLEAR_FEATURE(connsm, feature) (connsm->conn_features &= ~(feature)) /* All the features which can be controlled by the Host */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) -#define BLE_LL_HOST_CONTROLLED_FEATURES (BLE_LL_FEAT_CONN_SUBRATING_HOST) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) | \ + MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) +#define BLE_LL_HOST_CONTROLLED_FEATURES (1) #else #define BLE_LL_HOST_CONTROLLED_FEATURES (0) #endif diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_adv.h b/src/nimble/nimble/controller/include/controller/ble_ll_adv.h index ba17ed5e0..6290c9f45 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_adv.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_adv.h @@ -168,7 +168,7 @@ int ble_ll_adv_can_chg_whitelist(void); * Called when an advertising event has been removed from the scheduler * without being run. */ -void ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm); +void ble_ll_adv_preempted(struct ble_ll_adv_sm *advsm); /* * Called when a periodic event has been removed from the scheduler @@ -201,6 +201,9 @@ int ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len, /* Get advertising instance with periodic advertising configured */ struct ble_ll_adv_sm *ble_ll_adv_sync_get(uint8_t handle); +int ble_ll_adv_padv_event_start_get(struct ble_ll_adv_sm *advsm, + uint32_t *event_start, + uint8_t *event_start_rem_us); #if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) struct ble_ll_iso_big; @@ -213,6 +216,11 @@ int ble_ll_adv_sync_big_remove(struct ble_ll_adv_sm *advsm, struct ble_ll_iso_big *big); #endif /* BLE_LL_ISO_BROADCASTER */ +#if MYNEWT_VAL(BLE_VERSION) >= 54 +int ble_ll_adv_ext_set_param_v2(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen); +#endif + /* Called to notify adv code about RPA rotation */ void ble_ll_adv_rpa_timeout(void); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_conn.h b/src/nimble/nimble/controller/include/controller/ble_ll_conn.h index 8fabc0bc0..e07928df6 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_conn.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_conn.h @@ -108,6 +108,8 @@ struct ble_ll_conn_sm_flags { uint32_t encrypted : 1; uint32_t encrypt_ltk_req : 1; uint32_t encrypt_event_sent : 1; + uint32_t encrypt_paused : 1; + uint32_t pending_encrypt_restart : 1; uint32_t version_ind_txd : 1; uint32_t version_ind_rxd : 1; uint32_t features_rxd : 1; @@ -118,6 +120,7 @@ struct ble_ll_conn_sm_flags { uint32_t terminate_ind_rxd_acked : 1; uint32_t conn_update_sched : 1; uint32_t conn_update_use_cp : 1; + uint32_t conn_update_host_initd : 1; uint32_t conn_update_host_w4reply : 1; uint32_t conn_update_host_w4event : 1; uint32_t chanmap_update_sched : 1; @@ -233,7 +236,7 @@ struct ble_ll_conn_sm uint16_t host_req_max_rx_time; #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) struct ble_ll_conn_phy_data phy_data; uint16_t phy_instant; uint8_t phy_tx_transition; @@ -343,6 +346,8 @@ struct ble_ll_conn_sm /* Packet transmit queue */ struct os_mbuf *cur_tx_pdu; STAILQ_HEAD(conn_txq_head, os_mbuf_pkthdr) conn_txq; + uint8_t conn_txq_num_data_pkt; + uint8_t conn_txq_num_zero_pkt; /* List entry for active/free connection pools */ union { @@ -447,10 +452,15 @@ void ble_ll_conn_chan_map_update(void); /* required for unit testing */ uint8_t ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency); -/* used to get anchor point for connection event specified */ -void ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, +/* get current event counter and anchor point */ +void ble_ll_conn_anchor_get(struct ble_ll_conn_sm *connsm, uint16_t *event_cntr, uint32_t *anchor, uint8_t *anchor_usecs); +/* get anchor point for specified connection event */ +void ble_ll_conn_anchor_event_cntr_get(struct ble_ll_conn_sm *connsm, + uint16_t event_cntr, uint32_t *anchor, + uint8_t *anchor_usecs); + #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) int ble_ll_conn_move_anchor(struct ble_ll_conn_sm *connsm, uint16_t offset); #endif @@ -458,8 +468,6 @@ int ble_ll_conn_move_anchor(struct ble_ll_conn_sm *connsm, uint16_t offset); struct ble_ll_scan_addr_data; struct ble_ll_scan_pdu_data; -uint8_t ble_ll_conn_tx_connect_ind_pducb(uint8_t *dptr, void *pducb_arg, - uint8_t *hdr_byte); void ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm, struct ble_ll_scan_pdu_data *pdu_data, struct ble_ll_scan_addr_data *addrd, diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_cs.h b/src/nimble/nimble/controller/include/controller/ble_ll_cs.h new file mode 100644 index 000000000..fb7cb4a59 --- /dev/null +++ b/src/nimble/nimble/controller/include/controller/ble_ll_cs.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/* All Channel Sounding APIs are experimental and subject to change at any time */ + +#ifndef H_BLE_LL_CS +#define H_BLE_LL_CS + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* HCI handlers */ +int ble_ll_cs_hci_rd_loc_supp_cap(uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_cs_hci_rd_rem_supp_cap(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_cs_hci_wr_cached_rem_supp_cap(const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_cs_hci_sec_enable(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_cs_hci_set_def_settings(const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_cs_hci_rd_rem_fae(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_cs_hci_wr_cached_rem_fae(const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_cs_hci_create_config(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_cs_hci_remove_config(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_cs_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_cs_hci_set_proc_params(const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_cs_hci_proc_enable(const uint8_t *cmdbuf, uint8_t cmdlen); +int ble_ll_cs_hci_test(const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_cs_hci_test_end(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h b/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h index 89502a45a..918cc977b 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h @@ -294,8 +294,7 @@ struct ble_ll_len_req /* API */ struct ble_ll_conn_sm; -void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc, - void *data); +void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc); void ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc); int ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om); void ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm); @@ -307,7 +306,8 @@ uint8_t ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, int ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm *connsm, uint8_t rej_opcode, uint8_t err); int ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm); -int ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu); +int ble_ll_ctrl_enc_allowed_pdu_rx(struct ble_ll_conn_sm *connsm, + struct os_mbuf *rxpdu); int ble_ll_ctrl_enc_allowed_pdu_tx(struct os_mbuf_pkthdr *pkthdr); int ble_ll_ctrl_tx_start(struct ble_ll_conn_sm *connsm, struct os_mbuf *txpdu); int ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_iso.h b/src/nimble/nimble/controller/include/controller/ble_ll_iso.h index 2944b0747..4054ea16b 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_iso.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_iso.h @@ -21,16 +21,53 @@ #define H_BLE_LL_ISO #include +#include "nimble/nimble/controller/include/controller/ble_ll_isoal.h" #ifdef __cplusplus extern "C" { #endif -int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len); +struct ble_ll_iso_data_path { + uint8_t data_path_id; + uint8_t enabled : 1; +}; +struct ble_ll_iso_test_mode { + struct { + uint32_t rand; + uint8_t payload_type; + uint8_t enabled : 1; + } transmit; +}; +struct ble_ll_iso_conn { + /* Connection handle */ + uint16_t handle; + + /* Maximum SDU size */ + uint16_t max_sdu; + + /* ISO Data Path */ + struct ble_ll_iso_data_path data_path; + + /* ISO Test Mode */ + struct ble_ll_iso_test_mode test_mode; + + /* ISOAL Multiplexer */ + struct ble_ll_isoal_mux mux; + + /* HCI SDU Fragment */ + struct os_mbuf *frag; + + /* Number of Completed Packets */ + uint16_t num_completed_pkt; + + STAILQ_ENTRY(ble_ll_iso_conn) iso_conn_q_next; +}; + +/* HCI command handlers */ +int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); 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); @@ -39,12 +76,39 @@ 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_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); 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); +int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); + +void ble_ll_iso_init(void); +void ble_ll_iso_reset(void); + +/* ISO Data handler */ +int ble_ll_iso_data_in(struct os_mbuf *om); + +int ble_ll_iso_pdu_get(struct ble_ll_iso_conn *conn, uint8_t idx, uint32_t pkt_counter, uint8_t *llid, void *dptr); + +struct ble_ll_iso_conn_init_param { + uint32_t iso_interval_us; + uint32_t sdu_interval_us; + uint16_t conn_handle; + uint16_t max_sdu; + uint8_t max_pdu; + uint8_t framing; + uint8_t pte; + uint8_t bn; +}; + +void ble_ll_iso_conn_init(struct ble_ll_iso_conn *conn, struct ble_ll_iso_conn_init_param *param); +void ble_ll_iso_conn_free(struct ble_ll_iso_conn *conn); + +int ble_ll_iso_conn_event_start(struct ble_ll_iso_conn *conn, uint32_t timestamp); +int ble_ll_iso_conn_event_done(struct ble_ll_iso_conn *conn); + +struct ble_ll_iso_conn *ble_ll_iso_conn_find_by_handle(uint16_t conn_handle); #ifdef __cplusplus } diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_iso_big.h b/src/nimble/nimble/controller/include/controller/ble_ll_iso_big.h index 30cf1b46a..8576fc549 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_iso_big.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_iso_big.h @@ -33,12 +33,6 @@ int ble_ll_iso_big_biginfo_copy(struct ble_ll_iso_big *big, uint8_t *dptr, uint32_t base_ticks, uint8_t base_rem_us); int ble_ll_iso_big_biginfo_len(struct ble_ll_iso_big *big); -struct ble_ll_iso_bis *ble_ll_iso_big_find_bis_by_handle(uint16_t conn_handle); -struct ble_ll_isoal_mux *ble_ll_iso_big_find_mux_by_handle(uint16_t conn_handle); -int ble_ll_iso_big_last_tx_timestamp_get(struct ble_ll_iso_bis *bis, - uint16_t *packet_seq_num, - uint32_t *timestamp); - void ble_ll_iso_big_chan_map_update(void); void ble_ll_iso_big_halt(void); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_isoal.h b/src/nimble/nimble/controller/include/controller/ble_ll_isoal.h index 5104ea979..f95468d55 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_isoal.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_isoal.h @@ -20,13 +20,18 @@ #ifndef H_BLE_LL_ISOAL_ #define H_BLE_LL_ISOAL_ +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include + #ifdef __cplusplus extern "C" { #endif -#if MYNEWT_VAL(BLE_LL_ISO) - struct ble_ll_isoal_mux { +#if MYNEWT_VAL(BLE_LL_ISOAL_MUX_PREFILL) + uint8_t active; +#endif + /* Max PDU length */ uint8_t max_pdu; /* Number of expected SDUs per ISO interval */ @@ -38,44 +43,53 @@ struct ble_ll_isoal_mux { /* Number of SDUs available for current event */ uint8_t sdu_in_event; - STAILQ_HEAD(, os_mbuf_pkthdr) sdu_q; + /* Burst Number */ + uint8_t bn; - struct os_mbuf *frag; + STAILQ_HEAD(, os_mbuf_pkthdr) sdu_q; + uint16_t sdu_q_len; uint32_t sdu_counter; uint32_t event_tx_timestamp; uint32_t last_tx_timestamp; uint16_t last_tx_packet_seq_num; + + /* The head SDU Segment is the Continuation of an SDU */ + uint8_t sc : 1; + uint8_t framed : 1; + uint8_t framing_mode : 1; }; -void -ble_ll_isoal_mux_init(struct ble_ll_isoal_mux *mux, uint8_t max_pdu, - uint32_t iso_interval_us, uint32_t sdu_interval_us, - uint8_t bn, uint8_t pte); +#define BLE_LL_ISOAL_SEGHDR(sc, cmplt, len) \ + ((uint16_t)((sc) & 0x01) | (((cmplt) & 0x01) << 1) | ((len) & 0xff) << 8) + +#define BLE_LL_ISOAL_SEGHDR_SC(word) ((word) & 0x01) +#define BLE_LL_ISOAL_SEGHDR_CMPLT(word) ((word >> 1) & 0x01) +#define BLE_LL_ISOAL_SEGHDR_LEN(word) ((word >> 8) & 0xff) + +#define BLE_LL_ISOAL_MUX_IS_FRAMED(framing) \ + ((framing) == BLE_HCI_ISO_FRAMING_FRAMED_SEGMENTABLE || \ + (framing) == BLE_HCI_ISO_FRAMING_FRAMED_UNSEGMENTED) + +void ble_ll_isoal_mux_init(struct ble_ll_isoal_mux *mux, uint8_t max_pdu, + uint32_t iso_interval_us, uint32_t sdu_interval_us, + uint8_t bn, uint8_t pte, bool framed, + uint8_t framing_mode); void ble_ll_isoal_mux_free(struct ble_ll_isoal_mux *mux); int ble_ll_isoal_mux_event_start(struct ble_ll_isoal_mux *mux, uint32_t timestamp); int ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux); -int -ble_ll_isoal_mux_unframed_get(struct ble_ll_isoal_mux *mux, uint8_t idx, - uint8_t *llid, void *dptr); +int ble_ll_isoal_mux_pdu_get(struct ble_ll_isoal_mux *mux, uint8_t idx, + uint8_t *llid, void *dptr); -/* HCI command handlers */ -int ble_ll_isoal_hci_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_isoal_hci_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_isoal_hci_read_tx_sync(const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen); +void ble_ll_isoal_mux_sdu_enqueue(struct ble_ll_isoal_mux *mux, + struct os_mbuf *om); void ble_ll_isoal_init(void); void ble_ll_isoal_reset(void); -int ble_ll_isoal_data_in(struct os_mbuf *om); - -#endif /* BLE_LL_ISO */ #ifdef __cplusplus } diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h b/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h index b9ca7fd38..ff28e783c 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_resolv.h @@ -115,6 +115,17 @@ int ble_ll_resolv_peer_rpa_any(const uint8_t *rpa); /* Initialize resolv*/ void ble_ll_resolv_init(void); +#if MYNEWT_VAL(BLE_LL_HCI_VS_LOCAL_IRK) +int ble_ll_resolv_local_irk_set(uint8_t own_addr_type, const uint8_t *irk); +int ble_ll_resolv_local_rpa_get(uint8_t own_addr_type, uint8_t *rpa); +#else +static inline int +ble_ll_resolv_local_rpa_get(uint8_t own_addr_type, uint8_t *rpa) +{ + return -1; +} +#endif + #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_scan.h b/src/nimble/nimble/controller/include/controller/ble_ll_scan.h index 4c71a3e74..2baed9054 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_scan.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_scan.h @@ -99,6 +99,14 @@ struct ble_ll_scan_pdu_data { uint8_t adva[BLE_DEV_ADDR_LEN]; }; +struct ble_ll_scan_vs_config { + uint8_t ignore_legacy : 1; + uint8_t ignore_ext : 1; + uint8_t rssi_filter : 1; + + int8_t rssi_threshold; +}; + struct ble_ll_scan_addr_data { uint8_t *adva; uint8_t *targeta; @@ -124,7 +132,7 @@ struct ble_ll_scan_sm uint8_t scan_rsp_cons_fails; uint8_t scan_rsp_cons_ok; uint8_t scan_peer_rpa[BLE_DEV_ADDR_LEN]; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +#if MYNEWT_VAL(BLE_LL_SCAN_ACTIVE_SCAN_NRPA) ble_npl_time_t scan_nrpa_timer; uint8_t scan_nrpa[BLE_DEV_ADDR_LEN]; #endif @@ -156,6 +164,10 @@ struct ble_ll_scan_sm /* Connection sm for initiator scan */ struct ble_ll_conn_sm *connsm; #endif + +#if MYNEWT_VAL(BLE_LL_HCI_VS_SET_SCAN_CFG) + struct ble_ll_scan_vs_config vs_config; +#endif }; /* Scan types */ @@ -238,7 +250,6 @@ void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm); /* Called to halt currently running scan */ void ble_ll_scan_halt(void); -uint8_t *ble_ll_get_scan_nrpa(void); uint8_t ble_ll_scan_get_own_addr_type(void); uint8_t ble_ll_scan_get_filt_policy(void); uint8_t ble_ll_scan_get_filt_dups(void); @@ -254,11 +265,21 @@ int ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, uint8_t ext_adv, void ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, uint8_t ext_adv, uint16_t adi); +struct ble_ll_scan_sm *ble_ll_scan_sm_get(void); + +void ble_ll_scan_make_req_pdu(struct ble_ll_scan_sm *scansm, uint8_t *pdu, + uint8_t *hdr_byte, uint8_t adva_type, + const uint8_t *adva, int rpa_index); + int ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, struct ble_ll_scan_addr_data *addrd, uint8_t *scan_ok); int ble_ll_scan_rx_check_init(struct ble_ll_scan_addr_data *addrd); +#if MYNEWT_VAL(BLE_LL_HCI_VS_SET_SCAN_CFG) +int ble_ll_scan_set_vs_config(uint32_t flags, int8_t rssi_threshold); +#endif + #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_sched.h b/src/nimble/nimble/controller/include/controller/ble_ll_sched.h index cceb96ce1..5daa647fa 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_sched.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_sched.h @@ -219,7 +219,7 @@ uint32_t ble_ll_sched_css_get_conn_interval_us(void); #endif #if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) -int ble_ll_sched_iso_big(struct ble_ll_sched_item *sch, int first); +int ble_ll_sched_iso_big(struct ble_ll_sched_item *sch, int first, int fixed); #endif /* BLE_LL_ISO_BROADCASTER */ #ifdef __cplusplus diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_sync.h b/src/nimble/nimble/controller/include/controller/ble_ll_sync.h index 9817a67ed..30ae2b083 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_sync.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_sync.h @@ -45,7 +45,7 @@ int ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); void ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, - const uint8_t *sync_ind, bool reports_disabled, + const uint8_t *sync_ind, uint8_t mode, uint16_t max_skip, uint32_t sync_timeout); void ble_ll_sync_transfer_disconnected(struct ble_ll_conn_sm *connsm); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_tmr.h b/src/nimble/nimble/controller/include/controller/ble_ll_tmr.h index 2dbe8a0e1..3c2bd28f9 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_tmr.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_tmr.h @@ -64,9 +64,17 @@ ble_ll_tmr_u2t(uint32_t usecs) return usecs / 32; #endif #if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768 +#if __ARM_FEATURE_IDIV + if (usecs < 131072) { + return (usecs * 32768) / 1000000; + } else { + return ((uint64_t)usecs * 32768) / 1000000; + } +#else if (usecs <= 31249) { return (usecs * 137439) / 4194304; } +#endif #endif return os_cputime_usecs_to_ticks(usecs); diff --git a/src/nimble/nimble/controller/include/controller/ble_phy.h b/src/nimble/nimble/controller/include/controller/ble_phy.h index 8864231ab..67d50b26d 100644 --- a/src/nimble/nimble/controller/include/controller/ble_phy.h +++ b/src/nimble/nimble/controller/include/controller/ble_phy.h @@ -238,6 +238,9 @@ static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options) #if MYNEWT_VAL(BLE_LL_DTM) void ble_phy_enable_dtm(void); void ble_phy_disable_dtm(void); +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) +int ble_phy_dtm_carrier(uint8_t rf_channel); +#endif #endif #ifdef __cplusplus diff --git a/src/nimble/nimble/controller/src/ble_ll.c b/src/nimble/nimble/controller/src/ble_ll.c index 06d0d4520..e0624cbc0 100644 --- a/src/nimble/nimble/controller/src/ble_ll.c +++ b/src/nimble/nimble/controller/src/ble_ll.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM #include #include @@ -47,22 +48,26 @@ #include "nimble/nimble/controller/include/controller/ble_ll_trace.h" #include "nimble/nimble/controller/include/controller/ble_ll_sync.h" #include "nimble/nimble/controller/include/controller/ble_fem.h" -#include "nimble/nimble/controller/include/controller/ble_ll_isoal.h" +#if MYNEWT_VAL(BLE_LL_ISO) +#include "nimble/nimble/controller/include/controller/ble_ll_iso.h" +#endif +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) #include "nimble/nimble/controller/include/controller/ble_ll_iso_big.h" +#endif #if MYNEWT_VAL(BLE_LL_EXT) #include "nimble/nimble/controller/include/controller/ble_ll_ext.h" #endif #include "ble_ll_conn_priv.h" #include "ble_ll_hci_priv.h" #include "ble_ll_priv.h" -#include "nimble/porting/nimble/include/hal/hal_system.h" + #if MYNEWT_VAL(BLE_LL_DTM) #include "ble_ll_dtm_priv.h" #endif #if MYNEWT_VAL(BLE_LL_EXT) -#include +#include "nimble/nimble/controller/include/controller/ble_ll_ext.h" #endif /* XXX: @@ -83,6 +88,17 @@ static int8_t g_ble_ll_tx_power_phy_current; int8_t g_ble_ll_tx_power_compensation; int8_t g_ble_ll_rx_power_compensation; +#if BLE_LL_HOST_CONTROLLED_FEATURES +static const uint64_t g_ble_ll_host_controlled_features = +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) + BLE_LL_FEAT_CONN_SUBRATING_HOST | +#endif +#if MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) + BLE_LL_FEAT_ADV_CODING_SEL_HOST | +#endif + 0; +#endif + /* Supported states */ #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) #define BLE_LL_S_NCA ((uint64_t)1 << 0) @@ -321,6 +337,7 @@ STATS_NAME_START(ble_ll_stats) STATS_NAME(ble_ll_stats, rx_connect_reqs) STATS_NAME(ble_ll_stats, rx_scan_ind) STATS_NAME(ble_ll_stats, rx_aux_connect_rsp) + STATS_NAME(ble_ll_stats, rx_pdu_on_scan_disabled) STATS_NAME(ble_ll_stats, adv_txg) STATS_NAME(ble_ll_stats, adv_late_starts) STATS_NAME(ble_ll_stats, adv_resched_pdu_fail) @@ -843,7 +860,7 @@ ble_ll_tx_pkt_in(void) /* Do some basic error checking */ pb = handle & 0x3000; - if ((pkthdr->omp_len != length) || (pb > 0x1000) || (length == 0)) { + if ((pkthdr->omp_len != length) || (pb > 0x1000)) { /* This is a bad ACL packet. Count a stat and free it */ STATS_INC(ble_ll_stats, bad_acl_hdr); os_mbuf_free_chain(om); @@ -1371,9 +1388,6 @@ ble_ll_task(void *arg) MYNEWT_VAL(BLE_LL_TX_PWR_MAX_DBM))); g_ble_ll_tx_power_phy_current = INT8_MAX; - /* Tell the host that we are ready to receive packets */ - ble_ll_hci_send_noop(); - while (1) { ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER); BLE_LL_ASSERT(ev); @@ -1463,6 +1477,7 @@ ble_ll_read_supp_features(void) return g_ble_ll_data.ll_supp_features; } +#if BLE_LL_HOST_CONTROLLED_FEATURES /** * Sets the features controlled by the host. * @@ -1489,7 +1504,7 @@ 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)) { + if (!(mask & g_ble_ll_host_controlled_features)) { return BLE_ERR_UNSUPPORTED; } @@ -1501,6 +1516,8 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_SUCCESS; } +#endif + /** * Flush a link layer packet queue. * @@ -1547,7 +1564,7 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr) /* Set BLE transmit header */ ble_hdr = BLE_MBUF_HDR_PTR(m); - ble_hdr->txinfo.flags = 0; + ble_hdr->txinfo.num_data_pkt = 0; ble_hdr->txinfo.offset = 0; ble_hdr->txinfo.pyld_len = pdulen; ble_hdr->txinfo.hdr_byte = hdr; @@ -1681,13 +1698,14 @@ ble_ll_reset(void) ble_fem_lna_init(); #endif -#if MYNEWT_VAL(BLE_LL_ISO) - ble_ll_isoal_reset(); -#endif #if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) ble_ll_iso_big_reset(); #endif +#if MYNEWT_VAL(BLE_LL_ISO) + ble_ll_iso_reset(); +#endif + /* Re-initialize the PHY */ rc = ble_phy_init(); @@ -1767,7 +1785,7 @@ ble_ll_assert(const char *file, unsigned line) * * @return int */ -static void +void ble_ll_init(void) { int rc; @@ -1925,12 +1943,6 @@ ble_ll_init(void) features |= BLE_LL_FEAT_SCA_UPDATE; #endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) - features |= BLE_LL_FEAT_CIS_CENTRAL; - features |= BLE_LL_FEAT_CIS_PERIPH; - features |= BLE_LL_FEAT_CIS_HOST; -#endif - #if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) features |= BLE_LL_FEAT_ISO_BROADCASTER; #endif @@ -1939,6 +1951,19 @@ ble_ll_init(void) features |= BLE_LL_FEAT_CONN_SUBRATING; #endif +#if MYNEWT_VAL(BLE_LL_CHANNEL_SOUNDING) + features |= BLE_LL_FEAT_CS; + features |= BLE_LL_FEAT_CS_PCT_QUALITY_IND; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + features |= BLE_LL_FEAT_PERIODIC_ADV_ADI; +#endif + +#if MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) + features |= BLE_LL_FEAT_ADV_CODING_SEL; +#endif + lldata->ll_supp_features = features; /* Initialize random number generation */ @@ -1961,7 +1986,7 @@ ble_ll_init(void) #endif #if MYNEWT_VAL(BLE_LL_ISO) - ble_ll_isoal_init(); + ble_ll_iso_init(); #endif #if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) ble_ll_iso_big_init(); @@ -2009,7 +2034,8 @@ ble_transport_to_ll_iso_impl(struct os_mbuf *om) void ble_transport_ll_init(void) { - ble_ll_init(); + /* Tell the host that we are ready to receive packets */ + ble_ll_hci_send_noop(); } int diff --git a/src/nimble/nimble/controller/src/ble_ll_adv.c b/src/nimble/nimble/controller/src/ble_ll_adv.c index 7a517a6a3..6e952d3b1 100644 --- a/src/nimble/nimble/controller/src/ble_ll_adv.c +++ b/src/nimble/nimble/controller/src/ble_ll_adv.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include @@ -26,6 +26,7 @@ #include #include "syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/util.h" #include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" @@ -112,6 +113,7 @@ struct ble_ll_adv_sm uint8_t own_addr_type; uint8_t peer_addr_type; uint8_t adv_chan; + uint8_t retry_event; uint8_t adv_pdu_len; int8_t adv_rpa_index; int8_t tx_power; @@ -155,13 +157,15 @@ struct ble_ll_adv_sm uint8_t events; uint8_t pri_phy; uint8_t sec_phy; +#if MYNEWT_VAL(BLE_VERSION) >= 54 + uint8_t pri_phy_opt; + uint8_t sec_phy_opt; +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) struct os_mbuf *periodic_adv_data; struct os_mbuf *periodic_new_data; uint32_t periodic_crcinit; /* only 3 bytes are used */ uint32_t periodic_access_addr; - uint16_t periodic_adv_itvl_min; - uint16_t periodic_adv_itvl_max; uint16_t periodic_adv_props; uint16_t periodic_channel_id; uint16_t periodic_event_cntr; @@ -170,12 +174,23 @@ struct ble_ll_adv_sm uint8_t periodic_adv_active : 1; uint8_t periodic_sync_active : 1; uint8_t periodic_sync_index : 1; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + uint8_t periodic_include_adi : 1; + uint16_t periodic_adv_adi; +#endif uint8_t periodic_num_used_chans; uint8_t periodic_chanmap[BLE_LL_CHAN_MAP_LEN]; - uint32_t periodic_adv_itvl_ticks; - uint8_t periodic_adv_itvl_rem_usec; - uint8_t periodic_adv_event_start_time_remainder; - uint32_t periodic_adv_event_start_time; + uint16_t periodic_adv_itvl; + + uint32_t padv_itvl_us; + + uint16_t padv_anchor_offset; + uint32_t padv_anchor; + uint8_t padv_anchor_rem_us; + + uint32_t padv_event_start; + uint8_t padv_event_start_rem_us; + struct ble_ll_adv_sync periodic_sync[2]; struct ble_npl_event adv_periodic_txdone_ev; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) @@ -229,7 +244,7 @@ struct ble_ll_adv_sm struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_ADV_INSTANCES]; struct ble_ll_adv_sm *g_ble_ll_cur_adv_sm; -static void ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm); +static void ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm, bool preempted); static struct ble_ll_adv_sm * ble_ll_adv_sm_find_configured(uint8_t instance) @@ -334,7 +349,9 @@ static void ble_ll_adv_rpa_update(struct ble_ll_adv_sm *advsm) { if (ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type, - advsm->adva, 1)) { + advsm->adva, 1) || + (ble_ll_resolv_local_rpa_get(advsm->own_addr_type & 1, + advsm->adva) == 0)) { ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD); } else { if (advsm->own_addr_type & 1) { @@ -564,6 +581,7 @@ ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) uint8_t ext_hdr_len; uint8_t ext_hdr_flags; uint32_t offset; + bool has_adva; advsm = pducb_arg; @@ -575,8 +593,6 @@ ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) /* only ADV_EXT_IND goes on primary advertising channels */ pdu_type = BLE_ADV_PDU_TYPE_ADV_EXT_IND; - *hdr_byte = pdu_type; - adv_mode = 0; if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { adv_mode |= BLE_LL_EXT_ADV_MODE_CONN; @@ -585,11 +601,19 @@ ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) adv_mode |= BLE_LL_EXT_ADV_MODE_SCAN; } + has_adva = !MYNEWT_VAL(BLE_LL_EXT_ADV_ADVA_IN_AUX) && + !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV); + ext_hdr_len = BLE_LL_EXT_ADV_FLAGS_SIZE + BLE_LL_EXT_ADV_DATA_INFO_SIZE + BLE_LL_EXT_ADV_AUX_PTR_SIZE; ext_hdr_flags = (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT) | (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); + if (has_adva) { + ext_hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); + } + /* ext hdr len and adv mode */ dptr[0] = ext_hdr_len | (adv_mode << 6); dptr += 1; @@ -598,6 +622,15 @@ ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) dptr[0] = ext_hdr_flags; dptr += 1; + if (has_adva) { + /* AdvA */ + if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { + pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND; + } + memcpy(dptr, advsm->adva, BLE_LL_EXT_ADV_ADVA_SIZE); + dptr += BLE_LL_EXT_ADV_ADVA_SIZE; + } + /* ADI */ dptr[0] = advsm->adi & 0x00ff; dptr[1] = advsm->adi >> 8; @@ -613,89 +646,84 @@ ble_ll_adv_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) ble_ll_adv_put_aux_ptr(AUX_CURRENT(advsm)->chan, advsm->sec_phy, offset, dptr); + *hdr_byte = pdu_type; + return BLE_LL_EXT_ADV_HDR_LEN + ext_hdr_len; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) static void ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm, - struct ble_ll_conn_sm *connsm, uint8_t *conn_event_cnt, + struct ble_ll_conn_sm *connsm, uint8_t *conn_event_cntr, uint8_t *dptr) { + uint32_t offset_us; + uint32_t offset; + uint32_t anchor_ticks; + uint8_t anchor_rem_us; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - uint8_t anchor_usecs; - uint16_t conn_cnt; + uint16_t anchor_event_cntr; #endif - unsigned int event_cnt_off = 0; - uint32_t offset = 0; - uint32_t anchor; - uint8_t units; + uint32_t event_start; + uint8_t event_start_us; + uint32_t event_cntr_offset = 0; if (connsm) { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) - anchor = connsm->anchor_point; - anchor_usecs = connsm->anchor_point_usecs; - conn_cnt = connsm->event_cntr; - - /* get anchor for conn event that is before periodic_adv_event_start_time */ - while (LL_TMR_GT(anchor, advsm->periodic_adv_event_start_time)) { - ble_ll_conn_get_anchor(connsm, --conn_cnt, &anchor, &anchor_usecs); - } - - offset = ble_ll_tmr_t2u(advsm->periodic_adv_event_start_time - anchor); - offset -= anchor_usecs; - offset += advsm->periodic_adv_event_start_time_remainder; + ble_ll_conn_anchor_get(connsm, &anchor_event_cntr, + &anchor_ticks, &anchor_rem_us); /* connEventCount */ - put_le16(conn_event_cnt, conn_cnt); + put_le16(conn_event_cntr, anchor_event_cntr); +#else + BLE_LL_ASSERT(0); #endif } else { - anchor = advsm->periodic_adv_event_start_time; + anchor_ticks = AUX_CURRENT(advsm)->start_time; + anchor_rem_us = 0; + } - /* Get periodic event that is past AUX start time (so that we always - * provide valid offset if it is not too far in future). This can - * happen if advertising event is interleaved with periodic advertising - * event (when chaining). - */ - while (LL_TMR_GT(AUX_CURRENT(advsm)->start_time, anchor)) { - anchor += advsm->periodic_adv_itvl_ticks; - event_cnt_off++; - } + event_start = advsm->padv_event_start; + event_start_us = advsm->padv_event_start_rem_us; - offset = ble_ll_tmr_t2u(anchor - AUX_CURRENT(advsm)->start_time); - offset += advsm->periodic_adv_event_start_time_remainder; - offset += advsm->periodic_adv_itvl_rem_usec; + /* Find padv event that is past anchor item */ + while (LL_TMR_LEQ(event_start, anchor_ticks)) { + ble_ll_tmr_add(&event_start, &event_start_us, advsm->padv_itvl_us); + event_cntr_offset++; } + offset_us = ble_ll_tmr_t2u(event_start - anchor_ticks); + offset_us += event_start_us; + offset_us -= anchor_rem_us; + /* Sync Packet Offset (13 bits), Offset Units (1 bit), Offset Adjust (1 bit), * RFU (1 bit) */ - if (offset > 245700) { - units = 0x20; - offset = offset / 300; - + if (offset_us > 245700) { + offset = offset_us / 300; if (offset >= 0x2000) { if (connsm) { offset -= 0x2000; - units |= 0x40; + /* Offset Units = 1, Offset Adjust = 1 */ + offset |= 0x6000; } else { - /* not able to represent time in offset */ offset = 0; - units = 0x00; - event_cnt_off = 0; + event_cntr_offset = 0; } + } else { + /* Offset Units = 1, Offset Adjust = 0 */ + offset |= 0x2000; } } else { - units = 0x00; - offset = offset / 30; + offset = offset_us / 30; + /* Offset Units = 0, Offset Adjust = 0 */ } - dptr[0] = (offset & 0x000000ff); - dptr[1] = ((offset >> 8) & 0x0000001f) | units; + put_le16(&dptr[0], offset); /* Interval (2 bytes) */ - put_le16(&dptr[2], advsm->periodic_adv_itvl_max); + put_le16(&dptr[2], advsm->periodic_adv_itvl); /* Channels Mask (37 bits) */ dptr[4] = advsm->periodic_chanmap[0]; @@ -716,7 +744,7 @@ ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm, dptr[15] = (uint8_t)(advsm->periodic_crcinit >> 16); /* Event Counter (2 bytes) */ - put_le16(&dptr[16], advsm->periodic_event_cntr + event_cnt_off); + put_le16(&dptr[16], advsm->periodic_event_cntr + event_cntr_offset); } #endif @@ -1068,14 +1096,10 @@ ble_ll_adv_tx_done(void *arg) g_ble_ll_cur_adv_sm = NULL; } -/* - * Called when an advertising event has been removed from the scheduler - * without being run. - */ void -ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm) +ble_ll_adv_preempted(struct ble_ll_adv_sm *advsm) { - ble_ll_adv_drop_event(advsm); + ble_ll_adv_drop_event(advsm, 1); } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) @@ -1107,6 +1131,9 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) uint8_t end_trans; uint32_t txstart; struct ble_ll_adv_sm *advsm; +#if MYNEWT_VAL(BLE_LL_PHY) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + uint8_t phy_mode __attribute__((unused)); +#endif /* Get the state machine for the event */ advsm = (struct ble_ll_adv_sm *)sch->cb_arg; @@ -1125,13 +1152,18 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) rc = ble_phy_setchan(advsm->adv_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); BLE_LL_ASSERT(rc == 0); -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) /* Set phy mode */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_VERSION) >= 54 + phy_mode = ble_ll_phy_to_phy_mode(advsm->pri_phy, advsm->pri_phy_opt); +#else + phy_mode = ble_ll_phy_to_phy_mode(advsm->pri_phy, BLE_HCI_LE_PHY_CODED_ANY); +#endif if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); } else { - ble_phy_mode_set(advsm->pri_phy, advsm->pri_phy); + ble_phy_mode_set(phy_mode, phy_mode); } #else ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); @@ -1256,6 +1288,9 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) struct ble_ll_adv_sm *advsm; ble_phy_tx_pducb_t pducb; struct ble_ll_adv_aux *aux; +#if MYNEWT_VAL(BLE_LL_PHY) + uint8_t phy_mode; +#endif /* Get the state machine for the event */ advsm = (struct ble_ll_adv_sm *)sch->cb_arg; @@ -1271,9 +1306,14 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) BLE_LL_CRCINIT_ADV); BLE_LL_ASSERT(rc == 0); -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) +#if MYNEWT_VAL(BLE_VERSION) >= 54 + phy_mode = ble_ll_phy_to_phy_mode(advsm->sec_phy, advsm->sec_phy_opt); +#else + phy_mode = ble_ll_phy_to_phy_mode(advsm->sec_phy, BLE_HCI_LE_PHY_CODED_ANY); +#endif /* Set phy mode */ - ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); + ble_phy_mode_set(phy_mode, phy_mode); #endif /* Set the power */ @@ -1402,9 +1442,16 @@ ble_ll_adv_aux_calculate_payload(struct ble_ll_adv_sm *advsm, uint16_t props, ext_hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; } - /* AdvA in 1st PDU, except for anonymous */ + /* AdvA if: + * - 1st PDU + * - not anonymous + * - scannable/connectable or ADVA_IN_AUX selected + */ if (first_pdu && - !(props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { + !(props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV) && + ((props & (BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE | + BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) || + MYNEWT_VAL(BLE_LL_EXT_ADV_ADVA_IN_AUX))) { ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); ext_hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; } @@ -1911,10 +1958,10 @@ ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -static void -ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm) +static uint16_t +ble_ll_adv_update_did(uint16_t old_adi) { - uint16_t old_adi = advsm->adi; + uint16_t new_adi; /* * The Advertising DID for a given advertising set shall be initialized @@ -1925,8 +1972,10 @@ ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm) * the previously used value. */ do { - advsm->adi = (advsm->adi & 0xf000) | (ble_ll_rand() & 0x0fff); - } while (old_adi == advsm->adi); + new_adi = (old_adi & 0xf000) | (ble_ll_rand() & 0x0fff); + } while (old_adi == new_adi); + + return new_adi; } #endif @@ -1960,7 +2009,7 @@ ble_ll_adv_update_adv_scan_rsp_data(struct ble_ll_adv_sm *advsm) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /* DID shall be updated when host provides new advertising data */ - ble_ll_adv_update_did(advsm); + advsm->adi = ble_ll_adv_update_did(advsm->adi); #endif } @@ -2153,6 +2202,12 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) dptr += 1; } #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + if (sync->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + put_le16(dptr, advsm->periodic_adv_adi); + dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } +#endif if (sync->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { if (!SYNC_NEXT(advsm)->sch.enqueued) { @@ -2186,7 +2241,6 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) sync->sch.start_time + g_ble_ll_sched_offset_ticks, sync->sch.remainder); - BLE_LL_ASSERT(biginfo_len > 0); dptr += biginfo_len; } @@ -2266,7 +2320,7 @@ ble_ll_adv_sync_tx_start_cb(struct ble_ll_sched_item *sch) BLE_LL_ASSERT(rc == 0); -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) /* Set phy mode */ ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); #endif @@ -2335,6 +2389,13 @@ ble_ll_adv_sync_calculate(struct ble_ll_adv_sm *advsm, ext_hdr_len = BLE_LL_EXT_ADV_HDR_LEN; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + if (advsm->periodic_include_adi) { + sync->ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + } +#endif + /* TxPower if configured * Note: TxPower shall not be present in chain PDU for SYNC */ @@ -2421,7 +2482,7 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, * Preincrement event counter as we later send this in PDU so make sure * same values are used */ - chan = ble_ll_utils_dci_csa2(++advsm->periodic_event_cntr, + chan = ble_ll_utils_dci_csa2(advsm->periodic_event_cntr, advsm->periodic_channel_id, advsm->periodic_num_used_chans, advsm->periodic_chanmap); @@ -2433,14 +2494,20 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, sch = &sync->sch; - ble_ll_tmr_add_u(&advsm->periodic_adv_event_start_time, - &advsm->periodic_adv_event_start_time_remainder, - advsm->periodic_adv_itvl_rem_usec); + advsm->padv_event_start = advsm->padv_anchor; + advsm->padv_event_start_rem_us = advsm->padv_anchor_rem_us; + ble_ll_tmr_add(&advsm->padv_event_start, &advsm->padv_event_start_rem_us, + advsm->padv_itvl_us * advsm->padv_anchor_offset); - sch->start_time = advsm->periodic_adv_event_start_time; - sch->remainder = advsm->periodic_adv_event_start_time_remainder; - sch->end_time = sch->start_time + ble_ll_tmr_u2t_up(max_usecs); - sch->start_time -= g_ble_ll_sched_offset_ticks; + if (advsm->padv_anchor_offset == UINT16_MAX) { + advsm->padv_anchor_offset = 0; + advsm->padv_anchor = advsm->padv_event_start; + advsm->padv_anchor_rem_us = advsm->padv_event_start_rem_us; + } + + sch->start_time = advsm->padv_event_start - g_ble_ll_sched_offset_ticks; + sch->remainder = advsm->padv_event_start_rem_us; + sch->end_time = advsm->padv_event_start + ble_ll_tmr_u2t_up(max_usecs); rc = ble_ll_sched_periodic_adv(sch, first_pdu); if (rc) { @@ -2452,10 +2519,14 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, sync->start_time = sch->start_time + g_ble_ll_sched_offset_ticks; assert(first_pdu || - (sync->start_time == advsm->periodic_adv_event_start_time)); + (sync->start_time == advsm->padv_event_start)); - /* The event start time is when we start transmission of the SYNC PDU */ - advsm->periodic_adv_event_start_time = sync->start_time; + if (first_pdu) { + /* Need to update anchor on 1st PDU since it's start time can be changed + * while scheduling */ + advsm->padv_anchor = sync->start_time; + advsm->padv_event_start = sync->start_time; + } } static void @@ -2536,8 +2607,8 @@ ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm) * is scheduled past advertising interval. */ if (sync->auxptr_zero || - (LL_TMR_GT(sch->end_time, advsm->periodic_adv_event_start_time + - advsm->periodic_adv_itvl_ticks))) { + (LL_TMR_GT(sch->end_time, advsm->padv_event_start + + ble_ll_tmr_u2t(advsm->padv_itvl_us)))) { STATS_INC(ble_ll_stats, periodic_chain_drop_event); ble_ll_sched_rmv_elem(&sync->sch); } @@ -2561,7 +2632,9 @@ ble_ll_adv_sync_schedule(struct ble_ll_adv_sm *advsm, bool first_pdu) static void ble_ll_adv_reschedule_periodic_event(struct ble_ll_adv_sm *advsm) { - advsm->periodic_adv_event_start_time += advsm->periodic_adv_itvl_ticks; + advsm->periodic_event_cntr++; + advsm->padv_anchor_offset++; + ble_ll_adv_sync_schedule(advsm, false); } @@ -2580,6 +2653,9 @@ ble_ll_adv_update_periodic_data(struct ble_ll_adv_sm *advsm) os_mbuf_free_chain(advsm->periodic_adv_data); advsm->periodic_adv_data = advsm->periodic_new_data; advsm->periodic_new_data = NULL; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + advsm->periodic_adv_adi = ble_ll_adv_update_did(advsm->periodic_adv_adi); +#endif } ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA); @@ -2635,8 +2711,6 @@ ble_ll_adv_periodic_event_done(struct ble_npl_event *ev) static void ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm) { - uint32_t usecs; - /* * The Advertising DID is not required to change when a SyncInfo field is * added to or removed from an advertising set. However, if it does not @@ -2646,7 +2720,15 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm) * advertisers should update the Advertising DID when a periodic advertising * train is enabled. */ - ble_ll_adv_update_did(advsm); + advsm->adi = ble_ll_adv_update_did(advsm->adi); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + /* + * Since periodic advertising can be started without data we initialize DID here + * instead of after setting periodic advertising data. + */ + advsm->periodic_adv_adi = ble_ll_adv_update_did(advsm->periodic_adv_adi); +#endif advsm->periodic_adv_active = 1; @@ -2661,17 +2743,9 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm) (advsm->periodic_access_addr & 0x0000ffff); advsm->periodic_crcinit = ble_ll_rand() & 0xffffff; - usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL; - - advsm->periodic_adv_itvl_ticks = ble_ll_tmr_u2t_r(usecs, - &advsm->periodic_adv_itvl_rem_usec); - - /* There is no point in starting periodic advertising until next advertising - * event since SyncInfo is needed for synchronization - */ - advsm->periodic_adv_event_start_time_remainder = 0; - advsm->periodic_adv_event_start_time = advsm->adv_pdu_start_time + - ble_ll_tmr_u2t(advsm->adv_itvl_usecs + 5000); + advsm->padv_anchor_offset = 1; + advsm->padv_anchor = ble_ll_tmr_get(); + advsm->padv_anchor_rem_us = 0; ble_ll_adv_sync_schedule(advsm, true); } @@ -2697,7 +2771,7 @@ ble_ll_adv_sm_stop_periodic(struct ble_ll_adv_sm *advsm) * advertisers should update the Advertising DID when a periodic advertising * train is disabled. */ - ble_ll_adv_update_did(advsm); + advsm->adi = ble_ll_adv_update_did(advsm->adi); /* Remove any scheduled advertising items */ advsm->periodic_adv_active = 0; @@ -3119,7 +3193,7 @@ ble_ll_adv_set_scan_rsp_data(const uint8_t *data, uint8_t datalen, } /* DID shall be updated when host provides new scan response data */ - ble_ll_adv_update_did(advsm); + advsm->adi = ble_ll_adv_update_did(advsm->adi); #endif } @@ -3194,7 +3268,7 @@ ble_ll_adv_set_adv_data(const uint8_t *data, uint8_t datalen, uint8_t instance, } /* update DID only */ - ble_ll_adv_update_did(advsm); + advsm->adi = ble_ll_adv_update_did(advsm->adi); return BLE_ERR_SUCCESS; case BLE_HCI_LE_SET_DATA_OPER_LAST: ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_ADV_DATA_INCOMPLETE); @@ -3282,7 +3356,7 @@ ble_ll_adv_set_adv_data(const uint8_t *data, uint8_t datalen, uint8_t instance, } /* DID shall be updated when host provides new advertising data */ - ble_ll_adv_update_did(advsm); + advsm->adi = ble_ll_adv_update_did(advsm->adi); #endif } @@ -3410,16 +3484,40 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, } #endif - adv_itvl_min = cmd->pri_itvl_min[2] << 16 | cmd->pri_itvl_min[1] << 8 | - cmd->pri_itvl_min[0]; - adv_itvl_max = cmd->pri_itvl_max[2] << 16 | cmd->pri_itvl_max[1] << 8 | - cmd->pri_itvl_max[0]; + adv_itvl_min = get_le24(cmd->pri_itvl_min); + adv_itvl_max = get_le24(cmd->pri_itvl_max); if (props & ~BLE_HCI_LE_SET_EXT_ADV_PROP_MASK) { rc = BLE_ERR_INV_HCI_CMD_PARMS; goto done; } + /* Anonymous advertising only makes sense for non-connectable, non-scannable + * and non-legacy. This is not explicitly stated anywhere in HCI/LL part of + * the spec, but Vol 3, Part C, 9.1.1.2 (GAP) states: + * "A device in the Broadcast mode may send non-connectable and non- + * scannable undirected or non-connectable and non-scannable directed + * advertising events anonymously by excluding the Broadcaster's address." + * And Vol 4, Part E, 7.8.53 (HCI) states: + * "If the Advertising_Event_Properties parameter does not describe an + * event type supported by the Controller, contains an invalid bit + * combination, or specifies a type that does not support advertising + * data when the advertising set already contains some, the Controller + * shall return the error code Invalid HCI Command Parameters (0x12)." + * + * So let's just assume anonymous on connectable/scannable/legacy is an + * invalid bit combination. + */ + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV) { + if (props & (BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE | + BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE | + BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED | + BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + } + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { if (ADV_DATA_LEN(advsm) > BLE_ADV_LEGACY_DATA_MAX_LEN || SCAN_RSP_DATA_LEN(advsm) > BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN) { @@ -3587,6 +3685,9 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, advsm->sec_phy = cmd->sec_phy; /* Update SID only */ advsm->adi = (advsm->adi & 0x0fff) | ((cmd->sid << 12)); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + advsm->periodic_adv_adi = (advsm->periodic_adv_adi & 0x0fff) | ((cmd->sid << 12)); +#endif advsm->props = props; @@ -3615,6 +3716,59 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, return rc; } +#if MYNEWT_VAL(BLE_VERSION) >= 54 +static inline uint8_t +ble_ll_adv_convert_phy_opt(uint8_t cmd_phy_opt) +{ + switch (cmd_phy_opt) { + case BLE_HCI_ADVERTISING_PHY_OPT_NO_PREF: + return BLE_HCI_LE_PHY_CODED_ANY; + case BLE_HCI_ADVERTISING_PHY_OPT_S2_PREF: + case BLE_HCI_ADVERTISING_PHY_OPT_S2_REQ: + return BLE_HCI_LE_PHY_CODED_S2_PREF; + case BLE_HCI_ADVERTISING_PHY_OPT_S8_PREF: + case BLE_HCI_ADVERTISING_PHY_OPT_S8_REQ: + return BLE_HCI_LE_PHY_CODED_S8_PREF; + default: + BLE_LL_ASSERT(0); + } +} + +int +ble_ll_adv_ext_set_param_v2(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_set_ext_adv_params_v2_cp *cmd = (const void *) cmdbuf; + struct ble_ll_adv_sm *advsm; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if ((cmd->pri_phy_opt > BLE_HCI_ADVERTISING_PHY_OPT_S8_REQ) || + (cmd->sec_phy_opt > BLE_HCI_ADVERTISING_PHY_OPT_S8_REQ)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rc = ble_ll_adv_ext_set_param(cmdbuf, len - 2, rspbuf, rsplen); + if (rc != 0) { + return rc; + } + + advsm = ble_ll_adv_sm_get(cmd->params_v1.adv_handle); + + if (advsm->pri_phy == BLE_HCI_LE_PHY_CODED) { + advsm->pri_phy_opt = ble_ll_adv_convert_phy_opt(cmd->pri_phy_opt); + } + if (advsm->sec_phy == BLE_HCI_LE_PHY_CODED) { + advsm->sec_phy_opt = ble_ll_adv_convert_phy_opt(cmd->sec_phy_opt); + } + + return rc; +} +#endif + int ble_ll_adv_ext_set_adv_data(const uint8_t *cmdbuf, uint8_t cmdlen) { @@ -3978,8 +4132,8 @@ ble_ll_adv_periodic_set_param(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_PACKET_TOO_LONG; } - advsm->periodic_adv_itvl_min = adv_itvl_min; - advsm->periodic_adv_itvl_max = adv_itvl_max; + advsm->periodic_adv_itvl = adv_itvl_max; + advsm->padv_itvl_us = adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL; advsm->periodic_adv_props = props; ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED); @@ -4041,6 +4195,23 @@ ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len) case BLE_HCI_LE_SET_DATA_OPER_COMPLETE: new_data = true; break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + case BLE_HCI_LE_SET_DATA_OPER_UNCHANGED: + if (!advsm->periodic_adv_enabled) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (advsm->periodic_adv_data->om_len == 0) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->adv_data_len != 0) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + advsm->periodic_adv_adi = ble_ll_adv_update_did(advsm->periodic_adv_adi); + return BLE_ERR_SUCCESS; +#endif default: return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -4059,7 +4230,7 @@ ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len) */ if (!ble_ll_adv_periodic_check_data_itvl(payload_total_len, advsm->periodic_adv_props, - advsm->periodic_adv_itvl_max, + advsm->periodic_adv_itvl, advsm->sec_phy)) { return BLE_ERR_PACKET_TOO_LONG; } @@ -4117,10 +4288,14 @@ ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_UNK_ADV_INDENT; } -#if MYNEWT_VAL(BLE_VERSION) >= 53 +#if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) if (cmd->enable & 0x02) { return BLE_ERR_UNSUPPORTED; - } else if (cmd->enable & 0xfc) { + } +#endif + +#if MYNEWT_VAL(BLE_VERSION) >= 53 + if (cmd->enable & 0xfc) { return BLE_ERR_INV_HCI_CMD_PARMS; } #else @@ -4129,7 +4304,7 @@ ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len) } #endif - if (cmd->enable) { + if (cmd->enable & 0x1) { if (advsm->props & (BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV | BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE | BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE | @@ -4147,16 +4322,20 @@ ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len) /* If Enable is set to 0x01 and the length of the periodic advertising * data is greater than the maximum that the Controller can transmit - * within the chosen periodicadvertising interval, the Controller shall + * within the chosen periodic advertising interval, the Controller shall * return the error code Packet Too Long (0x45). */ if (!ble_ll_adv_periodic_check_data_itvl(SYNC_DATA_LEN(advsm), advsm->periodic_adv_props, - advsm->periodic_adv_itvl_max, + advsm->periodic_adv_itvl, advsm->sec_phy)) { return BLE_ERR_PACKET_TOO_LONG; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + advsm->periodic_include_adi = !!(cmd->enable & 0x2); +#endif + /* If the advertising set is not currently enabled (see the * LE_Set_Extended_Advertising_Enable command), the periodic advertising * is not started until the advertising set is enabled. @@ -4742,8 +4921,10 @@ ble_ll_adv_rx_isr_start(uint8_t pdu_type) } static void -ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm) +ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm, bool preempted) { + os_sr_t sr; + STATS_INC(ble_ll_stats, adv_drop_event); ble_ll_sched_rmv_elem(&advsm->adv_sch); @@ -4755,6 +4936,12 @@ ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm) advsm->aux_active = 0; #endif + if (preempted) { + OS_ENTER_CRITICAL(sr); + advsm->retry_event = !(advsm->flags & BLE_LL_ADV_SM_FLAG_ACTIVE_CHANSET_MASK); + OS_EXIT_CRITICAL(sr); + } + advsm->adv_chan = ble_ll_adv_final_chan(advsm); ble_ll_event_add(&advsm->adv_txdone_ev); } @@ -4779,7 +4966,7 @@ ble_ll_adv_reschedule_event(struct ble_ll_adv_sm *advsm) rc = ble_ll_sched_adv_reschedule(sch, max_delay_ticks); if (rc) { - ble_ll_adv_drop_event(advsm); + ble_ll_adv_drop_event(advsm, 0); return; } @@ -4845,25 +5032,35 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) final_adv_chan = ble_ll_adv_final_chan(advsm); if (advsm->adv_chan == final_adv_chan) { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (advsm->events_max) { - advsm->events++; - } -#endif - ble_ll_scan_chk_resume(); /* This event is over. Set adv channel to first one */ advsm->adv_chan = ble_ll_adv_first_chan(advsm); - /* - * Calculate start time of next advertising event. NOTE: we do not - * add the random advDelay as the scheduling code will do that. - */ itvl = advsm->adv_itvl_usecs; tick_itvl = ble_ll_tmr_u2t(itvl); - advsm->adv_event_start_time += tick_itvl; - advsm->adv_pdu_start_time = advsm->adv_event_start_time; + + /* do not calculate new event time if current event should be retried; + * this happens if event was preempted, so we just try to schedule one + * more time with the same start time + */ + + if (!advsm->retry_event) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (advsm->events_max) { + advsm->events++; + } +#endif + + /* + * Calculate start time of next advertising event. NOTE: we do not + * add the random advDelay as the scheduling code will do that. + */ + advsm->adv_event_start_time += tick_itvl; + advsm->adv_pdu_start_time = advsm->adv_event_start_time; + } else { + advsm->retry_event = 0; + } /* * The scheduled time better be in the future! If it is not, we will @@ -4909,7 +5106,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) advsm->aux_active && LL_TMR_GT(advsm->adv_pdu_start_time, AUX_CURRENT(advsm)->start_time)) { - ble_ll_adv_drop_event(advsm); + ble_ll_adv_drop_event(advsm, 0); return; } #endif @@ -5009,7 +5206,7 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm) ble_ll_rfmgmt_release(); if (advsm->aux_dropped) { - ble_ll_adv_drop_event(advsm); + ble_ll_adv_drop_event(advsm, 0); return; } @@ -5311,6 +5508,23 @@ ble_ll_adv_sync_get(uint8_t handle) return advsm; } +int +ble_ll_adv_padv_event_start_get(struct ble_ll_adv_sm *advsm, + uint32_t *event_start, + uint8_t *event_start_rem_us) +{ + if (!advsm || !advsm->periodic_adv_active) { + return -EINVAL; + } + + *event_start = advsm->padv_event_start; + if (event_start_rem_us) { + *event_start_rem_us = advsm->padv_event_start_rem_us; + } + + return 0; +} + int ble_ll_adv_sync_big_add(struct ble_ll_adv_sm *advsm, struct ble_ll_iso_big *big) @@ -5358,4 +5572,5 @@ ble_ll_adv_init(void) } #endif -#endif \ No newline at end of file + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_conn.c b/src/nimble/nimble/controller/src/ble_ll_conn.c index e01c24a33..3be7a3f1e 100644 --- a/src/nimble/nimble/controller/src/ble_ll_conn.c +++ b/src/nimble/nimble/controller/src/ble_ll_conn.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM #include #include @@ -47,7 +48,7 @@ #include "ble_ll_ctrl_priv.h" #include "ble_ll_priv.h" #if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc -#include +#include #endif #if (BLETEST_THROUGHPUT_TEST == 1) @@ -555,7 +556,7 @@ ble_ll_conn_find_by_peer_addr(const uint8_t *addr, uint8_t addr_type) return NULL; } -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) static inline int ble_ll_conn_phy_should_update(uint8_t pref_mask, uint8_t curr_mask) { @@ -587,7 +588,7 @@ ble_ll_conn_phy_update_if_needed(struct ble_ll_conn_sm *connsm) connsm->phy_data.pref_mask_tx_req = connsm->phy_data.pref_mask_tx; connsm->phy_data.pref_mask_rx_req = connsm->phy_data.pref_mask_rx; - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); return 0; } @@ -973,11 +974,21 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) if (connsm->flags.encrypt_ltk_req) { /* * Send Long term key request event to host. If masked, we need to - * send a REJECT_IND. + * send a REJECT_IND or TERMINATE_IND. */ if (ble_ll_hci_ev_ltk_req(connsm)) { - ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, - BLE_ERR_PINKEY_MISSING); + /* Core 6.1 | Vol 6, Part B | 5.1.3.1 + * If this procedure is being performed after a Pause Encryption procedure, and the + * Peripheral's Host does not provide a Long Term Key, the Peripheral shall perform the + * ACL Termination procedure with the error code PIN or Key Missing (0x06). + */ + if (connsm->flags.encrypt_paused) { + connsm->disconnect_reason = BLE_ERR_PINKEY_MISSING; + ble_ll_ctrl_terminate_start(connsm); + } else { + ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, + BLE_ERR_PINKEY_MISSING); + } } connsm->flags.encrypt_ltk_req = 0; } @@ -1004,7 +1015,7 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) } /* Check if we need to send PHY update complete event */ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) if (connsm->flags.phy_update_host_w4event) { if (!ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS)) { /* Sent event. Clear flag */ @@ -1041,7 +1052,7 @@ ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) uint16_t max_pyld_len; uint16_t ret; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) uint8_t phy_mode; if (connsm->phy_tx_transition) { @@ -1269,7 +1280,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) * now. This is not the most accurate especially if we have * received a frame and we are replying to it. */ -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) tx_phy_mode = connsm->phy_data.tx_phy_mode; #else tx_phy_mode = BLE_PHY_MODE_1M; @@ -1302,7 +1313,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) m->om_data = (uint8_t *)&empty_pdu; m->om_data += BLE_MBUF_MEMBLOCK_OVERHEAD; ble_hdr = &empty_pdu.ble_hdr; - ble_hdr->txinfo.flags = 0; + ble_hdr->txinfo.num_data_pkt = 0; ble_hdr->txinfo.offset = 0; ble_hdr->txinfo.pyld_len = 0; } @@ -1342,7 +1353,8 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) (CONN_IS_PERIPHERAL(connsm) && (md == 0) && (connsm->cons_rxd_bad_crc == 0) && ((connsm->last_rxd_hdr_byte & BLE_LL_DATA_HDR_MD_MASK) == 0) && - !ble_ll_ctrl_is_terminate_ind(hdr_byte, m->om_data[0]))) { + ((connsm->flags.empty_pdu_txd) || + !ble_ll_ctrl_is_terminate_ind(hdr_byte, m->om_data[0])))) { /* We will end the connection event */ end_transition = BLE_PHY_TRANSITION_NONE; txend_func = ble_ll_conn_wait_txend; @@ -1523,7 +1535,7 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) ble_phy_resolv_list_disable(); #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) ble_phy_mode_set(connsm->phy_data.tx_phy_mode, connsm->phy_data.rx_phy_mode); #endif @@ -1660,7 +1672,7 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime, uint32_t allowed_usecs; int tx_phy_mode; -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) tx_phy_mode = connsm->phy_data.tx_phy_mode; #else tx_phy_mode = BLE_PHY_MODE_1M; @@ -1727,7 +1739,7 @@ ble_ll_conn_auth_pyld_timer_cb(struct ble_npl_event *ev) connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); ble_ll_auth_pyld_tmo_event_send(connsm); - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_LE_PING, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_LE_PING); ble_ll_conn_auth_pyld_timer_start(connsm); } @@ -1839,6 +1851,21 @@ ble_ll_conn_set_data_len(struct ble_ll_conn_sm *connsm, tx_time = MIN(tx_time, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); rx_time = MIN(rx_time, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); } +#else + tx_time = MIN(tx_time, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); + rx_time = MIN(rx_time, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); +#endif + +#if !MYNEWT_VAL(BLE_LL_CONN_INIT_AUTO_DLE) + if (connsm->eff_max_tx_octets != tx_octets) { + connsm->max_tx_octets = tx_octets; + init_dle = 1; + } + + if (rx_octets && connsm->eff_max_rx_octets != rx_octets) { + connsm->max_rx_octets = rx_octets; + init_dle = 1; + } #endif if (connsm->max_tx_time != tx_time) { @@ -1869,7 +1896,7 @@ ble_ll_conn_set_data_len(struct ble_ll_conn_sm *connsm, } #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) static void ble_ll_conn_set_phy(struct ble_ll_conn_sm *connsm, int tx_phy, int rx_phy) @@ -2006,7 +2033,7 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) #endif /* XXX: TODO set these based on PHY that started connection */ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) connsm->phy_data.cur_tx_phy = BLE_PHY_1M; connsm->phy_data.cur_rx_phy = BLE_PHY_1M; connsm->phy_data.tx_phy_mode = BLE_PHY_MODE_1M; @@ -2035,6 +2062,8 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) /* Initialize transmit queue and ack/flow control elements */ STAILQ_INIT(&connsm->conn_txq); + connsm->conn_txq_num_data_pkt = 0; + connsm->conn_txq_num_zero_pkt = 0; connsm->cur_tx_pdu = NULL; connsm->tx_seqnum = 0; connsm->next_exp_seqnum = 0; @@ -2137,7 +2166,7 @@ ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm) * connection events timings. */ if (ota_max_rx_time_calc) { -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) phy_mode = ble_ll_phy_to_phy_mode(connsm->phy_data.cur_rx_phy, BLE_HCI_LE_PHY_CODED_S8_PREF); #else @@ -2276,10 +2305,20 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err) connsm->event_cntr, (uint32_t)ble_err); } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) void -ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, +ble_ll_conn_anchor_get(struct ble_ll_conn_sm *connsm, uint16_t *event_cntr, uint32_t *anchor, uint8_t *anchor_usecs) +{ + *event_cntr = connsm->event_cntr; + *anchor = connsm->anchor_point; + *anchor_usecs = connsm->anchor_point_usecs; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +void +ble_ll_conn_anchor_event_cntr_get(struct ble_ll_conn_sm *connsm, + uint16_t event_cntr, uint32_t *anchor, + uint8_t *anchor_usecs) { uint32_t itvl; @@ -2288,11 +2327,11 @@ ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, *anchor = connsm->anchor_point; *anchor_usecs = connsm->anchor_point_usecs; - if ((int16_t)(conn_event - connsm->event_cntr) < 0) { - itvl *= connsm->event_cntr - conn_event; + if ((int16_t)(event_cntr - connsm->event_cntr) < 0) { + itvl *= connsm->event_cntr - event_cntr; ble_ll_tmr_sub(anchor, anchor_usecs, itvl); } else { - itvl *= conn_event - connsm->event_cntr; + itvl *= event_cntr - connsm->event_cntr; ble_ll_tmr_add(anchor, anchor_usecs, itvl); } } @@ -2310,7 +2349,7 @@ ble_ll_conn_move_anchor(struct ble_ll_conn_sm *connsm, uint16_t offset) } connsm->conn_update_anchor_offset_req = offset; - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE); return 0; } @@ -2528,15 +2567,16 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) if (connsm->flags.conn_update_sched && (connsm->event_cntr == connsm->conn_update_req.instant)) { - /* Set flag so we send connection update event */ + /* Set flag to send event to host if request was issued by host or + * any of parameters changed (i.e. skip on anchor moves) + */ upd = &connsm->conn_update_req; - if (CONN_IS_CENTRAL(connsm) || - (CONN_IS_PERIPHERAL(connsm) && - IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) || + if (connsm->flags.conn_update_host_initd || (connsm->conn_itvl != upd->interval) || (connsm->periph_latency != upd->latency) || (connsm->supervision_tmo != upd->timeout)) { connsm->flags.conn_update_host_w4event = 1; + connsm->flags.conn_update_host_initd = 0; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) @@ -2640,7 +2680,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) } #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) if (connsm->flags.phy_update_sched && (connsm->event_cntr == connsm->phy_instant)) { @@ -2847,7 +2887,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) /* Send connection complete event to inform host of connection */ if (rc) { -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) && MYNEWT_VAL(BLE_LL_CONN_PHY_INIT_UPDATE) +#if MYNEWT_VAL(BLE_LL_PHY) && MYNEWT_VAL(BLE_LL_CONN_PHY_INIT_UPDATE) /* * If we have default phy preferences and they are different than * the current PHY's in use, start update procedure. @@ -2884,8 +2924,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) * models; for peripheral just assume central will initiate features xchg * if it has some additional features to use. */ - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG, - NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); break; #endif #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) @@ -3119,15 +3158,20 @@ ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm, /* XXX: do this ahead of time? Calculate the local rpa I mean */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if ((connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) && - (addrd->rpa_index >= 0)) { - /* We are using RPA and advertiser was on our resolving list, so - * we'll use RPA to reply (see Core 5.3, Vol 6, Part B, 6.4). - */ - rl = &g_ble_ll_resolv_list[addrd->rpa_index]; - if (rl->rl_has_local) { + if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { + if (addrd->rpa_index >= 0) { + /* We are using RPA and advertiser was on our resolving list, so + * we'll use RPA to reply (see Core 5.3, Vol 6, Part B, 6.4). + */ + rl = &g_ble_ll_resolv_list[addrd->rpa_index]; + if (rl->rl_has_local) { + hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; + ble_ll_resolv_get_priv_addr(rl, 1, pdu_data->inita); + addr = NULL; + } + } else if (ble_ll_resolv_local_rpa_get(connsm->own_addr_type & 1, + pdu_data->inita) == 0) { hdr |= BLE_ADV_PDU_HDR_TXADD_RAND; - ble_ll_resolv_get_priv_addr(rl, 1, pdu_data->inita); addr = NULL; } } @@ -3145,7 +3189,8 @@ ble_ll_conn_prepare_connect_ind(struct ble_ll_conn_sm *connsm, pdu_data->hdr_byte = hdr; } -uint8_t +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +static uint8_t ble_ll_conn_tx_connect_ind_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) { struct ble_ll_conn_sm *connsm; @@ -3179,6 +3224,7 @@ ble_ll_conn_tx_connect_ind_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_by return 34; } +#endif /** * Called when a schedule item overlaps the currently running connection @@ -3207,25 +3253,47 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu, { struct ble_ll_conn_sm *connsm; struct ble_mbuf_hdr *rxhdr; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) uint8_t phy; -#endif + uint8_t phy_mode; + uint32_t sch_next; + uint32_t conn_req_us; + uint32_t conn_req_end; int rc; connsm = g_ble_ll_conn_create_sm.connsm; rxhdr = BLE_MBUF_HDR_PTR(rxpdu); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - if (ext) { -#if BLE_LL_BT5_PHY_SUPPORTED - phy = rxhdr->rxinfo.phy; +#if MYNEWT_VAL(BLE_LL_PHY) + phy = rxhdr->rxinfo.phy; + phy_mode = rxhdr->rxinfo.phy_mode; #else - phy = BLE_PHY_1M; + phy = BLE_PHY_1M; + phy_mode = BLE_PHY_MODE_1M; #endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (ext) { ble_ll_conn_create_set_params(connsm, phy); } +#else + (void)phy; #endif + rc = ble_ll_sched_next_time(&sch_next); + if (rc) { + conn_req_us = rxhdr->rem_usecs + ble_ll_pdu_us(34, phy_mode); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (ext) { + conn_req_us += BLE_LL_IFS + ble_ll_pdu_us(14, phy_mode); + } +#endif + conn_req_end = rxhdr->beg_cputime + ble_ll_tmr_u2t_up(conn_req_us); + + if (LL_TMR_LEQ(sch_next, conn_req_end)) { + return -1; + } + } + if (ble_ll_sched_conn_central_new(connsm, rxhdr, 0)) { return -1; } @@ -3241,7 +3309,7 @@ ble_ll_conn_send_connect_req(struct os_mbuf *rxpdu, return -1; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_PHY) if (ext) { ble_ll_conn_init_phy(connsm, phy); } @@ -3256,6 +3324,9 @@ ble_ll_conn_send_connect_req_cancel(void) struct ble_ll_conn_sm *connsm; connsm = g_ble_ll_conn_create_sm.connsm; + if (connsm == NULL) { + return; + } ble_ll_sched_rmv_elem(&connsm->conn_sch); } @@ -3289,7 +3360,7 @@ ble_ll_conn_central_start(uint8_t phy, uint8_t csa, #endif ble_ll_conn_set_csa(connsm, csa); -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) ble_ll_conn_init_phy(connsm, phy); #endif ble_ll_conn_created(connsm, NULL); @@ -3317,12 +3388,12 @@ ble_ll_conn_created_on_aux(struct os_mbuf *rxpdu, struct ble_ll_scan_addr_data *addrd, uint8_t *targeta) { -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) struct ble_mbuf_hdr *rxhdr; #endif uint8_t phy; -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) rxhdr = BLE_MBUF_HDR_PTR(rxpdu); phy = rxhdr->rxinfo.phy; #else @@ -3491,7 +3562,7 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) CONN_IS_CENTRAL(connsm)) || (connsm->enc_data.enc_state >= CONN_ENC_S_ENC_RSP_TO_BE_SENT && CONN_IS_PERIPHERAL(connsm))) { - if (!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) { + if (!ble_ll_ctrl_enc_allowed_pdu_rx(connsm, rxpdu)) { ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); goto conn_rx_data_pdu_end; } @@ -3699,7 +3770,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) * to the 'additional usecs' field to save some calculations. */ begtime = rxhdr->beg_cputime; -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) rx_phy_mode = connsm->phy_data.rx_phy_mode; #else rx_phy_mode = BLE_PHY_MODE_1M; @@ -3714,30 +3785,15 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) */ if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) { /* - * Increment # of consecutively received CRC errors. If more than - * one we will end the connection event. + * Increment # of consecutively received CRC errors. + * + * If more than one, we will end the connection event and no reply is needed. + * If less or equal to one, we always reply: + * - peripheral always replies + * - central replies to allow peripheral retransmit the packet */ ++connsm->cons_rxd_bad_crc; - if (connsm->cons_rxd_bad_crc >= 2) { - reply = 0; - } else { - switch (connsm->conn_role) { -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) - case BLE_LL_CONN_ROLE_CENTRAL: - reply = connsm->flags.last_txd_md; - break; -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) - case BLE_LL_CONN_ROLE_PERIPHERAL: - /* A peripheral always responds with a packet */ - reply = 1; - break; -#endif - default: - BLE_LL_ASSERT(0); - break; - } - } + reply = connsm->cons_rxd_bad_crc < 2; } else { /* Reset consecutively received bad crcs (since this one was good!) */ connsm->cons_rxd_bad_crc = 0; @@ -3824,7 +3880,8 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) #if (BLETEST_THROUGHPUT_TEST == 1) bletest_completed_pkt(connsm->conn_handle); #endif - ++connsm->completed_pkts; + BLE_LL_ASSERT(txhdr->txinfo.num_data_pkt >= 1); + connsm->completed_pkts += txhdr->txinfo.num_data_pkt; if (connsm->completed_pkts > 2) { ble_ll_event_add(&g_ble_ll_data.ll_comp_pkt_ev); } @@ -3835,7 +3892,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) rem_bytes = OS_MBUF_PKTLEN(txpdu) - txhdr->txinfo.offset; /* Adjust payload for max TX time and octets */ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) if (BLE_LL_LLID_IS_CTRL(hdr_byte) && CONN_IS_PERIPHERAL(connsm) && (opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) { @@ -3925,17 +3982,46 @@ ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, os_sr_t sr; struct os_mbuf_pkthdr *pkthdr; struct ble_mbuf_hdr *ble_hdr; + uint8_t num_pkt; int lifo; + /* We cannot send empty payload with LLID=0b10. Instead, we need to wait for + * non-empty payload and combine it together. Since we don't really recombine + * fragments we just count number of consecutive empty payloads and use 1st + * non-empty as a start packet. Empty payloads can be freed immediately as + * we don't need to enqueue them. + * + * Reference: Core 6.0, Vol 6, Part B, 2.4.1 + */ + if ((length == 0) && + ((hdr_byte == BLE_LL_LLID_DATA_START) || (connsm->conn_txq_num_zero_pkt > 0))) { + connsm->conn_txq_num_zero_pkt++; + os_mbuf_free_chain(om); + return; + } + /* Set mbuf length and packet length if a control PDU */ if (hdr_byte == BLE_LL_LLID_CTRL) { om->om_len = length; OS_MBUF_PKTHDR(om)->omp_len = length; + num_pkt = 0; + } else { + num_pkt = 1; + + /* This is the 1st non-empty data fragment so adjust LLID accordingly. + * num_pkt is updated to make sure we send back proper numbber of + * completed packets back to host. + */ + if (connsm->conn_txq_num_zero_pkt) { + hdr_byte = BLE_LL_LLID_DATA_START; + num_pkt += connsm->conn_txq_num_zero_pkt; + connsm->conn_txq_num_zero_pkt = 0; + } } /* Set BLE transmit header */ ble_hdr = BLE_MBUF_HDR_PTR(om); - ble_hdr->txinfo.flags = 0; + ble_hdr->txinfo.num_data_pkt = num_pkt; ble_hdr->txinfo.offset = 0; ble_hdr->txinfo.hdr_byte = hdr_byte; @@ -3994,6 +4080,7 @@ ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om, } else { STAILQ_INSERT_TAIL(&connsm->conn_txq, pkthdr, omp_next); } + connsm->conn_txq_num_data_pkt += num_pkt; OS_EXIT_CRITICAL(sr); } @@ -4050,7 +4137,7 @@ ble_ll_conn_chan_map_update(void) /* Perform channel map update */ SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD); } } #endif @@ -4168,7 +4255,7 @@ ble_ll_conn_periph_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr connsm->conn_role = BLE_LL_CONN_ROLE_PERIPHERAL; ble_ll_conn_sm_new(connsm); -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) /* Use the same PHY as we received CONNECT_REQ on */ ble_ll_conn_init_phy(connsm, rxhdr->rxinfo.phy); #endif @@ -4246,14 +4333,14 @@ ble_ll_conn_subrate_req_hci(struct ble_ll_conn_sm *connsm, connsm->subrate_trans.cont_num = srp->cont_num; connsm->subrate_trans.supervision_tmo = srp->supervision_tmo; connsm->flags.subrate_host_req = 1; - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_UPDATE, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_UPDATE); break; #endif #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CONN_ROLE_PERIPHERAL: connsm->subrate_req = *srp; connsm->flags.subrate_host_req = 1; - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_REQ, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_REQ); break; #endif default: @@ -4302,7 +4389,7 @@ ble_ll_conn_subrate_req_llcp(struct ble_ll_conn_sm *connsm, connsm->subrate_trans.supervision_tmo = MIN(connsm->supervision_tmo, srp->supervision_tmo); - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_UPDATE, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_UPDATE); return 0; } @@ -4499,6 +4586,6 @@ ble_ll_conn_module_init(void) /* Call reset to finish reset of initialization */ ble_ll_conn_module_reset(); } - -#endif #endif + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_conn_hci.c b/src/nimble/nimble/controller/src/ble_ll_conn_hci.c index 3b1a4d161..e33ff4562 100644 --- a/src/nimble/nimble/controller/src/ble_ll_conn_hci.c +++ b/src/nimble/nimble/controller/src/ble_ll_conn_hci.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM #include #include @@ -33,6 +34,7 @@ #include "nimble/nimble/controller/include/controller/ble_ll_ctrl.h" #include "nimble/nimble/controller/include/controller/ble_ll_scan.h" #include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "ble_ll_priv.h" #include "ble_ll_conn_priv.h" #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) @@ -42,7 +44,6 @@ * event to the host. This is the os time at which we can send an event. */ static ble_npl_time_t g_ble_ll_last_num_comp_pkt_evt; -extern uint8_t *g_ble_ll_conn_comp_ev; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static const uint8_t ble_ll_conn_create_valid_phy_mask = ( @@ -63,6 +64,9 @@ static const uint8_t ble_ll_conn_create_required_phy_mask = ( 0); #endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +extern uint8_t *g_ble_ll_conn_comp_ev; + /** * Allocate an event to send a connection complete event when initiating * @@ -87,6 +91,7 @@ ble_ll_init_alloc_conn_comp_ev(void) return rc; } +#endif /** * Called to check that the connection parameters are within range @@ -311,6 +316,8 @@ ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm) ev->completed[0].packets = htole16(connsm->completed_pkts); hci_ev->length += sizeof(ev->completed[0]); + BLE_LL_ASSERT(connsm->conn_txq_num_data_pkt >= connsm->completed_pkts); + connsm->conn_txq_num_data_pkt -= connsm->completed_pkts; connsm->completed_pkts = 0; ble_ll_hci_event_send(hci_ev); @@ -331,7 +338,7 @@ ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm) * event and that either has packets enqueued or has completed packets. */ if ((connsm->conn_state != BLE_LL_CONN_STATE_IDLE) && - (connsm->completed_pkts || !STAILQ_EMPTY(&connsm->conn_txq))) { + (connsm->completed_pkts || connsm->conn_txq_num_data_pkt)) { /* If no buffer, get one, If cant get one, leave. */ if (!hci_ev) { hci_ev = ble_transport_alloc_evt(0); @@ -352,6 +359,8 @@ ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm) hci_ev->length += sizeof(ev->completed[ev->count]); ev->count++; + BLE_LL_ASSERT(connsm->conn_txq_num_data_pkt >= connsm->completed_pkts); + connsm->conn_txq_num_data_pkt -= connsm->completed_pkts; connsm->completed_pkts = 0; /* Send now if the buffer is full. */ @@ -453,7 +462,7 @@ ble_ll_conn_hci_create_check_scan(struct ble_ll_conn_create_scan *p) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (p->init_phy_mask & ~ble_ll_conn_create_valid_phy_mask) { - return BLE_ERR_INV_HCI_CMD_PARMS; + return BLE_ERR_UNSUPPORTED; } if (!(p->init_phy_mask & ble_ll_conn_create_required_phy_mask)) { @@ -464,6 +473,7 @@ ble_ll_conn_hci_create_check_scan(struct ble_ll_conn_create_scan *p) return 0; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) static int ble_ll_conn_hci_create_check_params(struct ble_ll_conn_create_params *cc_params) { @@ -636,6 +646,7 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len) return rc; } +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static void @@ -659,6 +670,7 @@ ble_ll_conn_hci_ext_create_set_fb_params(uint8_t init_phy_mask, #endif } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) static int ble_ll_conn_hci_ext_create_parse_params(const struct conn_params *params, uint8_t phy, @@ -864,6 +876,7 @@ ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len) return rc; } #endif +#endif static int ble_ll_conn_process_conn_params(const struct ble_hci_le_rem_conn_param_rr_cp *cmd, @@ -939,7 +952,7 @@ ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len) } #endif - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG); } connsm->flags.features_host_req = 1; @@ -1030,11 +1043,11 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) } #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - /* Do not allow connection update if css in enabled, we only allow to move - * anchor point (i.e. change slot) via dedicated HCI command. - */ + /* We only allow to change connection parameters if conn_itvl can stay unchanged */ if (ble_ll_sched_css_is_enabled() && - connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { + connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL && + (connsm->conn_itvl < le16toh(cmd->conn_itvl_min) || + connsm->conn_itvl > le16toh(cmd->conn_itvl_max))) { return BLE_ERR_CMD_DISALLOWED; } #endif @@ -1099,8 +1112,18 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) /* Retrieve command data */ hcu = &connsm->conn_param_req; +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + if (ble_ll_sched_css_is_enabled()) { + hcu->conn_itvl_max = connsm->conn_itvl; + hcu->conn_itvl_min = connsm->conn_itvl; + } else { + hcu->conn_itvl_min = le16toh(cmd->conn_itvl_min); + hcu->conn_itvl_max = le16toh(cmd->conn_itvl_max); + } +#else hcu->conn_itvl_min = le16toh(cmd->conn_itvl_min); hcu->conn_itvl_max = le16toh(cmd->conn_itvl_max); +#endif hcu->conn_latency = le16toh(cmd->conn_latency); hcu->supervision_timeout = le16toh(cmd->supervision_timeout); hcu->min_ce_len = le16toh(cmd->min_ce_len); @@ -1117,8 +1140,15 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) if (!rc) { hcu->handle = handle; +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + connsm->css_slot_idx_pending = connsm->css_slot_idx; +#endif + + /* Mark procedure as host initiated */ + connsm->flags.conn_update_host_initd = 1; + /* Start the control procedure */ - ble_ll_ctrl_proc_start(connsm, ctrl_proc, NULL); + ble_ll_ctrl_proc_start(connsm, ctrl_proc); } return rc; @@ -1244,6 +1274,7 @@ ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, return rc; } +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* this is called from same context after cmd complete is send so it is * safe to use g_ble_ll_conn_comp_ev */ @@ -1297,6 +1328,7 @@ ble_ll_conn_create_cancel(void) return rc; } +#endif /** * Called to process a HCI disconnect command @@ -1395,7 +1427,7 @@ ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len) * be queued before the command status. */ if (!connsm->flags.version_ind_txd) { - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG); } else { connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_VERSION_XCHG); } @@ -1515,7 +1547,8 @@ ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, tx_time = le16toh(cmd->tx_time); if (!ble_ll_hci_check_dle(tx_octets, tx_time)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; } rc = ble_ll_conn_set_data_len(connsm, tx_octets, tx_time, 0, 0); @@ -1566,7 +1599,7 @@ ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len) connsm->enc_data.host_rand_num = le64toh(cmd->rand); connsm->enc_data.enc_div = le16toh(cmd->div); swap_buf(connsm->enc_data.enc_block.key, cmd->ltk, 16); - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_ENCRYPT, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_ENCRYPT); rc = BLE_ERR_SUCCESS; } @@ -1679,9 +1712,19 @@ ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len, goto ltk_key_cmd_complete; } - /* We received a negative reply! Send REJECT_IND */ - ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, - BLE_ERR_PINKEY_MISSING); + /* Core 6.1 | Vol 6, Part B | 5.1.3.1 + * If this procedure is being performed after a Pause Encryption procedure, and the + * Peripheral's Host does not provide a Long Term Key, the Peripheral shall perform the + * ACL Termination procedure with the error code PIN or Key Missing (0x06). + */ + if (connsm->flags.encrypt_paused) { + connsm->disconnect_reason = BLE_ERR_PINKEY_MISSING; + ble_ll_ctrl_terminate_start(connsm); + } else { + /* We received a negative reply! Send REJECT_IND */ + ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, BLE_ERR_PINKEY_MISSING); + } + connsm->enc_data.enc_state = CONN_ENC_S_LTK_NEG_REPLY; rc = BLE_ERR_SUCCESS; @@ -1716,7 +1759,7 @@ ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len, return BLE_ERR_CTLR_BUSY; } - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE); return 0; } @@ -1918,7 +1961,40 @@ ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len, } #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +int +ble_ll_conn_hci_cb_read_tx_pwr(const uint8_t *cmdbuf, uint8_t len, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_cb_read_tx_pwr_cp *cmd = (const void *)cmdbuf; + struct ble_hci_cb_read_tx_pwr_rp *rsp = (void *)rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t handle; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (cmd->type != 0x01) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_by_handle(handle); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; + } + + rsp->conn_handle = cmd->conn_handle; + rsp->tx_level = g_ble_ll_tx_power; + + *rsplen = sizeof(*rsp); + + return BLE_ERR_SUCCESS; +} +#endif + +#if MYNEWT_VAL(BLE_LL_PHY) /** * Read current phy for connection (OGF=8, OCF==0x0030) * @@ -2070,13 +2146,23 @@ ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len, goto done; } - if ((MYNEWT_VAL(BLE_VERSION) >= 53 ) && (cmd->mode == 0x03)) { - /* We do not support ADI in periodic advertising thus cannot enable - * duplicate filtering. - */ - return BLE_ERR_UNSUPPORTED; + if (MYNEWT_VAL(BLE_VERSION) >= 53) { + if (cmd->mode > 0x03) { + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; + } + + if ((cmd->mode == 0x03) && + !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)) { + /* We do not support ADI in periodic advertising thus cannot enable + * duplicate filtering. + */ + rc = BLE_ERR_UNSUPPORTED; + goto done; + } } else if (cmd->mode > 0x02) { - return BLE_ERR_INV_HCI_CMD_PARMS; + rc = BLE_ERR_INV_HCI_CMD_PARMS; + goto done; } skip = le16toh(cmd->skip); @@ -2127,11 +2213,18 @@ ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } - if ((MYNEWT_VAL(BLE_VERSION) >= 53 ) && (cmd->mode == 0x03)) { - /* We do not support ADI in periodic advertising thus cannot enable - * duplicate filtering. - */ - return BLE_ERR_UNSUPPORTED; + if (MYNEWT_VAL(BLE_VERSION) >= 53) { + if (cmd->mode > 0x03) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if ((cmd->mode == 0x03) && + !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)) { + /* We do not support ADI in periodic advertising thus cannot enable + * duplicate filtering. + */ + return BLE_ERR_UNSUPPORTED; + } } else if (cmd->mode > 0x02) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -2160,4 +2253,5 @@ ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len) } #endif #endif -#endif + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_conn_priv.h b/src/nimble/nimble/controller/src/ble_ll_conn_priv.h index 09546bed2..489914038 100644 --- a/src/nimble/nimble/controller/src/ble_ll_conn_priv.h +++ b/src/nimble/nimble/controller/src/ble_ll_conn_priv.h @@ -197,14 +197,21 @@ void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm); int ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd); int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len); + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) int ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_conn_create_cancel(void); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +int ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len); +#endif +#endif + int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); int ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_create_cancel(void); void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm); void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, uint8_t *evbuf, struct ble_ll_adv_sm *advsm); @@ -227,6 +234,9 @@ 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); +int ble_ll_conn_hci_cb_read_tx_pwr(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); @@ -264,9 +274,6 @@ int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len, uint8_t *rsp, uint8_t *rsplen); int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len); int ble_ll_conn_phy_update_if_needed(struct ble_ll_conn_sm *connsm); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -int ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len); -#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) int ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len, diff --git a/src/nimble/nimble/controller/src/ble_ll_crypto.c b/src/nimble/nimble/controller/src/ble_ll_crypto.c index 15d62ebf3..0406705af 100644 --- a/src/nimble/nimble/controller/src/ble_ll_crypto.c +++ b/src/nimble/nimble/controller/src/ble_ll_crypto.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,11 +20,11 @@ */ #include -#include -#include -#include -#include -#include +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/controller/include/controller/ble_ll_crypto.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" int ble_ll_crypto_cmac(const uint8_t *key, const uint8_t *in, int len, @@ -60,3 +62,5 @@ ble_ll_crypto_h8(const uint8_t *k, const uint8_t *s, const uint8_t *key_id, return ble_ll_crypto_cmac(ik, key_id, 4, out); } + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_cs.c b/src/nimble/nimble/controller/src/ble_ll_cs.c new file mode 100644 index 000000000..16337f10a --- /dev/null +++ b/src/nimble/nimble/controller/src/ble_ll_cs.c @@ -0,0 +1,123 @@ +#ifndef ESP_PLATFORM + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#if MYNEWT_VAL(BLE_LL_CHANNEL_SOUNDING) +#include +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_conn.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_cs.h" + +int +ble_ll_cs_hci_rd_loc_supp_cap(uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_rd_rem_supp_cap(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_wr_cached_rem_supp_cap(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_sec_enable(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_set_def_settings(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_rd_rem_fae(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_wr_cached_rem_fae(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_create_config(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_remove_config(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_set_proc_params(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_proc_enable(const uint8_t *cmdbuf, uint8_t cmdlen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_test(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + return BLE_ERR_UNSUPPORTED; +} + +int +ble_ll_cs_hci_test_end(void) +{ + return BLE_ERR_UNSUPPORTED; +} + +#endif /* BLE_LL_CHANNEL_SOUNDING */ + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_cs_drbg.c b/src/nimble/nimble/controller/src/ble_ll_cs_drbg.c new file mode 100644 index 000000000..7e43358c3 --- /dev/null +++ b/src/nimble/nimble/controller/src/ble_ll_cs_drbg.c @@ -0,0 +1,686 @@ +#ifndef ESP_PLATFORM + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#if MYNEWT_VAL(BLE_LL_CHANNEL_SOUNDING) +#include +#include +#include "nimble/porting/nimble/include/os/endian.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" +#include "ble_ll_cs_drbg_priv.h" +#if !(BABBLESIM || MYNEWT_VAL(SELFTEST)) +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#endif + +static const uint8_t rtt_seq_len[] = { 0, 4, 12, 4, 8, 12, 16 }; + +/** + * Security function e generates 128-bit encrypted_data from a 128-bit key + * and 128-bit data using the AES-128-bit block cypher. + */ +int +ble_ll_cs_drbg_e(const uint8_t *key, const uint8_t *data, uint8_t *out_data) +{ + struct ble_encryption_block ecb; + int rc = 0; + + /* The cryptographic function uses the leftmost to rightmost + * representation (MSO to LSO). + */ + swap_buf(ecb.key, key, BLE_ENC_BLOCK_SIZE); + swap_buf(ecb.plain_text, data, BLE_ENC_BLOCK_SIZE); + +#if BABBLESIM || MYNEWT_VAL(SELFTEST) + /* Use software to encrypt the data */ + mbedtls_aes_context aes_ctx; + mbedtls_aes_init(&aes_ctx); + mbedtls_aes_setkey_enc(&aes_ctx, ecb.key, 16 * 8); + rc = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, ecb.plain_text, + ecb.cipher_text); + mbedtls_aes_free(&aes_ctx); +#else + /* Use hardware to encrypt the data */ + rc = ble_hw_encrypt_block(&ecb); +#endif + + if (!rc) { + swap_buf(out_data, ecb.cipher_text, BLE_ENC_BLOCK_SIZE); + } else { + rc = -1; + } + + return rc; +} + +/** + * DRBG chain function f7. + * - k - 128-bit key + * - in - an input bit string whose length is a multiple of 128 bits and + * generates an output that is 128 bits long using a cipher block + * chaining technique. + * - out - processed bit string + */ +int +ble_ll_cs_drbg_f7(const uint8_t *k, const uint8_t *in, uint8_t len, uint8_t *out) +{ + int rc = 0; + int i; + const uint64_t *block; + uint64_t *hout = (uint64_t *)out; + + memset(hout, 0, 16); + + /* Starting with the leftmost bits (MSO) of input_bit_string, split into + * 128-bit blocks + */ + for (i = len - 16; i >= 0; i -= 16) { + block = (uint64_t *)&in[i]; + /* XOR a 128-bit block in two steps */ + *hout ^= *block; + *(hout + 1) ^= *(block + 1); + + rc = ble_ll_cs_drbg_e(k, out, out); + if (rc) { + break; + } + } + + return rc; +} + +/** + * DRBG derivation function f8. + * - input - 320-bit input bit string + * - sm - output, generated 256-bit seed material (SM) + */ +int +ble_ll_cs_drbg_f8(const uint8_t *input, uint8_t *sm) +{ + int rc; + uint8_t k[16] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + uint8_t k2[16] = { 0 }; + uint8_t x[16] = { 0 }; + /* buf contains V || S */ + uint8_t buf[80] = { 0 }; + uint8_t *s = buf; + uint8_t *v = buf + 64; + + /* S = 0x0000002800000020 || input_bit_string || 0x80 || + * 0x000000000000000000000000000000 + */ + s[15] = 0x80; + memcpy(s + 16, input, 40); + put_le64(s + 56, 0x0000002800000020); + + /* K2 = f7( K, V || S ) */ + rc = ble_ll_cs_drbg_f7(k, buf, 80, k2); + if (rc) { + return rc; + } + + /* V = 0x00000001000000000000000000000000 */ + v[12] = 0x01; + + /* X = f7( K, V || S ) */ + rc = ble_ll_cs_drbg_f7(k, buf, 80, x); + if (rc) { + return rc; + } + + /* Calculate the most significant part of SM: + * SM = e( K2, X ) + */ + rc = ble_ll_cs_drbg_e(k2, x, sm + 16); + if (rc) { + return rc; + } + + /* Calculate the least significant part of SM and concatenate + * both parts: + * SM = SM || e( K2, SM ) + */ + rc = ble_ll_cs_drbg_e(k2, sm + 16, sm); + + return rc; +} + +/** + * DRBG update function f9 is used to update and refresh a DRBG 128-bit + * temporal key K and a 128-bit nonce vector V using a 256-bit seed material + * (SM) that may carry fresh entropy. The SM value may also be 0 if f9 is + * called for backtracking purposes. + * - sm - 256-bit seed material + * - k_in - 128-bit key + * - v_in - 128-bit nonce vector + */ +int +ble_ll_cs_drbg_f9(const uint8_t *sm, uint8_t *k, uint8_t *v) +{ + int rc; + uint8_t x[32] = { 0 }; + uint64_t *x_p = (uint64_t *)x; + uint64_t *sm_p = (uint64_t *)sm; + + /* V = V[127:8] || (( V[7:0] + 1 ) mod 2^8) */ + v[0]++; + rc = ble_ll_cs_drbg_e(k, v, x + 16); + if (rc) { + return rc; + } + + v[0]++; + /* Again V = V[127:8] || (( V[7:0] + 1 ) mod 2^8) */ + rc = ble_ll_cs_drbg_e(k, v, x); + if (rc) { + return rc; + } + + /* X = X ⊕ SM */ + x_p[0] ^= sm_p[0]; + x_p[1] ^= sm_p[1]; + x_p[2] ^= sm_p[2]; + x_p[3] ^= sm_p[3]; + + memcpy(v, x, 16); + memcpy(k, x + 16, 16); + + return 0; +} + +/** + * DRBG instantiation function h9. + * - iv - 128-bit initialization vector (CS_IV) + * - in - 64-bit instantiation nonce (CS_IN) + * - pv - 128-bit personalization vector (CS_PV) + * - key - output, 128-bit temporal key (K_DRBG) + * - nonce_v - output, 128-bit nonce vector (V_DRBG) + */ +int +ble_ll_cs_drbg_h9(const uint8_t *iv, const uint8_t *in, const uint8_t *pv, + uint8_t *key, uint8_t *nonce_v) +{ + int rc; + uint8_t input_bit_string[40] = { 0 }; + uint8_t sm[32] = { 0 }; + + /* 320-bit input bit string created from concatenated vectors + * CS_IV || CS_IN || CS_PV + */ + memcpy(input_bit_string, pv, 16); + memcpy(input_bit_string + 16, in, 8); + memcpy(input_bit_string + 24, iv, 16); + + /* Generate seed material (SM) */ + rc = ble_ll_cs_drbg_f8(input_bit_string, sm); + if (rc) { + return rc; + } + + /* Generate K_DRBG and V_DRBG */ + memset(key, 0, 16); + memset(nonce_v, 0, 16); + rc = ble_ll_cs_drbg_f9(sm, key, nonce_v); + + return rc; +} + +/** + * Random bit generation function CS_DRBG + * - transaction_id - CSTransactionID, + * - drbg_ctx - the drbg context, already inited with keys, + * - output - output buffer, + * - len - number of bytes to be generated. + */ +int +ble_ll_cs_drbg_rand(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count, + uint8_t transaction_id, uint8_t *output, uint8_t len) +{ + int rc; + uint8_t rand_len = 0; + uint8_t nonce[16]; + struct ble_ll_cs_transaction_cache *cache = &drbg_ctx->t_cache[transaction_id]; + + /* Set the fixed values of the DRGB nonce */ + memcpy(nonce, drbg_ctx->nonce_v, sizeof(nonce)); + /* Set the Transaction_Counter */ + if (cache->last_step_count != step_count) { + cache->transaction_counter = 0; + cache->last_step_count = step_count; + } + nonce[0] += cache->transaction_counter; + /* Set the Transaction_Identifier */ + nonce[1] += transaction_id; + /* Set the CS Step_Counter */ + put_le16(&nonce[2], step_count + get_le16(&nonce[2])); + + while (len > 0) { + if (cache->free_bytes > 0) { + /* Use bytes from previous DRBG invocation */ + + if (len < cache->free_bytes) { + rand_len = len; + } else { + rand_len = cache->free_bytes; + } + + cache->free_bytes -= rand_len; + /* [0] is LSO, [15] is MSO. Return cached bytes starting from MSO. */ + memcpy(output, cache->random_bytes + cache->free_bytes, rand_len); + + len -= rand_len; + output += rand_len; + } else { + /* Invoke CS_DRBG to get fresh 128-bit sequence */ + rc = ble_ll_cs_drbg_e(drbg_ctx->key, nonce, cache->random_bytes); + if (rc) { + return rc; + } + + cache->free_bytes = sizeof(cache->random_bytes); + /* Increment the transaction counter */ + ++nonce[0]; + ++cache->transaction_counter; + } + } + + return 0; +} + +/** Channel Sounding random number generation function hr1 */ +int +ble_ll_cs_drbg_rand_hr1(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count, + uint8_t transaction_id, uint8_t r, uint8_t *r_out) +{ + int rc; + uint16_t t_rand; + uint8_t random_bits; + + if (r <= 1) { + *r_out = 0; + + return 0; + } + + rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, transaction_id, &random_bits, 1); + if (rc) { + return rc; + } + + t_rand = r * random_bits; + + if ((t_rand & 0xFF) < (256 % r)) { + rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, transaction_id, + &random_bits, 1); + *r_out = ((256 * random_bits * r) + t_rand) / 65536; + } else { + *r_out = t_rand / 256; + } + + return rc; +} + +int +ble_ll_cs_drbg_shuffle_cr1(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count, + uint8_t transaction_id, uint8_t *channel_array, + uint8_t *shuffled_array, uint8_t len) +{ + int rc; + uint8_t i, j; + + for (i = 0; i < len; ++i) { + rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count, transaction_id, i + 1, &j); + if (rc) { + return rc; + } + + if (i != j) { + shuffled_array[i] = shuffled_array[j]; + } + + shuffled_array[j] = channel_array[i]; + } + + return 0; +} + +static uint32_t +cs_autocorrelation_score(uint32_t sequence) +{ + int c; + uint32_t s, score = 0; + uint8_t i, k; + + for (k = 1; k <= 3; ++k) { + c = 0; + s = sequence; + for (i = 1; i <= 32 - k; ++i) { + c += (s & 1) ^ ((s >> k) & 1); + s >>= 1; + } + score += abs(2 * c - (32 - k)); + } + + return score; +} + +int +ble_ll_cs_drbg_generate_aa(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count, + uint32_t *initiator_aa, uint32_t *reflector_aa) +{ + int rc; + uint8_t buf[16]; + uint32_t s0, s1, s2, s3; + + rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, + BLE_LL_CS_DRBG_ACCESS_ADDRESS, buf, sizeof(buf)); + + if (rc) { + return rc; + } + + /* The buf[15] is the first generated octet */ + s0 = get_le32(&buf[12]); + s1 = get_le32(&buf[8]); + s2 = get_le32(&buf[4]); + s3 = get_le32(&buf[0]); + + /* The sequence with the lower autocorrelation score is selected + * as the CS Access Address. See 2.2.1 Channel Sounding Access Address + * selection rules. + */ + if (cs_autocorrelation_score(s0) < cs_autocorrelation_score(s1)) { + *initiator_aa = s0; + } else { + *initiator_aa = s1; + } + + if (cs_autocorrelation_score(s2) < cs_autocorrelation_score(s3)) { + *reflector_aa = s2; + } else { + *reflector_aa = s3; + } + + return 0; +} + +int +ble_ll_cs_drbg_rand_marker_position(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint16_t step_count, uint8_t rtt_type, + uint8_t *position1, uint8_t *position2) +{ + int rc; + uint8_t rand_range; + + if (rtt_type == BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE) { + rand_range = 29; + } else { /* BLE_LL_CS_RTT_96_BIT_SOUNDING_SEQUENCE */ + rand_range = 64; + } + + rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count, + BLE_LL_CS_DRBG_SEQ_MARKER_POSITION, + rand_range, position1); + if (rc) { + return -1; + } + + if (rtt_type == BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE) { + *position2 = 0xFF; + + return 0; + } + + rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count, + BLE_LL_CS_DRBG_SEQ_MARKER_POSITION, 75, position2); + if (rc) { + return -1; + } + + *position2 += 67; + if (*position2 > 92) { + /* Omit the second marker */ + *position2 = 0xFF; + } + + return 0; +} + +int +ble_ll_cs_drbg_rand_marker_selection(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t *marker_selection) +{ + int rc; + + if (drbg_ctx->marker_selection_free_bits == 0) { + rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, BLE_LL_CS_DRBG_SEQ_MARKER_SIGNAL, + &drbg_ctx->marker_selection_cache, 1); + if (rc) { + return rc; + } + + drbg_ctx->marker_selection_free_bits = 8; + } + + *marker_selection = drbg_ctx->marker_selection_cache & 0x80; + drbg_ctx->marker_selection_cache <<= 1; + --drbg_ctx->marker_selection_free_bits; + + return 0; +} + +int +ble_ll_cs_drbg_rand_main_mode_steps(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t main_mode_min_steps, + uint8_t main_mode_max_steps, + uint8_t *main_mode_steps) +{ + int rc; + uint8_t r; + uint8_t r_out; + + r = main_mode_max_steps - main_mode_min_steps + 1; + rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count, + BLE_LL_CS_DRBG_SUBEVT_SUBMODE, r, &r_out); + if (rc) { + return rc; + } + + *main_mode_steps = r_out + main_mode_min_steps; + + return 0; +} + +static int +ble_ll_cs_drbg_apply_marker_signal(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t *buf, uint8_t position) +{ + int rc; + uint16_t *byte_ptr; + uint16_t marker_signal; + uint8_t marker_selection; + uint8_t byte_id = 0; + uint8_t bit_offset = 0; + + rc = ble_ll_cs_drbg_rand_marker_selection(drbg_ctx, step_count, &marker_selection); + if (rc) { + return rc; + } + + if (marker_selection) { + /* '0011' in transmission order */ + marker_signal = 0b1100; + } else { + /* '1100' in transmission order */ + marker_signal = 0b0011; + } + + byte_id = position / 8; + byte_ptr = (uint16_t *)&buf[byte_id]; + bit_offset = position % 8; + *byte_ptr &= ~(0xF << bit_offset); + *byte_ptr |= ~(marker_signal << bit_offset); + + return 0; +} + +static int +ble_ll_cs_generate_sounding_sequence(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t rtt_type, + uint8_t *buf, uint8_t sequence_len) +{ + int rc; + uint8_t i; + uint8_t position1; + uint8_t position2; + + for (i = 0; i < sequence_len; ++i) { + buf[i] = 0b10101010; + } + + rc = ble_ll_cs_drbg_rand_marker_position(drbg_ctx, step_count, rtt_type, + &position1, &position2); + if (rc) { + return rc; + } + + rc = ble_ll_cs_drbg_apply_marker_signal(drbg_ctx, step_count, buf, position1); + if (rc) { + return rc; + } + + if (position2 != 0xFF) { + rc = ble_ll_cs_drbg_apply_marker_signal(drbg_ctx, step_count, buf, position2); + } + + return rc; +} + +int +ble_ll_cs_drbg_generate_sync_sequence(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t rtt_type, + uint8_t *buf, uint8_t *sequence_len) +{ + int rc = -1; + + *sequence_len = rtt_seq_len[rtt_type]; + + switch (rtt_type) { + case BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE: + rc = ble_ll_cs_generate_sounding_sequence(drbg_ctx, step_count, + rtt_type, buf, *sequence_len); + break; + case BLE_LL_CS_RTT_96_BIT_SOUNDING_SEQUENCE: + rc = ble_ll_cs_generate_sounding_sequence(drbg_ctx, step_count, + rtt_type, buf, *sequence_len); + break; + case BLE_LL_CS_RTT_32_BIT_RANDOM_SEQUENCE: + case BLE_LL_CS_RTT_64_BIT_RANDOM_SEQUENCE: + case BLE_LL_CS_RTT_96_BIT_RANDOM_SEQUENCE: + case BLE_LL_CS_RTT_128_BIT_RANDOM_SEQUENCE: + rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, + BLE_LL_CS_DRBG_RAND_SEQ_GENERATION, buf, + *sequence_len); + break; + default: + break; + } + + return rc; +} + +int +ble_ll_cs_drbg_rand_tone_ext_presence(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t *presence) +{ + int rc; + + if (drbg_ctx->tone_ext_presence_free_bits == 0) { + rc = ble_ll_cs_drbg_rand(drbg_ctx, step_count, + BLE_LL_CS_DRBG_T_PM_TONE_SLOT_PRESENCE, + &drbg_ctx->tone_ext_presence_cache, 1); + if (rc) { + return rc; + } + + drbg_ctx->tone_ext_presence_free_bits = 8; + } + + *presence = drbg_ctx->tone_ext_presence_cache & 0x80 ? 1 : 0; + drbg_ctx->tone_ext_presence_cache <<= 1; + --drbg_ctx->tone_ext_presence_free_bits; + + return 0; +} + +int +ble_ll_cs_drbg_rand_antenna_path_perm_id(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint16_t step_count, uint8_t n_ap, + uint8_t *ap_id) +{ + int rc; + uint8_t i; + uint8_t n_ap_f = 0; + + if (n_ap <= 1) { + *ap_id = 0; + + return 0; + } + + assert(n_ap <= 4); + + for (i = 1; i <= n_ap; ++i) { + n_ap_f *= i; + } + + rc = ble_ll_cs_drbg_rand_hr1(drbg_ctx, step_count, + BLE_LL_CS_DRBG_ANTENNA_PATH_PERMUTATION, + n_ap_f, ap_id); + + return rc; +} + +void +ble_ll_cs_drbg_clear_cache(struct ble_ll_cs_drbg_ctx *drbg_ctx) +{ + memset(drbg_ctx->t_cache, 0, sizeof(drbg_ctx->t_cache)); + drbg_ctx->marker_selection_cache = 0; + drbg_ctx->marker_selection_free_bits = 0; +} + +int +ble_ll_cs_drbg_init(struct ble_ll_cs_drbg_ctx *drbg_ctx) +{ + /* Calculate temporal key K and nonce vector V */ + return ble_ll_cs_drbg_h9(drbg_ctx->iv, drbg_ctx->in, drbg_ctx->pv, + drbg_ctx->key, drbg_ctx->nonce_v); +} + +void +ble_ll_cs_drbg_free(struct ble_ll_cs_drbg_ctx *drbg_ctx) +{ + memset(drbg_ctx, 0, sizeof(*drbg_ctx)); +} +#endif /* BLE_LL_CHANNEL_SOUNDING */ + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_cs_drbg_priv.h b/src/nimble/nimble/controller/src/ble_ll_cs_drbg_priv.h new file mode 100644 index 000000000..8229cd374 --- /dev/null +++ b/src/nimble/nimble/controller/src/ble_ll_cs_drbg_priv.h @@ -0,0 +1,125 @@ +/* + * 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_CS_DRBG_PRIV +#define H_BLE_LL_CS_DRBG_PRIV + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_LL_CS_DRBG_HOP_CHAN_NON_MODE0 (0x00) +#define BLE_LL_CS_DRBG_HOP_CHAN_MODE0 (0x01) +#define BLE_LL_CS_DRBG_SUBEVT_SUBMODE (0x02) +#define BLE_LL_CS_DRBG_T_PM_TONE_SLOT_PRESENCE (0x03) +#define BLE_LL_CS_DRBG_ANTENNA_PATH_PERMUTATION (0x04) +#define BLE_LL_CS_DRBG_ACCESS_ADDRESS (0x05) +#define BLE_LL_CS_DRBG_SEQ_MARKER_POSITION (0x06) +#define BLE_LL_CS_DRBG_SEQ_MARKER_SIGNAL (0x07) +#define BLE_LL_CS_DRBG_RAND_SEQ_GENERATION (0x08) +#define BLE_LL_CS_DRBG_BACKTRACKING_RESISTANCE (0x09) +#define BLE_LL_CS_DRBG_TRANSACTION_IDS_NUMBER (0x0a) + +#define BLE_LL_CS_RTT_AA_ONLY (0x00) +#define BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE (0x01) +#define BLE_LL_CS_RTT_96_BIT_SOUNDING_SEQUENCE (0x02) +#define BLE_LL_CS_RTT_32_BIT_RANDOM_SEQUENCE (0x03) +#define BLE_LL_CS_RTT_64_BIT_RANDOM_SEQUENCE (0x04) +#define BLE_LL_CS_RTT_96_BIT_RANDOM_SEQUENCE (0x05) +#define BLE_LL_CS_RTT_128_BIT_RANDOM_SEQUENCE (0x06) + +struct ble_ll_cs_transaction_cache { + uint16_t last_step_count; + /* 1-octet CSTransactionCounter per each CS Transaction ID. Should + * be reset each time the nonce V CS Step_Counter field is set to + * a new value. + */ + uint8_t transaction_counter; + /* Random bits cache */ + uint8_t random_bytes[16]; + /* The number of cached bytes that have been already used */ + uint8_t free_bytes; +}; + +/* DRBG context */ +struct ble_ll_cs_drbg_ctx { + /* Initialization vector, entropy input */ + uint8_t iv[16]; + /* Instantiation nonce */ + uint8_t in[8]; + /* Personalization vector/string */ + uint8_t pv[16]; + /* Temporal key K */ + uint8_t key[16]; + /* DRBG nonce/counter (V), the starting value from which the DRBG operates. + * Initialized once per LE Connection. + */ + uint8_t nonce_v[16]; + /* Cache bits generated with single DRBG transation */ + struct ble_ll_cs_transaction_cache t_cache[BLE_LL_CS_DRBG_TRANSACTION_IDS_NUMBER]; + + uint8_t marker_selection_free_bits; + uint8_t marker_selection_cache; + + uint8_t tone_ext_presence_free_bits; + uint8_t tone_ext_presence_cache; +}; + +int ble_ll_cs_drbg_e(const uint8_t *key, const uint8_t *data, uint8_t *out_data); +int ble_ll_cs_drbg_f7(const uint8_t *k, const uint8_t *in, uint8_t len, uint8_t *out); +int ble_ll_cs_drbg_f8(const uint8_t *input, uint8_t *sm); +int ble_ll_cs_drbg_f9(const uint8_t *sm, uint8_t *k, uint8_t *v); +int ble_ll_cs_drbg_h9(const uint8_t *iv, const uint8_t *in, const uint8_t *pv, + uint8_t *key, uint8_t *nonce_v); +int ble_ll_cs_drbg_rand(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count, + uint8_t transaction_id, uint8_t *output, uint8_t len); +int ble_ll_cs_drbg_rand_hr1(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count, + uint8_t transaction_id, uint8_t r, uint8_t *r_out); +int ble_ll_cs_drbg_shuffle_cr1(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count, + uint8_t transaction_id, uint8_t *channel_array, + uint8_t *shuffled_array, uint8_t len); +int ble_ll_cs_drbg_generate_aa(struct ble_ll_cs_drbg_ctx *drbg_ctx, uint16_t step_count, + uint32_t *initiator_aa, uint32_t *reflector_aa); +int ble_ll_cs_drbg_rand_marker_position(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint16_t step_count, uint8_t rtt_type, + uint8_t *position1, uint8_t *position2); +int ble_ll_cs_drbg_rand_marker_selection(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, + uint8_t *marker_selection); +int ble_ll_cs_drbg_rand_main_mode_steps(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t main_mode_min_steps, + uint8_t main_mode_max_steps, + uint8_t *main_mode_steps); +int ble_ll_cs_drbg_generate_sync_sequence(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t rtt_type, + uint8_t *buf, uint8_t *sequence_len); +int ble_ll_cs_drbg_rand_antenna_path_perm_id(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint16_t step_count, uint8_t n_ap, + uint8_t *ap_id); +int ble_ll_cs_drbg_rand_tone_ext_presence(struct ble_ll_cs_drbg_ctx *drbg_ctx, + uint8_t step_count, uint8_t *presence); +int ble_ll_cs_drbg_init(struct ble_ll_cs_drbg_ctx *drbg_ctx); +void ble_ll_cs_drbg_free(struct ble_ll_cs_drbg_ctx *drbg_ctx); +void ble_ll_cs_drbg_clear_cache(struct ble_ll_cs_drbg_ctx *drbg_ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_CS_DRBG_PRIV */ diff --git a/src/nimble/nimble/controller/src/ble_ll_ctrl.c b/src/nimble/nimble/controller/src/ble_ll_ctrl.c index c29aef86b..b836c6819 100644 --- a/src/nimble/nimble/controller/src/ble_ll_ctrl.c +++ b/src/nimble/nimble/controller/src/ble_ll_ctrl.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,8 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include @@ -186,7 +186,7 @@ ble_ll_ctrl_rej_ext_ind_make(uint8_t rej_opcode, uint8_t err, uint8_t *ctrdata) ctrdata[1] = err; } -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) /** * Called to cancel a phy update procedure. * @@ -293,8 +293,26 @@ ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr, req->offset4 = get_le16(dptr + 19); req->offset5 = get_le16(dptr + 21); - /* Check if parameters are valid */ ble_err = BLE_ERR_SUCCESS; + +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + /* Allow to change connection parameters only if conn_itvl can stay unchanged + * and anchor point change is not requested */ + if (ble_ll_sched_css_is_enabled()) { + if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL && + ((connsm->conn_itvl < le16toh(req->interval_min)) || + (connsm->conn_itvl > le16toh(req->interval_max)) || + (le16toh(req->offset0) != 0xffff))) { + ble_err = BLE_ERR_INV_LMP_LL_PARM; + goto conn_param_pdu_exit; + } + + req->interval_min = connsm->conn_itvl; + req->interval_max = connsm->conn_itvl; + } +#endif + + /* Check if parameters are valid */ rc = ble_ll_conn_hci_chk_conn_params(req->interval_min, req->interval_max, req->latency, @@ -382,6 +400,13 @@ ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr, rspbuf[1] = opcode; rspbuf[2] = ble_err; } + +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + if (!ble_err) { + connsm->css_slot_idx_pending = connsm->css_slot_idx; + } +#endif + return rsp_opcode; } @@ -548,7 +573,7 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t * ctrl_proc = BLE_LL_CTRL_PROC_LE_PING; BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_LE_PING); break; -#if (BLE_LL_BT5_PHY_SUPPORTED ==1) +#if MYNEWT_VAL(BLE_LL_PHY) case BLE_LL_CTRL_PHY_REQ: ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE); ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE; @@ -627,6 +652,11 @@ ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask) { uint8_t phy; + /* One and only one bit shall be set */ + if (__builtin_popcount(phy_mask) != 1) { + return 0; + } + /* * NOTE: wipe out unsupported PHYs. There should not be an unsupported * in this mask if the other side is working correctly. @@ -658,7 +688,7 @@ ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask) return phy; } -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask) { @@ -767,7 +797,6 @@ ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t s_to_m; uint8_t tx_phys; uint8_t rx_phys; - uint16_t instant; uint8_t is_periph_sym = 0; /* Get preferences from PDU */ @@ -841,13 +870,7 @@ ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, connsm->flags.phy_update_host_initiated = 0; ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); } - instant = 0; } else { - /* Determine instant we will use. 6 more is minimum */ - instant = connsm->event_cntr + connsm->periph_latency + 6 + 1; - connsm->phy_instant = instant; - connsm->flags.phy_update_sched = 1; - /* Set new phys to use when instant occurs */ connsm->phy_data.new_tx_phy = m_to_s; connsm->phy_data.new_rx_phy = s_to_m; @@ -864,7 +887,33 @@ ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, ctrdata[0] = m_to_s; ctrdata[1] = s_to_m; +} +#endif + +#if MYNEWT_VAL(BLE_LL_PHY) +static bool +ble_ll_ctrl_phy_update_ind_instant(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata) +{ + uint16_t instant; + uint8_t m_to_s; + uint8_t s_to_m; + bool schedule = false; + + m_to_s = ctrdata[0]; + s_to_m = ctrdata[1]; + + if ((m_to_s == 0) && (s_to_m == 0)) { + instant = 0; + } else { + /* Determine instant we will use. 6 more is minimum */ + instant = connsm->event_cntr + connsm->periph_latency + 6 + 1; + connsm->phy_instant = instant; + schedule = true; + } + put_le16(ctrdata + 2, instant); + + return schedule; } #endif @@ -1118,11 +1167,9 @@ ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) static uint8_t ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) { - if (connsm->sync_transfer_mode) { - ble_ll_sync_periodic_ind(connsm, dptr, connsm->sync_transfer_mode == 1, - connsm->sync_transfer_skip, - connsm->sync_transfer_sync_timeout); - } + ble_ll_sync_periodic_ind(connsm, dptr, connsm->sync_transfer_mode, + connsm->sync_transfer_skip, + connsm->sync_transfer_sync_timeout); return BLE_ERR_MAX; } #endif @@ -1298,27 +1345,6 @@ ble_ll_ctrl_rx_subrate_ind(struct ble_ll_conn_sm *connsm, uint8_t *req, } #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. * @@ -1427,11 +1453,13 @@ ble_ll_ctrl_enc_allowed_pdu(uint8_t llid, uint8_t len, uint8_t opcode) } int -ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu) +ble_ll_ctrl_enc_allowed_pdu_rx(struct ble_ll_conn_sm *connsm, struct os_mbuf *rxpdu) { uint8_t llid; uint8_t len; uint8_t opcode; + uint8_t state; + int allowed; llid = rxpdu->om_data[0] & BLE_LL_DATA_HDR_LLID_MASK; len = rxpdu->om_data[1]; @@ -1441,7 +1469,47 @@ ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu) opcode = 0; } - return ble_ll_ctrl_enc_allowed_pdu(llid, len, opcode); + allowed = 0; + state = connsm->enc_data.enc_state; + + switch (llid) { + case BLE_LL_LLID_CTRL: + switch (opcode) { + case BLE_LL_CTRL_REJECT_IND: + case BLE_LL_CTRL_REJECT_IND_EXT: + allowed = state == CONN_ENC_S_ENC_RSP_WAIT || + state == CONN_ENC_S_START_ENC_REQ_WAIT; + break; + case BLE_LL_CTRL_START_ENC_RSP: + allowed = state == CONN_ENC_S_START_ENC_RSP_WAIT; + break; + case BLE_LL_CTRL_START_ENC_REQ: + allowed = state == CONN_ENC_S_START_ENC_REQ_WAIT; + break; + case BLE_LL_CTRL_ENC_REQ: + allowed = state == CONN_ENC_S_ENCRYPTED || state == CONN_ENC_S_PAUSED; + break; + case BLE_LL_CTRL_ENC_RSP: + allowed = state == CONN_ENC_S_ENC_RSP_WAIT; + break; + case BLE_LL_CTRL_PAUSE_ENC_REQ: + allowed = state == CONN_ENC_S_ENCRYPTED; + break; + case BLE_LL_CTRL_PAUSE_ENC_RSP: + allowed = state == CONN_ENC_S_PAUSE_ENC_RSP_WAIT; + break; + case BLE_LL_CTRL_TERMINATE_IND: + allowed = 1; + break; + } + break; + case BLE_LL_LLID_DATA_FRAG: + /* Empty PDUs are allowed */ + allowed = len == 0; + break; + } + + return allowed; } int @@ -1524,15 +1592,6 @@ 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. * @@ -1788,6 +1847,7 @@ ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm) /* We are encrypted */ connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED; + connsm->flags.encrypt_paused = 0; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) ble_ll_conn_auth_pyld_timer_start(connsm); #endif @@ -1898,12 +1958,15 @@ ble_ll_ctrl_chanmap_req_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld) memcpy(pyld, g_ble_ll_data.chan_map, BLE_LL_CHAN_MAP_LEN); memcpy(connsm->req_chanmap, pyld, BLE_LL_CHAN_MAP_LEN); + /* Instant is placed in ble_ll_ctrl_chanmap_req_instant()*/ +} + +static void +ble_ll_ctrl_chanmap_req_instant(struct ble_ll_conn_sm *connsm, uint8_t *pyld) +{ /* Place instant into request */ connsm->chanmap_instant = connsm->event_cntr + connsm->periph_latency + 6 + 1; put_le16(pyld + BLE_LL_CHAN_MAP_LEN, connsm->chanmap_instant); - - /* Set scheduled flag */ - connsm->flags.chanmap_update_sched = 1; } /** @@ -2002,7 +2065,7 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED; break; #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) case BLE_LL_CTRL_PROC_PHY_UPDATE: ble_ll_ctrl_phy_update_cancel(connsm, ble_error); ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); @@ -2117,7 +2180,7 @@ ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm, bool initial) } } - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD, NULL); + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD); } static void @@ -2271,17 +2334,6 @@ ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, return BLE_ERR_MAX; } -#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - /* Reject any attempts to change connection parameters by peripheral */ - if (ble_ll_sched_css_is_enabled() && - connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { - rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; - rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ; - rspbuf[2] = BLE_ERR_UNSUPPORTED; - return rsp_opcode; - } -#endif - /* XXX: remember to deal with this on the central: if the peripheral has * initiated a procedure we may have received its connection parameter * update request and have signaled the host with an event. If that @@ -2460,7 +2512,7 @@ ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr) * @param ctrl_proc */ static struct os_mbuf * -ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data) +ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc) { uint8_t len; uint8_t opcode = 0; @@ -2479,7 +2531,7 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data) switch (ctrl_proc) { case BLE_LL_CTRL_PROC_CONN_UPDATE: opcode = BLE_LL_CTRL_CONN_UPDATE_IND; - ble_ll_ctrl_conn_update_init_proc(connsm, data); + ble_ll_ctrl_conn_update_init_proc(connsm, NULL); break; case BLE_LL_CTRL_PROC_CHAN_MAP_UPD: opcode = BLE_LL_CTRL_CHANNEL_MAP_REQ; @@ -2534,7 +2586,7 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data) } break; #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) case BLE_LL_CTRL_PROC_PHY_UPDATE: opcode = BLE_LL_CTRL_PHY_REQ; ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata); @@ -2546,12 +2598,6 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data) 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 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CTRL_PROC_SUBRATE_REQ: @@ -2643,7 +2689,7 @@ ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm) BLE_LL_ASSERT(connsm->disconnect_reason != 0); ctrl_proc = BLE_LL_CTRL_PROC_TERMINATE; - om = ble_ll_ctrl_proc_init(connsm, ctrl_proc, NULL); + om = ble_ll_ctrl_proc_init(connsm, ctrl_proc); if (om) { connsm->flags.terminate_started = 1; @@ -2663,8 +2709,7 @@ ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm) * @param connsm Pointer to connection state machine. */ void -ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc, - void *data) +ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc) { struct os_mbuf *om; @@ -2673,7 +2718,7 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc, om = NULL; if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) { /* Initiate the control procedure. */ - om = ble_ll_ctrl_proc_init(connsm, ctrl_proc, data); + om = ble_ll_ctrl_proc_init(connsm, ctrl_proc); if (om) { /* Set the current control procedure */ connsm->cur_ctrl_proc = ctrl_proc; @@ -2700,6 +2745,9 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc, void ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + struct os_mbuf *om; +#endif int i; /* XXX: TODO new rules! Cannot start certain control procedures if other @@ -2722,6 +2770,22 @@ ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm) return; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (connsm->flags.pending_encrypt_restart) { + /* This flag should only be set after LL_PAUSE_ENC_RSP was txd from + * central and there should be already active encryption procedure + * ongoing. We need to restart encryption to complete key refresh. + */ + BLE_LL_ASSERT(connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT); + BLE_LL_ASSERT(IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_ENCRYPT)); + + om = ble_ll_ctrl_proc_init(connsm, BLE_LL_CTRL_PROC_ENCRYPT); + if (om) { + connsm->flags.pending_encrypt_restart = 0; + } + } +#endif + /* If there is a running procedure or no pending, do nothing */ if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) && (connsm->pending_ctrl_procs != 0)) { @@ -2740,7 +2804,7 @@ ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm) ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS); CLR_PENDING_CTRL_PROC(connsm, i); } else { - ble_ll_ctrl_proc_start(connsm, i, NULL); + ble_ll_ctrl_proc_start(connsm, i); break; } } @@ -2771,9 +2835,6 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) uint8_t *dptr; uint8_t *rspbuf; uint8_t *rspdata; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - int restart_encryption; -#endif int rc = 0; uint8_t rsp_opcode = 0; @@ -2818,10 +2879,6 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CTRL_RX, opcode, len); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - restart_encryption = 0; -#endif - /* If opcode comes from reserved value or CtrlData fields is invalid * we shall respond with LL_UNKNOWN_RSP */ @@ -2972,9 +3029,6 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) break; case BLE_LL_CTRL_PAUSE_ENC_RSP: rsp_opcode = ble_ll_ctrl_rx_pause_enc_rsp(connsm); - if (rsp_opcode == BLE_LL_CTRL_PAUSE_ENC_RSP) { - restart_encryption = 1; - } break; #endif case BLE_LL_CTRL_PING_REQ: @@ -2989,13 +3043,13 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) case BLE_LL_CTRL_CONN_PARM_RSP: rsp_opcode = ble_ll_ctrl_rx_conn_param_rsp(connsm, dptr, rspbuf); break; - /* Fall-through intentional... */ + /* fall through */ case BLE_LL_CTRL_REJECT_IND: case BLE_LL_CTRL_REJECT_IND_EXT: /* Sometimes reject triggers sending other LL CTRL msg */ rsp_opcode = ble_ll_ctrl_rx_reject_ind(connsm, dptr, opcode, rspdata); break; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) case BLE_LL_CTRL_PHY_REQ: rsp_opcode = ble_ll_ctrl_rx_phy_req(connsm, dptr, rspdata); break; @@ -3015,17 +3069,6 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) 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); @@ -3059,13 +3102,6 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) } len = g_ble_ll_ctrl_pkt_lengths[rsp_opcode] + 1; ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (restart_encryption) { - /* XXX: what happens if this fails? Meaning we cant allocate - mbuf? */ - ble_ll_ctrl_proc_init(connsm, BLE_LL_CTRL_PROC_ENCRYPT, NULL); - } -#endif } #if MYNEWT_VAL(BLE_LL_CONN_INIT_AUTO_DLE) @@ -3138,6 +3174,17 @@ ble_ll_ctrl_tx_start(struct ble_ll_conn_sm *connsm, struct os_mbuf *txpdu) ble_ll_ctrl_conn_update_make_ind_pdu(connsm, ctrdata); connsm->flags.conn_update_sched = 1; break; + case BLE_LL_CTRL_CHANNEL_MAP_REQ: + ble_ll_ctrl_chanmap_req_instant(connsm, ctrdata); + connsm->flags.chanmap_update_sched = 1; + break; +#if MYNEWT_VAL(BLE_LL_PHY) + case BLE_LL_CTRL_PHY_UPDATE_IND: + if (ble_ll_ctrl_phy_update_ind_instant(connsm, ctrdata)) { + connsm->flags.phy_update_sched = 1; + } + break; +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) case BLE_LL_CTRL_SUBRATE_IND: connsm->flags.subrate_trans = 1; @@ -3202,7 +3249,8 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) case BLE_LL_CTRL_PAUSE_ENC_REQ: - /* note: fall-through intentional */ + connsm->flags.encrypt_paused = 1; + /* fall through */ case BLE_LL_CTRL_ENC_REQ: connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT; break; @@ -3214,6 +3262,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) case BLE_LL_CTRL_START_ENC_RSP: if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) { connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED; + connsm->flags.encrypt_paused = 0; if (connsm->flags.le_ping_supp) { ble_ll_conn_auth_pyld_timer_start(connsm); } @@ -3222,11 +3271,19 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) case BLE_LL_CTRL_PAUSE_ENC_RSP: if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) { connsm->enc_data.enc_state = CONN_ENC_S_PAUSE_ENC_RSP_WAIT; + connsm->flags.encrypt_paused = 1; + } else { + connsm->flags.pending_encrypt_restart = 1; } break; +#else + case BLE_LL_CTRL_PAUSE_ENC_RSP: + BLE_LL_ASSERT(connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL); + connsm->flags.pending_encrypt_restart = 1; + break; #endif #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CTRL_PHY_REQ: if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) { @@ -3268,6 +3325,6 @@ ble_ll_ctrl_init_conn_sm(struct ble_ll_conn_sm *connsm) ble_ll_conn_auth_pyld_timer_cb, connsm); #endif } - -#endif #endif + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_dtm.c b/src/nimble/nimble/controller/src/ble_ll_dtm.c index 33f96876d..a03236a4d 100644 --- a/src/nimble/nimble/controller/src/ble_ll_dtm.c +++ b/src/nimble/nimble/controller/src/ble_ll_dtm.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM #include "syscfg/syscfg.h" #include "nimble/porting/nimble/include/sysinit/sysinit.h" @@ -309,7 +310,7 @@ ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len, /* Set BLE transmit header */ ble_hdr = BLE_MBUF_HDR_PTR(m); - ble_hdr->txinfo.flags = 0; + ble_hdr->txinfo.num_data_pkt = 0; ble_hdr->txinfo.offset = 0; ble_hdr->txinfo.pyld_len = len; ble_hdr->txinfo.hdr_byte = packet_payload; @@ -343,6 +344,18 @@ ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len, case 0x07: byte_pattern = 0xAA; break; +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) + case 0xff: + ble_ll_tx_power_set(g_ble_ll_tx_power); + rc = ble_phy_dtm_carrier(channel_rf_to_index[rf_channel]); + if (rc) { + return 1; + } + + /* this is special as it doesn't involve scheduling */ + g_ble_ll_dtm_ctx.active = 1; + return 0; +#endif default: return 1; } @@ -479,10 +492,20 @@ ble_ll_dtm_tx_test(uint8_t tx_chan, uint8_t len, uint8_t packet_payload, return BLE_ERR_INV_HCI_CMD_PARMS; } - if (tx_chan > 0x27 || packet_payload > 0x07) { + if (tx_chan > 0x27) { return BLE_ERR_INV_HCI_CMD_PARMS; } + if (packet_payload > 0x07) { +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) + if (packet_payload != 255) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } +#else + return BLE_ERR_INV_HCI_CMD_PARMS; +#endif + } + if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode, interval, pkt_count)) { return BLE_ERR_UNSPECIFIED; @@ -691,4 +714,5 @@ ble_ll_dtm_init(void) SYSINIT_PANIC_ASSERT(rc == 0); } #endif -#endif \ No newline at end of file + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_hci.c b/src/nimble/nimble/controller/src/ble_ll_hci.c index 161c0a573..fcc5489b8 100644 --- a/src/nimble/nimble/controller/src/ble_ll_hci.c +++ b/src/nimble/nimble/controller/src/ble_ll_hci.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,8 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include @@ -39,6 +39,7 @@ #include "nimble/nimble/controller/include/controller/ble_ll_isoal.h" #include "nimble/nimble/controller/include/controller/ble_ll_iso.h" #include "nimble/nimble/controller/include/controller/ble_ll_iso_big.h" +#include "nimble/nimble/controller/include/controller/ble_ll_cs.h" #include "ble_ll_priv.h" #include "ble_ll_conn_priv.h" #include "ble_ll_hci_priv.h" @@ -357,8 +358,14 @@ 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; + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size); rp->data_packets = g_ble_ll_data.ll_num_acl_pkts; +#else + rp->data_len = 0; + rp->data_packets = 0; +#endif rp->iso_data_len = htole16(g_ble_ll_data.ll_iso_pkt_size); rp->iso_data_packets = g_ble_ll_data.ll_num_iso_pkts; @@ -367,7 +374,7 @@ ble_ll_hci_le_read_bufsize_v2(uint8_t *rspbuf, uint8_t *rsplen) } #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) /** * Checks the preferred phy masks for validity and places the preferred masks * in the input phy masks @@ -774,6 +781,9 @@ ble_ll_is_valid_adv_mode(uint8_t ocf) #if MYNEWT_VAL(BLE_VERSION) >= 51 case BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE: #endif +#if MYNEWT_VAL(BLE_VERSION) >= 54 + case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM_V2: +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) case BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER: case BLE_HCI_OCF_LE_PERIODIC_ADV_SET_INFO_TRANSFER: @@ -1112,7 +1122,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, } break; #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_RD_PHY: rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, len, rspbuf, rsplen); @@ -1276,42 +1286,22 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, case BLE_HCI_OCF_LE_TERMINATE_BIG: rc = ble_ll_iso_big_hci_terminate(cmdbuf, len); break; -#endif /* BLE_LL_ISO_BROADCASTER */ -#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_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); + case BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST: + rc = ble_ll_iso_transmit_test(cmdbuf, len, rspbuf, rsplen); break; -#endif +#endif /* BLE_LL_ISO_BROADCASTER */ #if MYNEWT_VAL(BLE_LL_ISO) case BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH: - rc = ble_ll_isoal_hci_setup_iso_data_path(cmdbuf, len, rspbuf, rsplen); + rc = ble_ll_iso_setup_iso_data_path(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH: - rc = ble_ll_isoal_hci_remove_iso_data_path(cmdbuf, len, rspbuf, rsplen); + rc = ble_ll_iso_remove_iso_data_path(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_ISO_TEST_END: + rc = ble_ll_iso_end_test(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_READ_ISO_TX_SYNC: - rc = ble_ll_isoal_hci_read_tx_sync(cmdbuf, len, rspbuf, rsplen); + rc = ble_ll_iso_read_tx_sync(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_RD_BUF_SIZE_V2: if (len == 0) { @@ -1319,27 +1309,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, } break; #endif /* BLE_LL_ISO */ -#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 +#if BLE_LL_HOST_CONTROLLED_FEATURES case BLE_HCI_OCF_LE_SET_HOST_FEATURE: rc = ble_ll_set_host_feat(cmdbuf, len); break; @@ -1357,6 +1327,59 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, case BLE_HCI_OCF_LE_SUBRATE_REQ: rc = ble_ll_conn_hci_subrate_req(cmdbuf, len, rspbuf, rsplen); break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_VERSION) >= 54 + case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM_V2: + rc = ble_ll_adv_ext_set_param_v2(cmdbuf, len, rspbuf, rsplen); + break; +#endif +#endif +#if MYNEWT_VAL(BLE_LL_CHANNEL_SOUNDING) + case BLE_HCI_OCF_LE_CS_RD_LOC_SUPP_CAP: + rc = ble_ll_cs_hci_rd_loc_supp_cap(rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_CS_RD_REM_SUPP_CAP: + rc = ble_ll_cs_hci_rd_rem_supp_cap(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CS_WR_CACHED_REM_SUPP_CAP: + rc = ble_ll_cs_hci_wr_cached_rem_supp_cap(cmdbuf, len, rspbuf, rsplen); + break; +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_HCI_OCF_LE_CS_SEC_ENABLE: + rc = ble_ll_cs_hci_sec_enable(cmdbuf, len); + break; +#endif + case BLE_HCI_OCF_LE_CS_SET_DEF_SETTINGS: + rc = ble_ll_cs_hci_set_def_settings(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_CS_RD_REM_FAE: + rc = ble_ll_cs_hci_rd_rem_fae(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CS_WR_CACHED_REM_FAE: + rc = ble_ll_cs_hci_wr_cached_rem_fae(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_CS_CREATE_CONFIG: + rc = ble_ll_cs_hci_create_config(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CS_REMOVE_CONFIG: + rc = ble_ll_cs_hci_remove_config(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CS_SET_CHAN_CLASS: + rc = ble_ll_cs_hci_set_chan_class(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CS_SET_PROC_PARAMS: + rc = ble_ll_cs_hci_set_proc_params(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_CS_PROC_ENABLE: + rc = ble_ll_cs_hci_proc_enable(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CS_TEST: + rc = ble_ll_cs_hci_test(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_CS_TEST_END: + rc = ble_ll_cs_hci_test_end(); + break; #endif default: rc = BLE_ERR_UNKNOWN_HCI_CMD; @@ -1387,12 +1410,6 @@ ble_ll_hci_disconnect(const uint8_t *cmdbuf, uint8_t len) 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); } #endif @@ -1532,6 +1549,11 @@ 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_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + case BLE_HCI_OCF_CB_READ_TX_PWR: + rc = ble_ll_conn_hci_cb_read_tx_pwr(cmdbuf, len, rspbuf, rsplen); + break; +#endif #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); @@ -1551,7 +1573,8 @@ ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, case BLE_HCI_OCF_CB_SET_EVENT_MASK2: rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len); break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) +#if (MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)) \ + && MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) case BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO: rc = ble_ll_conn_hci_rd_auth_pyld_tmo(cmdbuf, len, rspbuf, rsplen); break; @@ -1728,16 +1751,21 @@ ble_ll_hci_cmd_fake_dual_mode(uint16_t opcode, uint8_t *cmdbuf, uint8_t len, rc = 0; break; case BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT): - put_le64(rspbuf, 0x877bffdbfe0ffebf); + put_le64(rspbuf, 0x077bffdbfe0ffebf); *rsplen = 8; rc = 0; break; case BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, 0x04): /* Read Local Extended Features */ - rspbuf[0] = 0; + rspbuf[0] = cmdbuf[0]; rspbuf[1] = 0; - put_le64(&rspbuf[2], 0x877bffdbfe0ffebf); + if (rspbuf[0] == 0) { + put_le64(&rspbuf[2], 0x077bffdbfe0ffebf); + rc = 0; + } else { + put_le64(&rspbuf[2], 0); + rc = BLE_ERR_INV_HCI_CMD_PARMS; + } *rsplen = 10; - rc = 0; break; case BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BUF_SIZE): put_le16(rspbuf, 255); @@ -1975,7 +2003,7 @@ int ble_ll_hci_iso_rx(struct os_mbuf *om) { #if MYNEWT_VAL(BLE_LL_ISO) - ble_ll_isoal_data_in(om); + ble_ll_iso_data_in(om); #else os_mbuf_free_chain(om); #endif @@ -2017,4 +2045,4 @@ ble_ll_hci_init(void) #endif } -#endif +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_hci_ev.c b/src/nimble/nimble/controller/src/ble_ll_hci_ev.c index 7a9eda918..6dfa6df92 100644 --- a/src/nimble/nimble/controller/src/ble_ll_hci_ev.c +++ b/src/nimble/nimble/controller/src/ble_ll_hci_ev.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include @@ -434,7 +434,7 @@ ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, * @param connsm Pointer to connection state machine * @param status error status of event */ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) int ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status) { @@ -620,6 +620,7 @@ ble_ll_hci_ev_send_vs_printf(uint8_t id, const char *fmt, ...) struct ble_hci_ev_vs *ev; struct ble_hci_ev *hci_ev; va_list ap; + int len; hci_ev = ble_transport_alloc_evt(1); if (!hci_ev) { @@ -633,10 +634,12 @@ ble_ll_hci_ev_send_vs_printf(uint8_t id, const char *fmt, ...) ev->id = id; va_start(ap, fmt); - hci_ev->length += vsnprintf((void *)ev->data, - BLE_HCI_MAX_DATA_LEN - sizeof(*ev), fmt, ap); + len = vsnprintf((void *)ev->data, BLE_HCI_MAX_DATA_LEN - sizeof(*ev), fmt, ap); va_end(ap); + ev->data[len] = 0; + hci_ev->length += len + 1; + ble_ll_hci_event_send(hci_ev); } @@ -667,4 +670,5 @@ ble_ll_hci_ev_send_vs_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, } } #endif + #endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_hci_supp_cmd.c b/src/nimble/nimble/controller/src/ble_ll_hci_supp_cmd.c index 18b1720a9..8ce16fd4d 100644 --- a/src/nimble/nimble/controller/src/ble_ll_hci_supp_cmd.c +++ b/src/nimble/nimble/controller/src/ble_ll_hci_supp_cmd.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,13 +19,11 @@ * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include -#include -#include +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" /* Magic macros */ #define BIT(n) (1 << (n)) | @@ -47,6 +47,9 @@ static const uint8_t octet_5 = OCTET( ); static const uint8_t octet_10 = OCTET( +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(2) /* HCI Read Transmit Power Level */ +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) BIT(5) /* HCI Set Controller To Host Flow Control */ BIT(6) /* HCI Host Buffer Size */ @@ -66,6 +69,10 @@ static const uint8_t octet_15 = OCTET( #endif ); +static const uint8_t octet_22 = OCTET( + BIT(2) /* HCI Set Event Mask Page 2 */ +); + static const uint8_t octet_25 = OCTET( BIT(0) /* HCI LE Set Event Mask */ BIT(1) /* HCI LE Read Buffer Size [v1] */ @@ -130,6 +137,14 @@ static const uint8_t octet_28 = OCTET( #endif ); +static const uint8_t octet_32 = OCTET( +#if (MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)) && \ + MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + BIT(4) /* HCI Read Authenticated Payload Timeout */ + BIT(5) /* HCI Write Authenticated Payload Timeout */ +#endif +); + static const uint8_t octet_33 = OCTET( #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) BIT(4) /* HCI LE Remote Connection Parameter Request Reply */ @@ -163,7 +178,7 @@ static const uint8_t octet_35 = OCTET( BIT(2) /* HCI LE Set Resolvable Private Address Timeout */ #endif BIT(3) /* HCI LE Read Maximum Data Length */ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) BIT(4) /* HCI LE Read PHY */ BIT(5) /* HCI LE Set Default PHY */ @@ -271,10 +286,20 @@ static const uint8_t octet_43 = OCTET( #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) BIT(2) /* HCI LE Request Peer SCA */ #endif +#if MYNEWT_VAL(BLE_LL_ISO) + BIT(3) /* HCI LE Setup ISO Data Path */ + BIT(4) /* HCI LE Remove ISO Data Path */ +#endif +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + BIT(5) /* HCI LE ISO Transmit Test */ +#endif ); static const uint8_t octet_44 = OCTET( -#if MYNEWT_VAL(BLE_VERSION) >= 52 +#if MYNEWT_VAL(BLE_LL_ISO) + BIT(0) /* HCI LE ISO Test End */ +#endif +#if BLE_LL_HOST_CONTROLLED_FEATURES BIT(1) /* HCI LE Set Host Feature */ #endif ); @@ -284,6 +309,9 @@ static const uint8_t octet_46 = OCTET( BIT(0) /* HCI LE Set Default Subrate */ BIT(1) /* HCI LE Subrate Request */ #endif +#if MYNEWT_VAL(BLE_VERSION) >= 54 && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + BIT(2) /* HCI LE Set Extended Advertising Parameters [v2] */ +#endif ); static const uint8_t g_ble_ll_hci_supp_cmds[64] = { @@ -309,7 +337,7 @@ static const uint8_t g_ble_ll_hci_supp_cmds[64] = { 0, 0, 0, - 0, + octet_22, 0, 0, octet_25, @@ -319,7 +347,7 @@ static const uint8_t g_ble_ll_hci_supp_cmds[64] = { 0, 0, 0, - 0, + octet_32, octet_33, octet_34, octet_35, diff --git a/src/nimble/nimble/controller/src/ble_ll_hci_vs.c b/src/nimble/nimble/controller/src/ble_ll_hci_vs.c index db56e192b..2a069e4a4 100644 --- a/src/nimble/nimble/controller/src/ble_ll_hci_vs.c +++ b/src/nimble/nimble/controller/src/ble_ll_hci_vs.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#ifndef ESP_PLATFORM - #include #include "syscfg/syscfg.h" #include "nimble/nimble/controller/include/controller/ble_ll_utils.h" @@ -29,8 +29,10 @@ #include "nimble/nimble/controller/include/controller/ble_ll_scan.h" #include "nimble/nimble/controller/include/controller/ble_hw.h" #include "nimble/nimble/controller/include/controller/ble_fem.h" +#include "nimble/porting/nimble/include/os/util.h" #include "ble_ll_conn_priv.h" #include "ble_ll_priv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" #if MYNEWT_VAL(BLE_LL_HCI_VS) @@ -330,6 +332,64 @@ ble_ll_hci_vs_set_antenna(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, } #endif +#if MYNEWT_VAL(BLE_LL_HCI_VS_LOCAL_IRK) +static int +ble_ll_hci_vs_set_local_irk(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_vs_set_local_irk_cp *cmd = (const void *)cmdbuf; + int rc; + + if (cmdlen != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (ble_ll_is_busy(BLE_LL_BUSY_EXCLUDE_CONNECTIONS)) { + return BLE_ERR_CMD_DISALLOWED; + } + + rc = ble_ll_resolv_local_irk_set(cmd->own_addr_type, cmd->irk); + if (rc) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + *rsplen = 0; + + return 0; +} +#endif + +#if MYNEWT_VAL(BLE_LL_HCI_VS_SET_SCAN_CFG) +static int +ble_ll_hci_vs_set_scan_cfg(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_vs_set_scan_cfg_cp *cmd = (const void *)cmdbuf; + uint32_t flags; + int rc; + + if (cmdlen != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + flags = le32toh(cmd->flags); + + if ((flags & BLE_HCI_VS_SET_SCAN_CFG_FLAG_NO_LEGACY) && + (flags & BLE_HCI_VS_SET_SCAN_CFG_FLAG_NO_EXT)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rc = ble_ll_scan_set_vs_config(flags, cmd->rssi_threshold); + if (rc != 0) { + return BLE_ERR_CMD_DISALLOWED; + } + + *rsplen = 0; + + return 0; +} +#endif + static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_RD_STATIC_ADDR, ble_ll_hci_vs_rd_static_addr), @@ -356,6 +416,14 @@ static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { #if MYNEWT_VAL(BLE_FEM_ANTENNA) BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_ANTENNA, ble_ll_hci_vs_set_antenna), #endif +#if MYNEWT_VAL(BLE_LL_HCI_VS_LOCAL_IRK) + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_LOCAL_IRK, + ble_ll_hci_vs_set_local_irk), +#endif +#if MYNEWT_VAL(BLE_LL_HCI_VS_SET_SCAN_CFG) + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_SCAN_CFG, + ble_ll_hci_vs_set_scan_cfg) +#endif }; static struct ble_ll_hci_vs_cmd * diff --git a/src/nimble/nimble/controller/src/ble_ll_iso.c b/src/nimble/nimble/controller/src/ble_ll_iso.c index b4433e828..cadf70d9f 100644 --- a/src/nimble/nimble/controller/src/ble_ll_iso.c +++ b/src/nimble/nimble/controller/src/ble_ll_iso.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,132 +18,424 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM + #include -#include "syscfg/syscfg.h" -#include "nimble/nimble/include/nimble/ble.h" +#include #include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_isoal.h" #include "nimble/nimble/controller/include/controller/ble_ll_iso.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) +#if MYNEWT_VAL(BLE_LL_ISO) -int -ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len) -{ - return BLE_ERR_UNSUPPORTED; -} +STAILQ_HEAD(ble_ll_iso_conn_q, ble_ll_iso_conn); +struct ble_ll_iso_conn_q ll_iso_conn_q; int -ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) { - return BLE_ERR_UNSUPPORTED; -} + const struct ble_hci_le_setup_iso_data_path_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_setup_iso_data_path_rp *rsp = (void *)rspbuf; + struct ble_ll_iso_conn *conn; + uint16_t conn_handle; -int -ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len) -{ - return BLE_ERR_UNSUPPORTED; -} + conn_handle = le16toh(cmd->conn_handle); -int -ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd) -{ - return BLE_ERR_UNSUPPORTED; -} + conn = ble_ll_iso_conn_find_by_handle(conn_handle); + if (!conn) { + return BLE_ERR_UNK_CONN_ID; + } -int -ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len, - uint8_t *rspbuf, uint8_t *rsplen) -{ - return BLE_ERR_UNSUPPORTED; + if (conn->mux.bn == 0) { + return BLE_ERR_UNSUPPORTED; + } + + if (conn->data_path.enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* Only input for now since we only support BIS */ + if (cmd->data_path_dir) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* We do not (yet) support any vendor-specific data path */ + if (cmd->data_path_id) { + return BLE_ERR_CMD_DISALLOWED; + } + + conn->data_path.enabled = 1; + conn->data_path.data_path_id = cmd->data_path_id; + + rsp->conn_handle = cmd->conn_handle; + *rsplen = sizeof(*rsp); + + return 0; } int -ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len) +ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) { - return BLE_ERR_UNSUPPORTED; + const struct ble_hci_le_remove_iso_data_path_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_remove_iso_data_path_rp *rsp = (void *)rspbuf; + struct ble_ll_iso_conn *conn; + uint16_t conn_handle; + + conn_handle = le16toh(cmd->conn_handle); + + conn = ble_ll_iso_conn_find_by_handle(conn_handle); + if (!conn) { + return BLE_ERR_UNK_CONN_ID; + } + + /* Only input for now since we only support BIS */ + if (cmd->data_path_dir) { + return BLE_ERR_CMD_DISALLOWED; + } + + conn->data_path.enabled = 0; + + rsp->conn_handle = cmd->conn_handle; + *rsplen = sizeof(*rsp); + + return 0; } int -ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len) +ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) { - return BLE_ERR_UNSUPPORTED; + const struct ble_hci_le_read_iso_tx_sync_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_read_iso_tx_sync_rp *rsp = (void *)rspbuf; + struct ble_ll_iso_conn *iso_conn; + uint16_t handle; + + handle = le16toh(cmd->conn_handle); + iso_conn = ble_ll_iso_conn_find_by_handle(handle); + if (!iso_conn) { + return BLE_ERR_UNK_CONN_ID; + } + + rsp->conn_handle = cmd->conn_handle; + rsp->packet_seq_num = htole16(iso_conn->mux.last_tx_packet_seq_num); + rsp->tx_timestamp = htole32(iso_conn->mux.last_tx_timestamp); + put_le24(rsp->time_offset, 0); + + *rsplen = sizeof(*rsp); + + return 0; } int -ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len) +ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen) { - return BLE_ERR_UNSUPPORTED; + const struct ble_hci_le_iso_transmit_test_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_iso_transmit_test_rp *rsp = (void *)rspbuf; + struct ble_ll_iso_conn *conn; + uint16_t handle; + + handle = le16toh(cmd->conn_handle); + + conn = ble_ll_iso_conn_find_by_handle(handle); + if (!conn) { + return BLE_ERR_UNK_CONN_ID; + } + + if (conn->mux.bn == 0) { + return BLE_ERR_UNSUPPORTED; + } + + if (conn->data_path.enabled) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (cmd->payload_type > BLE_HCI_PAYLOAD_TYPE_MAXIMUM_LENGTH) { + return BLE_ERR_INV_LMP_LL_PARM; + } + + conn->data_path.enabled = 1; + conn->data_path.data_path_id = BLE_HCI_ISO_DATA_PATH_ID_HCI; + conn->test_mode.transmit.enabled = 1; + conn->test_mode.transmit.payload_type = cmd->payload_type; + + rsp->conn_handle = cmd->conn_handle; + + *rsplen = sizeof(*rsp); + + return 0; } int -ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len) +ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen) { - /* Nothing to do here for now when HCI is supported */ + const struct ble_hci_le_iso_test_end_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_iso_test_end_rp *rsp = (void *)rspbuf; + struct ble_ll_iso_conn *iso_conn; + uint16_t handle; + + handle = le16toh(cmd->conn_handle); + iso_conn = ble_ll_iso_conn_find_by_handle(handle); + if (!iso_conn) { + return BLE_ERR_UNK_CONN_ID; + } + + if (!iso_conn->test_mode.transmit.enabled) { + return BLE_ERR_UNSUPPORTED; + } + + iso_conn->data_path.enabled = 0; + iso_conn->test_mode.transmit.enabled = 0; + + rsp->conn_handle = cmd->conn_handle; + rsp->received_sdu_count = 0; + rsp->missed_sdu_count = 0; + rsp->failed_sdu_count = 0; + + *rsplen = sizeof(*rsp); + return 0; } -int -ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len) + +struct ble_ll_iso_conn * +ble_ll_iso_conn_find_by_handle(uint16_t conn_handle) { - return BLE_ERR_UNSUPPORTED; + struct ble_ll_iso_conn *conn; + + STAILQ_FOREACH(conn, &ll_iso_conn_q, iso_conn_q_next) { + if (conn_handle == conn->handle) { + return conn; + } + } + + return NULL; } -int -ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len) +void +ble_ll_iso_init(void) { - return BLE_ERR_UNSUPPORTED; + STAILQ_INIT(&ll_iso_conn_q); + ble_ll_isoal_init(); } -int -ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len) +void +ble_ll_iso_reset(void) { - return BLE_ERR_UNSUPPORTED; + STAILQ_INIT(&ll_iso_conn_q); + ble_ll_isoal_reset(); } int -ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len) +ble_ll_iso_data_in(struct os_mbuf *om) { - return BLE_ERR_UNSUPPORTED; + struct ble_hci_iso *hci_iso; + struct ble_hci_iso_data *hci_iso_data; + struct ble_ll_iso_conn *conn; + struct ble_mbuf_hdr *blehdr; + uint16_t data_hdr_len; + uint16_t handle; + uint16_t conn_handle; + uint16_t length; + uint16_t pb_flag; + uint16_t ts_flag; + uint32_t timestamp = 0; + + hci_iso = (void *)om->om_data; + + handle = le16toh(hci_iso->handle); + conn_handle = BLE_HCI_ISO_CONN_HANDLE(handle); + pb_flag = BLE_HCI_ISO_PB_FLAG(handle); + ts_flag = BLE_HCI_ISO_TS_FLAG(handle); + length = BLE_HCI_ISO_LENGTH(le16toh(hci_iso->length)); + + conn = ble_ll_iso_conn_find_by_handle(conn_handle); + if (!conn) { + os_mbuf_free_chain(om); + return BLE_ERR_UNK_CONN_ID; + } + + data_hdr_len = 0; + if ((pb_flag == BLE_HCI_ISO_PB_FIRST) || + (pb_flag == BLE_HCI_ISO_PB_COMPLETE)) { + blehdr = BLE_MBUF_HDR_PTR(om); + blehdr->txiso.packet_seq_num = ++conn->mux.sdu_counter; + blehdr->txiso.cpu_timestamp = ble_ll_tmr_get(); + + if (ts_flag) { + timestamp = get_le32(om->om_data + sizeof(*hci_iso)); + data_hdr_len += sizeof(uint32_t); + } + blehdr->txiso.hci_timestamp = timestamp; + + hci_iso_data = (void *)(om->om_data + sizeof(*hci_iso) + data_hdr_len); + data_hdr_len += sizeof(*hci_iso_data); + } + os_mbuf_adj(om, sizeof(*hci_iso) + data_hdr_len); + + if (OS_MBUF_PKTLEN(om) != length - data_hdr_len) { + os_mbuf_free_chain(om); + return BLE_ERR_MEM_CAPACITY; + } + + switch (pb_flag) { + case BLE_HCI_ISO_PB_FIRST: + BLE_LL_ASSERT(!conn->frag); + conn->frag = om; + om = NULL; + break; + case BLE_HCI_ISO_PB_CONTINUATION: + BLE_LL_ASSERT(conn->frag); + os_mbuf_concat(conn->frag, om); + om = NULL; + break; + case BLE_HCI_ISO_PB_COMPLETE: + BLE_LL_ASSERT(!conn->frag); + break; + case BLE_HCI_ISO_PB_LAST: + BLE_LL_ASSERT(conn->frag); + os_mbuf_concat(conn->frag, om); + om = conn->frag; + conn->frag = NULL; + break; + default: + BLE_LL_ASSERT(0); + break; + } + + if (om) { + ble_ll_isoal_mux_sdu_enqueue(&conn->mux, om); + } + + return 0; } -#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) +static int +ble_ll_iso_test_pdu_get(struct ble_ll_iso_conn *conn, uint8_t idx, uint32_t pkt_counter, uint8_t *llid, uint8_t *dptr) { - return BLE_ERR_UNSUPPORTED; + uint32_t payload_len; + uint16_t rem_len; + uint8_t sdu_idx; + uint8_t pdu_idx; + int pdu_len; + + BLE_LL_ASSERT(!conn->mux.framed); + + sdu_idx = idx / conn->mux.pdu_per_sdu; + pdu_idx = idx - sdu_idx * conn->mux.pdu_per_sdu; + + switch (conn->test_mode.transmit.payload_type) { + case BLE_HCI_PAYLOAD_TYPE_ZERO_LENGTH: + *llid = 0b00; + pdu_len = 0; + break; + case BLE_HCI_PAYLOAD_TYPE_VARIABLE_LENGTH: + payload_len = max(conn->test_mode.transmit.rand + (sdu_idx * pdu_idx), 4); + + rem_len = payload_len - pdu_idx * conn->mux.max_pdu; + if (rem_len == 0) { + *llid = 0b01; + pdu_len = 0; + } else { + *llid = rem_len > conn->mux.max_pdu; + pdu_len = min(conn->mux.max_pdu, rem_len); + } + + memset(dptr, 0, pdu_len); + + if (payload_len == rem_len) { + put_le32(dptr, pkt_counter); + } + + break; + case BLE_HCI_PAYLOAD_TYPE_MAXIMUM_LENGTH: + payload_len = conn->max_sdu; + + rem_len = payload_len - pdu_idx * conn->mux.max_pdu; + if (rem_len == 0) { + *llid = 0b01; + pdu_len = 0; + } else { + *llid = rem_len > conn->mux.max_pdu; + pdu_len = min(conn->mux.max_pdu, rem_len); + } + + memset(dptr, 0, pdu_len); + + if (payload_len == rem_len) { + put_le32(dptr, pkt_counter); + } + + break; + default: + BLE_LL_ASSERT(0); + } + + return pdu_len; } int -ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len) +ble_ll_iso_pdu_get(struct ble_ll_iso_conn *conn, uint8_t idx, uint32_t pkt_counter, uint8_t *llid, void *dptr) { - return BLE_ERR_UNSUPPORTED; + if (conn->test_mode.transmit.enabled) { + return ble_ll_iso_test_pdu_get(conn, idx, pkt_counter, llid, dptr); + } + + return ble_ll_isoal_mux_pdu_get(&conn->mux, idx, llid, dptr); } -int -ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len) +void +ble_ll_iso_conn_init(struct ble_ll_iso_conn *conn, struct ble_ll_iso_conn_init_param *param) { - return BLE_ERR_UNSUPPORTED; + os_sr_t sr; + + memset(conn, 0, sizeof(*conn)); + + conn->handle = param->conn_handle; + conn->max_sdu = param->max_sdu; + + ble_ll_isoal_mux_init(&conn->mux, param->max_pdu, param->iso_interval_us, param->sdu_interval_us, + param->bn, param->pte, BLE_LL_ISOAL_MUX_IS_FRAMED(param->framing), + param->framing == BLE_HCI_ISO_FRAMING_FRAMED_UNSEGMENTED); + + OS_ENTER_CRITICAL(sr); + STAILQ_INSERT_TAIL(&ll_iso_conn_q, conn, iso_conn_q_next); + OS_EXIT_CRITICAL(sr); } -int -ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len) +void +ble_ll_iso_conn_free(struct ble_ll_iso_conn *conn) { - return BLE_ERR_UNSUPPORTED; + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + STAILQ_REMOVE(&ll_iso_conn_q, conn, ble_ll_iso_conn, iso_conn_q_next); + OS_EXIT_CRITICAL(sr); + + ble_ll_isoal_mux_free(&conn->mux); } int -ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len) +ble_ll_iso_conn_event_start(struct ble_ll_iso_conn *conn, uint32_t timestamp) { - return BLE_ERR_UNSUPPORTED; + if (conn->test_mode.transmit.enabled) { + conn->test_mode.transmit.rand = ble_ll_rand() % conn->max_sdu; + } + + ble_ll_isoal_mux_event_start(&conn->mux, timestamp); + + return 0; } int -ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len) +ble_ll_iso_conn_event_done(struct ble_ll_iso_conn *conn) { - return BLE_ERR_UNSUPPORTED; + conn->num_completed_pkt += ble_ll_isoal_mux_event_done(&conn->mux); + + return conn->num_completed_pkt; } -#endif -#endif -#endif + +#endif /* BLE_LL_ISO */ + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_iso_big.c b/src/nimble/nimble/controller/src/ble_ll_iso_big.c index 3fc0fab8c..611a67a81 100644 --- a/src/nimble/nimble/controller/src/ble_ll_iso_big.c +++ b/src/nimble/nimble/controller/src/ble_ll_iso_big.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,26 +19,24 @@ * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/hci_common.h" +#include "nimble/nimble/transport/include/nimble/transport.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_crypto.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_iso.h" +#include "nimble/nimble/controller/include/controller/ble_ll_iso_big.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" #include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) @@ -55,7 +55,6 @@ struct ble_ll_iso_big; struct ble_ll_iso_bis { struct ble_ll_iso_big *big; uint8_t num; - uint16_t conn_handle; uint32_t aa; uint32_t crc_init; @@ -71,8 +70,7 @@ struct ble_ll_iso_bis { uint8_t g; } tx; - struct ble_ll_isoal_mux mux; - uint16_t num_completed_pkt; + struct ble_ll_iso_conn conn; STAILQ_ENTRY(ble_ll_iso_bis) bis_q_next; }; @@ -86,12 +84,12 @@ struct big_params { uint8_t pto; /* 0-15, mandatory 0 */ uint32_t sdu_interval; uint16_t iso_interval; - uint16_t max_transport_latency; + uint16_t max_transport_latency_ms; uint16_t max_sdu; uint8_t max_pdu; uint8_t phy; + uint8_t framing; uint8_t interleaved : 1; - uint8_t framed : 1; uint8_t encrypted : 1; uint8_t broadcast_code[16]; }; @@ -114,6 +112,7 @@ struct ble_ll_iso_big { uint8_t nse; /* 1-31 */ uint8_t interleaved : 1; uint8_t framed : 1; + uint8_t framing_mode : 1; uint8_t encrypted : 1; uint8_t giv[8]; uint8_t gskd[16]; @@ -134,8 +133,12 @@ struct ble_ll_iso_big { uint64_t bis_counter; uint32_t sync_delay; + uint32_t transport_latency_us; uint32_t event_start; uint8_t event_start_us; + uint32_t anchor_base_ticks; + uint8_t anchor_base_rem_us; + uint16_t anchor_offset; struct ble_ll_sched_item sch; struct ble_npl_event event_done; @@ -146,6 +149,10 @@ struct ble_ll_iso_big { struct ble_ll_iso_bis_q bis_q; +#if MYNEWT_VAL(BLE_LL_ISO_HCI_FEEDBACK_INTERVAL_MS) + uint32_t last_feedback; +#endif + uint8_t cstf : 1; uint8_t cssn : 4; uint8_t control_active : 3; @@ -166,56 +173,47 @@ static uint8_t bis_pool_free = BIS_POOL_SIZE; static struct ble_ll_iso_big *big_pending; static struct ble_ll_iso_big *big_active; -struct ble_ll_iso_bis * -ble_ll_iso_big_find_bis_by_handle(uint16_t conn_handle) +static void +big_sched_set(struct ble_ll_iso_big *big) { - struct ble_ll_iso_bis *bis; - uint8_t bis_idx; + uint32_t offset_us; - if (!BLE_LL_CONN_HANDLE_IS_BIS(conn_handle)) { - return NULL; - } + big->sch.start_time = big->anchor_base_ticks; + big->sch.remainder = big->anchor_base_rem_us; - bis_idx = BLE_LL_CONN_HANDLE_IDX(conn_handle); + offset_us = big->anchor_offset * big->iso_interval * 1250; - if (bis_idx >= BIS_POOL_SIZE) { - return NULL; - } + ble_ll_tmr_add(&big->sch.start_time, &big->sch.remainder, offset_us); - bis = &bis_pool[bis_idx]; - if (!bis->big) { - return NULL; + /* Reset anchor base before anchor offset wraps-around. + * This happens much earlier than possible overflow in calculations. + */ + if (big->anchor_offset == UINT16_MAX) { + big->anchor_base_ticks = big->sch.start_time; + big->anchor_base_rem_us = big->sch.remainder; + big->anchor_offset = 0; } - return bis; -} - -struct ble_ll_isoal_mux * -ble_ll_iso_big_find_mux_by_handle(uint16_t conn_handle) -{ - struct ble_ll_iso_bis *bis; + big->sch.end_time = big->sch.start_time + + ble_ll_tmr_u2t_up(big->sync_delay) + 1; + big->sch.start_time -= g_ble_ll_sched_offset_ticks; - bis = ble_ll_iso_big_find_bis_by_handle(conn_handle); - if (bis) { - return &bis->mux; + if (big->control_active) { + /* XXX calculate proper time */ + big->sch.end_time += 10; } - - return NULL; } -int -ble_ll_iso_big_last_tx_timestamp_get(struct ble_ll_iso_bis *bis, - uint16_t *packet_seq_num, uint32_t *timestamp) +static void +ble_ll_iso_big_biginfo_chanmap_update(struct ble_ll_iso_big *big) { - struct ble_ll_iso_big *big; - - big = bis->big; + uint8_t *buf; - *packet_seq_num = big->bis_counter; - *timestamp = (uint64_t)big->event_start * 1000000 / 32768 + - big->event_start_us; + buf = &big->biginfo[23]; - return 0; + /* chm, phy */ + memcpy(buf, big->chan_map, 5); + buf[4] |= (big->phy - 1) << 5; } static void @@ -241,8 +239,8 @@ ble_ll_iso_big_biginfo_calc(struct ble_ll_iso_big *big, uint32_t seed_aa) put_le24(buf, (big->irc << 20) | (big->bis_spacing)); buf += 3; - /* max_pdu, rfu */ - put_le16(buf, big->max_pdu); + /* max_pdu, rfu, framing_mode */ + put_le16(buf, big->max_pdu | (big->framing_mode) << 15); buf += 2; /* seed_access_address */ @@ -258,12 +256,12 @@ ble_ll_iso_big_biginfo_calc(struct ble_ll_iso_big *big, uint32_t seed_aa) buf += 2; /* chm, phy */ - memcpy(buf, big->chan_map, 5); - buf[4] |= (big->phy - 1) << 5; + ble_ll_iso_big_biginfo_chanmap_update(big); buf += 5; /* bis_payload_cnt, framing */ - memset(buf, 0x00, 5); + memset(buf, 0x01, 5); + buf[4] |= (big->framed << 7) & 0x80; } int @@ -271,20 +269,38 @@ ble_ll_iso_big_biginfo_copy(struct ble_ll_iso_big *big, uint8_t *dptr, uint32_t base_ticks, uint8_t base_rem_us) { uint8_t *dptr_start; + uint32_t event_start; + uint8_t event_start_us; uint64_t counter; uint32_t offset_us; uint32_t offset; - uint32_t d_ticks; - uint8_t d_rem_us; dptr_start = dptr; counter = big->bis_counter; - d_ticks = big->event_start - base_ticks; - d_rem_us = big->event_start_us; - ble_ll_tmr_sub(&d_ticks, &d_rem_us, base_rem_us); + event_start = big->event_start; + event_start_us = big->event_start_us; + + /* Use next BIG event in case current one is before AUX_SYNC_IND. This can + * happen if AUX_SYNC_IND is scheduled right after BIG event and the BIG + * was not yet advanced to next event. + */ + if (event_start <= base_ticks) { + ble_ll_tmr_add(&event_start, &event_start_us, big->iso_interval * 1250); + counter += big->bn; + } + + /* Drop BIGInfo if BIG event is still before AUX_SYNC_IND. This should not + * happen but better not send invalid offset. + */ + if (event_start <= base_ticks) { + return 0; + } + + offset_us = ble_ll_tmr_t2u(event_start - base_ticks); + offset_us += event_start_us; + offset_us -= base_rem_us; - offset_us = ble_ll_tmr_t2u(d_ticks) + d_rem_us; if (offset_us <= 600) { counter += big->bn; offset_us += big->iso_interval * 1250; @@ -306,7 +322,7 @@ ble_ll_iso_big_biginfo_copy(struct ble_ll_iso_big *big, uint8_t *dptr, *dptr++ = (counter >> 8) & 0xff; *dptr++ = (counter >> 16) & 0xff; *dptr++ = (counter >> 24) & 0xff; - *dptr++ = (counter >> 32) & 0xff; + *dptr++ = ((counter >> 32) & 0x7f) | ((big->framed << 7) & 0x80); if (big->encrypted) { memcpy(dptr, big->giv, 8); @@ -339,7 +355,7 @@ ble_ll_iso_big_free(struct ble_ll_iso_big *big) ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &big->event_done); STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { - ble_ll_isoal_mux_free(&bis->mux); + ble_ll_iso_conn_free(&bis->conn); bis->big = NULL; bis_pool_free++; } @@ -382,16 +398,22 @@ ble_ll_iso_big_chan_map_update_complete(struct ble_ll_iso_big *big) { memcpy(big->chan_map, big->chan_map_new, BLE_LL_CHAN_MAP_LEN); big->chan_map_used = ble_ll_utils_chan_map_used_get(big->chan_map); + + ble_ll_iso_big_biginfo_chanmap_update(big); } static void -ble_ll_iso_big_update_event_start(struct ble_ll_iso_big *big) +ble_ll_iso_big_update_event_start(struct ble_ll_iso_big *big, + uint64_t new_big_counter) { os_sr_t sr; OS_ENTER_CRITICAL(sr); + /* This has to be updated atomically to avoid races when copying to BIGInfo */ big->event_start = big->sch.start_time + g_ble_ll_sched_offset_ticks; big->event_start_us = big->sch.remainder; + big->bis_counter += (new_big_counter - big->big_counter) * big->bn; + big->big_counter = new_big_counter; OS_EXIT_CRITICAL(sr); } @@ -400,8 +422,17 @@ ble_ll_iso_big_event_done(struct ble_ll_iso_big *big) { struct ble_ll_iso_bis *bis; struct ble_hci_ev *hci_ev; - struct ble_hci_ev_num_comp_pkts *hci_ev_ncp; +#if MYNEWT_VAL(BLE_LL_ISO_HCI_FEEDBACK_INTERVAL_MS) + struct ble_hci_ev *fb_hci_ev = NULL; + struct ble_hci_ev_vs *fb_hci_ev_vs; + struct ble_hci_vs_subev_iso_hci_feedback *fb_hci_subev = NULL; + uint16_t exp; + uint32_t now; +#endif + uint64_t big_counter; + struct ble_hci_ev_num_comp_pkts *hci_ev_ncp = NULL; int num_completed_pkt; + int idx; int rc; ble_ll_rfmgmt_release(); @@ -419,18 +450,46 @@ ble_ll_iso_big_event_done(struct ble_ll_iso_big *big) hci_ev_ncp->count = 0; } +#if MYNEWT_VAL(BLE_LL_ISO_HCI_FEEDBACK_INTERVAL_MS) + now = os_time_get(); + if (OS_TIME_TICK_GEQ(now, big->last_feedback + + os_time_ms_to_ticks32(MYNEWT_VAL(BLE_LL_ISO_HCI_FEEDBACK_INTERVAL_MS)))) { + fb_hci_ev = ble_transport_alloc_evt(1); + if (fb_hci_ev) { + fb_hci_ev->opcode = BLE_HCI_EVCODE_VS; + fb_hci_ev->length = sizeof(*fb_hci_ev_vs) + sizeof(*fb_hci_subev); + fb_hci_ev_vs = (void *)fb_hci_ev->data; + fb_hci_ev_vs->id = BLE_HCI_VS_SUBEV_ISO_HCI_FEEDBACK; + fb_hci_subev = (void *)fb_hci_ev_vs->data; + fb_hci_subev->big_handle = big->handle; + fb_hci_subev->count = 0; + } + } +#endif + STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { - num_completed_pkt = ble_ll_isoal_mux_event_done(&bis->mux); + num_completed_pkt = ble_ll_iso_conn_event_done(&bis->conn); if (hci_ev && num_completed_pkt) { - hci_ev_ncp->completed[hci_ev_ncp->count].handle = - htole16(bis->conn_handle); - hci_ev_ncp->completed[hci_ev_ncp->count].packets = - htole16(num_completed_pkt + bis->num_completed_pkt); - bis->num_completed_pkt = 0; - hci_ev_ncp->count++; - } else { - bis->num_completed_pkt += num_completed_pkt; + idx = hci_ev_ncp->count++; + hci_ev_ncp->completed[idx].handle = htole16(bis->conn.handle); + hci_ev_ncp->completed[idx].packets = htole16(num_completed_pkt); + bis->conn.num_completed_pkt = 0; + } + +#if MYNEWT_VAL(BLE_LL_ISO_HCI_FEEDBACK_INTERVAL_MS) + if (fb_hci_ev) { + /* Expected SDUs in queue after an event -> host should send + * sdu_per_interval SDUs until next event so there are sdu_per_event + * SDUs queued at next event. Feedback value is the difference between + * expected and actual SDUs count. + */ + exp = bis->mux.sdu_per_event - bis->mux.sdu_per_interval; + idx = fb_hci_subev->count++; + fb_hci_subev->feedback[idx].handle = htole16(bis->conn.handle); + fb_hci_subev->feedback[idx].sdu_per_interval = bis->mux.sdu_per_interval; + fb_hci_subev->feedback[idx].diff = (int8_t)(bis->mux.sdu_q_len - exp); } +#endif } if (hci_ev) { @@ -443,15 +502,24 @@ ble_ll_iso_big_event_done(struct ble_ll_iso_big *big) } } +#if MYNEWT_VAL(BLE_LL_ISO_HCI_FEEDBACK_INTERVAL_MS) + if (fb_hci_ev) { + fb_hci_ev->length = sizeof(*fb_hci_ev_vs) + sizeof(*fb_hci_subev) + + fb_hci_subev->count * sizeof(fb_hci_subev->feedback[0]); + ble_transport_to_hs_evt(fb_hci_ev); + big->last_feedback = now; + } +#endif + big->sch.start_time = big->event_start; big->sch.remainder = big->event_start_us; + big_counter = big->big_counter; do { - big->big_counter++; - big->bis_counter += big->bn; + big_counter++; if (big->control_active && - (big->control_instant == (uint16_t)big->big_counter)) { + (big->control_instant == (uint16_t)big_counter)) { switch (big->control_active) { case BIG_CONTROL_ACTIVE_TERM: ble_ll_iso_big_terminate_complete(big); @@ -480,31 +548,21 @@ ble_ll_iso_big_event_done(struct ble_ll_iso_big *big) } if (big->control_active) { - big->control_instant = big->big_counter + 6; + big->control_instant = big_counter + 6; big->cstf = 1; big->cssn += 1; } } - /* XXX precalculate some data here? */ - - ble_ll_tmr_add(&big->sch.start_time, &big->sch.remainder, - big->iso_interval * 1250); - big->sch.end_time = big->sch.start_time + - ble_ll_tmr_u2t_up(big->sync_delay) + 1; - big->sch.start_time -= g_ble_ll_sched_offset_ticks; - - if (big->control_active) { - /* XXX fixme */ - big->sch.end_time += 10; - } + big->anchor_offset++; + big_sched_set(big); - /* XXX this should always succeed since we preempt anything for now */ - rc = ble_ll_sched_iso_big(&big->sch, 0); - assert(rc == 0); + /* This should always succeed since we preempt anything for now */ + rc = ble_ll_sched_iso_big(&big->sch, 0, 1); + BLE_LL_ASSERT(rc == 0); } while (rc < 0); - ble_ll_iso_big_update_event_start(big); + ble_ll_iso_big_update_event_start(big, big_counter); } static void @@ -627,7 +685,7 @@ ble_ll_iso_big_subevent_pdu_cb(uint8_t *dptr, void *arg, uint8_t *hdr_byte) } #if 1 - pdu_len = ble_ll_isoal_mux_unframed_get(&bis->mux, idx, &llid, dptr); + pdu_len = ble_ll_iso_pdu_get(&bis->conn, idx, big->bis_counter + idx, &llid, dptr); #else llid = 0; pdu_len = big->max_pdu; @@ -743,7 +801,7 @@ ble_ll_iso_big_event_sched_cb(struct ble_ll_sched_item *sch) { struct ble_ll_iso_big *big; struct ble_ll_iso_bis *bis; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) uint8_t phy_mode; #endif int rc; @@ -757,17 +815,17 @@ ble_ll_iso_big_event_sched_cb(struct ble_ll_sched_item *sch) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) ble_phy_resolv_list_disable(); #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) phy_mode = ble_ll_phy_to_phy_mode(big->phy, 0); ble_phy_mode_set(phy_mode, phy_mode); #endif - BLE_LL_ASSERT(!big->framed); + ble_ll_tx_power_set(g_ble_ll_tx_power); /* XXX calculate this in advance at the end of previous event? */ big->tx.subevents_rem = big->num_bis * big->nse; STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { - ble_ll_isoal_mux_event_start(&bis->mux, (uint64_t)big->event_start * + ble_ll_iso_conn_event_start(&bis->conn, (uint64_t)big->event_start * 1000000 / 32768 + big->event_start_us); @@ -867,11 +925,18 @@ static int ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, struct big_params *bp) { + struct ble_ll_iso_conn_init_param conn_init_param = { + .iso_interval_us = bp->iso_interval * 1250, + .sdu_interval_us = bp->sdu_interval, + .max_sdu = bp->max_sdu, + .max_pdu = bp->max_pdu, + .framing = bp->framing, + .bn = bp->bn, + }; struct ble_ll_iso_big *big = NULL; struct ble_ll_iso_bis *bis; struct ble_ll_adv_sm *advsm; uint32_t seed_aa; - uint8_t pte; uint8_t gc; uint8_t idx; int rc; @@ -892,17 +957,21 @@ ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, BLE_LL_ASSERT(big); + big_pool_free--; + big->handle = big_handle; + advsm = ble_ll_adv_sync_get(adv_handle); if (!advsm) { + ble_ll_iso_big_free(big); return -ENOENT; } if (ble_ll_adv_sync_big_add(advsm, big) < 0) { + ble_ll_iso_big_free(big); return -ENOENT; } big->advsm = advsm; - big->handle = big_handle; big->crc_init = ble_ll_rand(); memcpy(big->chan_map, g_ble_ll_data.chan_map, BLE_LL_CHAN_MAP_LEN); @@ -923,9 +992,9 @@ ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, /* Core 5.3, Vol 6, Part B, 4.4.6.6 */ gc = bp->nse / bp->bn; if (bp->irc == gc) { - pte = 0; + conn_init_param.pte = 0; } else { - pte = bp->pto * (gc - bp->irc); + conn_init_param.pte = bp->pto * (gc - bp->irc); } /* Allocate BISes */ @@ -944,46 +1013,20 @@ ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, bis->num = big->num_bis; bis->crc_init = (big->crc_init << 8) | (big->num_bis); - BLE_LL_ASSERT(!big->framed); + conn_init_param.conn_handle = BLE_LL_CONN_HANDLE(BLE_LL_CONN_HANDLE_TYPE_BIS, idx); - ble_ll_isoal_mux_init(&bis->mux, bp->max_pdu, bp->iso_interval * 1250, - bp->sdu_interval, bp->bn, pte); + ble_ll_iso_conn_init(&bis->conn, &conn_init_param); } - big_pool_free--; bis_pool_free -= num_bis; - /* Calculate AA for each BIS and BIG Control. We have to repeat this process - * until all AAs are valid. - */ - do { - rc = 0; - - seed_aa = ble_ll_utils_calc_seed_aa(); - big->ctrl_aa = ble_ll_utils_calc_big_aa(seed_aa, 0); - - if (!ble_ll_utils_verify_aa(big->ctrl_aa)) { - continue; - } - - rc = 1; - - STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { - bis->aa = ble_ll_utils_calc_big_aa(seed_aa, bis->num); - if (!ble_ll_utils_verify_aa(bis->aa)) { - rc = 0; - break; - } - bis->chan_id = bis->aa ^ (bis->aa >> 16); - } - } while (rc == 0); - big->bn = bp->bn; big->pto = bp->pto; big->irc = bp->irc; big->nse = bp->nse; big->interleaved = bp->interleaved; - big->framed = bp->framed; + big->framed = bp->framing != BLE_HCI_ISO_FRAMING_UNFRAMED; + big->framing_mode = bp->framing == BLE_HCI_ISO_FRAMING_FRAMED_UNSEGMENTED; big->encrypted = bp->encrypted; big->sdu_interval = bp->sdu_interval; big->iso_interval = bp->iso_interval; @@ -1013,13 +1056,54 @@ ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, big->pto = 0; } + /* Core 6.0, Vol 6, Part G, 3.2.1 and 3.2.2 */ + if (big->framed) { + big->transport_latency_us = big->sync_delay + + (big->pto * (big->nse / big->bn - big->irc) + 1) * + big->iso_interval * 1250 + big->sdu_interval; + } else { + big->transport_latency_us = big->sync_delay + + (big->pto * (big->nse / big->bn - big->irc) + 1) * + big->iso_interval * 1250 - big->sdu_interval; + } + + if (big->transport_latency_us > bp->max_transport_latency_ms * 1000) { + ble_ll_iso_big_free(big); + return -ERANGE; + } + + /* Calculate AA for each BIS and BIG Control. We have to repeat this process + * until all AAs are valid. + */ + do { + rc = 0; + + seed_aa = ble_ll_utils_calc_seed_aa(); + big->ctrl_aa = ble_ll_utils_calc_big_aa(seed_aa, 0); + + if (!ble_ll_utils_verify_aa(big->ctrl_aa)) { + continue; + } + + rc = 1; + + STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { + bis->aa = ble_ll_utils_calc_big_aa(seed_aa, bis->num); + if (!ble_ll_utils_verify_aa(bis->aa)) { + rc = 0; + break; + } + bis->chan_id = bis->aa ^ (bis->aa >> 16); + } + } while (rc == 0); + + ble_ll_iso_big_biginfo_calc(big, seed_aa); + if (big->encrypted) { ble_ll_iso_big_calculate_gsk(big, bp->broadcast_code); ble_ll_iso_big_calculate_iv(big); } - ble_ll_iso_big_biginfo_calc(big, seed_aa); - /* For now we will schedule complete event as single item. This allows for * shortest possible subevent space (150us) but can create sequence of long * events that will block scheduler from other activities. To mitigate this @@ -1031,24 +1115,42 @@ ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, * not enough for some phys to run scheduler item. */ - /* Schedule 1st event a bit in future */ - /* FIXME schedule 6ms in the future to avoid conflict with periodic - * advertising when both are started at the same time; we should - * select this value in some smart way later... - */ - big->sch.start_time = ble_ll_tmr_get() + ble_ll_tmr_u2t(6000); - big->sch.remainder = 0; - big->sch.end_time = big->sch.start_time + - ble_ll_tmr_u2t_up(big->sync_delay) + 1; - big->sch.start_time -= g_ble_ll_sched_offset_ticks; + uint32_t padv_start_time, big_start_time; + uint32_t sync_delay_ticks = ble_ll_tmr_u2t_up(big->sync_delay); + int big_event_fixed; - rc = ble_ll_sched_iso_big(&big->sch, 1); - if (rc < 0) { - ble_ll_iso_big_free(big); - return -EFAULT; + rc = ble_ll_adv_padv_event_start_get(big->advsm, &padv_start_time, NULL); + if (rc) { + /* 1st event will be moved by 1 interval before scheduling so this will + * be always in the future */ + big_start_time = ble_ll_tmr_get(); + big_event_fixed = 0; + } else { + /* Set 1st BIG event directly before periodic advertising event, this + * way it will not overlap it even if periodic advertising data changes. + * Make sure it's in the future. + */ + big_start_time = padv_start_time - g_ble_ll_sched_offset_ticks - + sync_delay_ticks - 1; + big_event_fixed = 1; } - ble_ll_iso_big_update_event_start(big); + big->anchor_base_ticks = big_start_time; + big->anchor_base_rem_us = 0; + big->anchor_offset = 0; + + do { + big->anchor_offset++; + big_sched_set(big); + + if (LL_TMR_LEQ(big->sch.start_time, ble_ll_tmr_get())) { + rc = -1; + } else { + rc = ble_ll_sched_iso_big(&big->sch, 1, big_event_fixed); + } + } while (rc < 0); + + ble_ll_iso_big_update_event_start(big, big->big_counter); big_pending = big; @@ -1141,10 +1243,7 @@ ble_ll_iso_big_hci_evt_complete(void) evt->big_handle = big->handle; put_le24(evt->big_sync_delay, big->sync_delay); /* Core 5.3, Vol 6, Part G, 3.2.2 */ - put_le24(evt->transport_latency_big, - big->sync_delay + - (big->pto * (big->nse / big->bn - big->irc) + 1) * big->iso_interval * 1250 - - big->sdu_interval); + put_le24(evt->transport_latency_big, big->transport_latency_us); evt->phy = big->phy; evt->nse = big->nse; evt->bn = big->bn; @@ -1156,7 +1255,7 @@ ble_ll_iso_big_hci_evt_complete(void) idx = 0; STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { - evt->conn_handle[idx] = htole16(bis->conn_handle); + evt->conn_handle[idx] = htole16(bis->conn.handle); idx++; } @@ -1168,6 +1267,7 @@ ble_ll_iso_big_hci_create(const uint8_t *cmdbuf, uint8_t len) { const struct ble_hci_le_create_big_cp *cmd = (void *)cmdbuf; struct big_params bp; + uint8_t valid_phys; int rc; if (len != sizeof(*cmd)) { @@ -1181,12 +1281,24 @@ ble_ll_iso_big_hci_create(const uint8_t *cmdbuf, uint8_t len) !IN_RANGE(le16toh(cmd->max_sdu), 0x0001, 0x0fff) || !IN_RANGE(le16toh(cmd->max_transport_latency), 0x0005, 0x0fa0) || !IN_RANGE(cmd->rtn, 0x00, 0x1e) || - (cmd->packing > 1) || (cmd->framing > 1) || (cmd->encryption) > 1) { + (cmd->packing > 1) || (cmd->framing > 2) || (cmd->encryption) > 1) { return BLE_ERR_INV_HCI_CMD_PARMS; } + valid_phys = BLE_HCI_LE_PHY_1M_PREF_MASK; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + valid_phys |= BLE_HCI_LE_PHY_2M_PREF_MASK; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + valid_phys |= BLE_HCI_LE_PHY_CODED_PREF_MASK; +#endif + + if (cmd->phy & ~valid_phys) { + return BLE_ERR_UNSUPPORTED; + } + bp.sdu_interval = get_le24(cmd->sdu_interval); - bp.max_transport_latency = le16toh(cmd->max_transport_latency); + bp.max_transport_latency_ms = le16toh(cmd->max_transport_latency); bp.max_sdu = le16toh(cmd->max_sdu); if (cmd->phy & BLE_HCI_LE_PHY_2M_PREF_MASK) { bp.phy = BLE_PHY_2M; @@ -1196,28 +1308,53 @@ ble_ll_iso_big_hci_create(const uint8_t *cmdbuf, uint8_t len) bp.phy = BLE_PHY_CODED; } bp.interleaved = cmd->packing; - bp.framed = cmd->framing; bp.encrypted = cmd->encryption; memcpy(bp.broadcast_code, cmd->broadcast_code, 16); - bp.nse = 1; - bp.bn = 1; - bp.irc = 1; + /* FIXME for now we only care about retransmissions, so set both NSE and IRC + * to RTN + */ + bp.nse = MIN(cmd->rtn + 1, 0x0f);; + bp.irc = MIN(cmd->rtn + 1, 0x0f); bp.pto = 0; - bp.iso_interval = bp.sdu_interval / 1250; - bp.max_pdu = bp.max_sdu; + + uint32_t iso_interval = bp.sdu_interval / 1250; + if (bp.sdu_interval > iso_interval * 1250) { + /* The requirements for using Unframed PDUs are not met */ + bp.framing = BLE_HCI_ISO_FRAMING_FRAMED_SEGMENTABLE; + bp.iso_interval = iso_interval + 1; + bp.bn = 2; + bp.max_pdu = bp.max_sdu + 5; + } else { + bp.framing = cmd->framing; + bp.iso_interval = iso_interval; + bp.bn = 1; + if (cmd->framing == BLE_HCI_ISO_FRAMING_UNFRAMED) { + bp.max_pdu = bp.max_sdu; + } else { + /** + * XXX: The requirements for using Unframed PDUs are met but the user + * requested Framed PDUs explicitly. Ensure the PDU fits the Segmentation Header. + */ + bp.max_pdu = bp.max_sdu + 5; + } + } rc = ble_ll_iso_big_create(cmd->big_handle, cmd->adv_handle, cmd->num_bis, &bp); switch (rc) { case 0: break; + case -EALREADY: + return BLE_ERR_CMD_DISALLOWED; case -EINVAL: return BLE_ERR_INV_HCI_CMD_PARMS; case -ENOMEM: return BLE_ERR_CONN_REJ_RESOURCES; case -ENOENT: return BLE_ERR_UNK_ADV_INDENT; + case -ERANGE: + return BLE_ERR_UNSUPPORTED; default: return BLE_ERR_UNSPECIFIED; } @@ -1260,6 +1397,7 @@ ble_ll_iso_big_hci_create_test(const uint8_t *cmdbuf, uint8_t len) bp.pto = cmd->pto; bp.sdu_interval = get_le24(cmd->sdu_interval); bp.iso_interval = le16toh(cmd->iso_interval); + bp.max_transport_latency_ms = 0x0fa0; /* max_transport_latency for HCI LE Create BIG */ bp.max_sdu = le16toh(cmd->max_sdu); bp.max_pdu = le16toh(cmd->max_pdu); /* TODO verify phy */ @@ -1271,7 +1409,7 @@ ble_ll_iso_big_hci_create_test(const uint8_t *cmdbuf, uint8_t len) bp.phy = BLE_PHY_CODED; } bp.interleaved = cmd->packing; - bp.framed = cmd->framing; + bp.framing = cmd->framing; bp.encrypted = cmd->encryption; memcpy(bp.broadcast_code, cmd->broadcast_code, 16); @@ -1281,7 +1419,7 @@ ble_ll_iso_big_hci_create_test(const uint8_t *cmdbuf, uint8_t len) iso_interval_us = bp.iso_interval * 1250; - if (!bp.framed) { + if (bp.framing == BLE_HCI_ISO_FRAMING_UNFRAMED) { /* sdu_interval shall be an integer multiple of iso_interval */ if (iso_interval_us % bp.sdu_interval) { return BLE_ERR_INV_HCI_CMD_PARMS; @@ -1298,12 +1436,16 @@ ble_ll_iso_big_hci_create_test(const uint8_t *cmdbuf, uint8_t len) switch (rc) { case 0: break; + case -EALREADY: + return BLE_ERR_CMD_DISALLOWED; case -EINVAL: return BLE_ERR_INV_HCI_CMD_PARMS; case -ENOMEM: return BLE_ERR_CONN_REJ_RESOURCES; case -ENOENT: return BLE_ERR_UNK_ADV_INDENT; + case -ERANGE: + return BLE_ERR_UNSUPPORTED; default: return BLE_ERR_UNSPECIFIED; } @@ -1334,7 +1476,6 @@ void ble_ll_iso_big_init(void) { struct ble_ll_iso_big *big; - struct ble_ll_iso_bis *bis; uint8_t idx; memset(big_pool, 0, sizeof(big_pool)); @@ -1352,11 +1493,6 @@ ble_ll_iso_big_init(void) ble_npl_event_init(&big->event_done, ble_ll_iso_big_event_done_ev, big); } - for (idx = 0; idx < BIS_POOL_SIZE; idx++) { - bis = &bis_pool[idx]; - bis->conn_handle = BLE_LL_CONN_HANDLE(BLE_LL_CONN_HANDLE_TYPE_BIS, idx); - } - big_pool_free = ARRAY_SIZE(big_pool); bis_pool_free = ARRAY_SIZE(bis_pool); } @@ -1376,4 +1512,5 @@ ble_ll_iso_big_reset(void) } #endif /* BLE_LL_ISO_BROADCASTER */ + #endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_isoal.c b/src/nimble/nimble/controller/src/ble_ll_isoal.c index 65c3ddce4..0308639da 100644 --- a/src/nimble/nimble/controller/src/ble_ll_isoal.c +++ b/src/nimble/nimble/controller/src/ble_ll_isoal.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,153 +19,148 @@ * under the License. */ -#ifndef ESP_PLATFORM - #include #include -#include -#include -#include -#include - -#if MYNEWT_VAL(BLE_LL_ISO) +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_isoal.h" -STAILQ_HEAD(ble_ll_iso_tx_q, os_mbuf_pkthdr); +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif -static struct ble_npl_event ll_isoal_tx_pkt_in; -static struct ble_ll_iso_tx_q ll_isoal_tx_q; +#if MYNEWT_VAL(BLE_LL_ISO) void ble_ll_isoal_mux_init(struct ble_ll_isoal_mux *mux, uint8_t max_pdu, uint32_t iso_interval_us, uint32_t sdu_interval_us, - uint8_t bn, uint8_t pte) + uint8_t bn, uint8_t pte, bool framed, uint8_t framing_mode) { memset(mux, 0, sizeof(*mux)); mux->max_pdu = max_pdu; /* Core 5.3, Vol 6, Part G, 2.1 */ mux->sdu_per_interval = iso_interval_us / sdu_interval_us; - mux->pdu_per_sdu = bn / mux->sdu_per_interval; + + if (framed) { + /* TODO */ + } else { + mux->pdu_per_sdu = bn / mux->sdu_per_interval; + } mux->sdu_per_event = (1 + pte) * mux->sdu_per_interval; + mux->bn = bn; + STAILQ_INIT(&mux->sdu_q); + mux->sdu_q_len = 0; + + mux->framed = framed; + mux->framing_mode = framing_mode; } void ble_ll_isoal_mux_free(struct ble_ll_isoal_mux *mux) { struct os_mbuf_pkthdr *pkthdr; - struct os_mbuf *om; - struct os_mbuf *om_next; pkthdr = STAILQ_FIRST(&mux->sdu_q); while (pkthdr) { - om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + /* remove from list before freeing om */ + STAILQ_REMOVE_HEAD(&mux->sdu_q, omp_next); - while (om) { - om_next = SLIST_NEXT(om, om_next); - os_mbuf_free(om); - om = om_next; - } + os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(pkthdr)); - STAILQ_REMOVE_HEAD(&mux->sdu_q, omp_next); pkthdr = STAILQ_FIRST(&mux->sdu_q); } STAILQ_INIT(&mux->sdu_q); + mux->sdu_q_len = 0; } -static void -ble_ll_isoal_mux_tx_pkt_in(struct ble_ll_isoal_mux *mux, struct os_mbuf *om, - uint8_t pb, uint32_t timestamp) +void +ble_ll_isoal_mux_sdu_enqueue(struct ble_ll_isoal_mux *mux, struct os_mbuf *om) { struct os_mbuf_pkthdr *pkthdr; - struct ble_mbuf_hdr *blehdr; os_sr_t sr; BLE_LL_ASSERT(mux); - switch (pb) { - case BLE_HCI_ISO_PB_FIRST: - BLE_LL_ASSERT(!mux->frag); - mux->frag = om; - om = NULL; - break; - case BLE_HCI_ISO_PB_CONTINUATION: - BLE_LL_ASSERT(mux->frag); - os_mbuf_concat(mux->frag, om); - om = NULL; - break; - case BLE_HCI_ISO_PB_COMPLETE: - BLE_LL_ASSERT(!mux->frag); - break; - case BLE_HCI_ISO_PB_LAST: - BLE_LL_ASSERT(mux->frag); - os_mbuf_concat(mux->frag, om); - om = mux->frag; - mux->frag = NULL; - break; - default: - BLE_LL_ASSERT(0); - break; - } - - if (!om) { - return; - } - - blehdr = BLE_MBUF_HDR_PTR(om); - blehdr->txiso.packet_seq_num = ++mux->sdu_counter; - OS_ENTER_CRITICAL(sr); pkthdr = OS_MBUF_PKTHDR(om); STAILQ_INSERT_TAIL(&mux->sdu_q, pkthdr, omp_next); + mux->sdu_q_len++; +#if MYNEWT_VAL(BLE_LL_ISOAL_MUX_PREFILL) + if (mux->sdu_q_len >= mux->sdu_per_event) { + mux->active = 1; + } +#endif OS_EXIT_CRITICAL(sr); } int ble_ll_isoal_mux_event_start(struct ble_ll_isoal_mux *mux, uint32_t timestamp) { - struct os_mbuf_pkthdr *pkthdr; - uint8_t num_sdu; - - num_sdu = mux->sdu_per_event; - - pkthdr = STAILQ_FIRST(&mux->sdu_q); - while (pkthdr && num_sdu--) { - pkthdr = STAILQ_NEXT(pkthdr, omp_next); +#if MYNEWT_VAL(BLE_LL_ISOAL_MUX_PREFILL) + /* If prefill is enabled, we always expect to have required number of SDUs + * in queue, otherwise we disable mux until enough SDUs are queued again. + */ + if (mux->sdu_per_event > mux->sdu_q_len) { + mux->active = 0; } - - mux->sdu_in_event = mux->sdu_per_event - num_sdu; + if (mux->active && mux->framed) { + mux->sdu_in_event = mux->sdu_q_len; + } else if (mux->active) { + mux->sdu_in_event = mux->sdu_per_event; + } else { + mux->sdu_in_event = 0; + } +#else + if (mux->framed) { + mux->sdu_in_event = mux->sdu_q_len; + } else { + mux->sdu_in_event = min(mux->sdu_q_len, mux->sdu_per_event); + } +#endif mux->event_tx_timestamp = timestamp; return mux->sdu_in_event; } -int -ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux) +static int +ble_ll_isoal_mux_unframed_event_done(struct ble_ll_isoal_mux *mux) { struct os_mbuf_pkthdr *pkthdr; - struct ble_mbuf_hdr *blehdr; struct os_mbuf *om; struct os_mbuf *om_next; uint8_t num_sdu; int pkt_freed = 0; + os_sr_t sr; num_sdu = min(mux->sdu_in_event, mux->sdu_per_interval); - pkthdr = STAILQ_FIRST(&mux->sdu_q); - if (pkthdr) { - om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); - blehdr = BLE_MBUF_HDR_PTR(om); - mux->last_tx_timestamp = mux->event_tx_timestamp; - mux->last_tx_packet_seq_num = blehdr->txiso.packet_seq_num; +#if MYNEWT_VAL(BLE_LL_ISO_HCI_DISCARD_THRESHOLD) + /* Drop queued SDUs if number of queued SDUs exceeds defined threshold. + * Threshold is defined as number of ISO events. If number of queued SDUs + * exceeds number of SDUs required for single event (i.e. including pt) + * and number of subsequent ISO events defined by threshold value, we'll + * drop any excessive SDUs and notify host as if they were sent. + */ + uint32_t thr = MYNEWT_VAL(BLE_LL_ISO_HCI_DISCARD_THRESHOLD); + if (mux->sdu_q_len > mux->sdu_per_event + thr * mux->sdu_per_interval) { + num_sdu = mux->sdu_q_len - mux->sdu_per_event - + thr * mux->sdu_per_interval; } +#endif + pkthdr = STAILQ_FIRST(&mux->sdu_q); while (pkthdr && num_sdu--) { - om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + OS_ENTER_CRITICAL(sr); + STAILQ_REMOVE_HEAD(&mux->sdu_q, omp_next); + BLE_LL_ASSERT(mux->sdu_q_len > 0); + mux->sdu_q_len--; + OS_EXIT_CRITICAL(sr); + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); while (om) { om_next = SLIST_NEXT(om, om_next); os_mbuf_free(om); @@ -171,7 +168,6 @@ ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux) om = om_next; } - STAILQ_REMOVE_HEAD(&mux->sdu_q, omp_next); pkthdr = STAILQ_FIRST(&mux->sdu_q); } @@ -180,23 +176,165 @@ ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux) return pkt_freed; } +static struct os_mbuf * +ble_ll_isoal_sdu_trim(struct os_mbuf *om, int *pkt_freed) +{ + /* Count the number of packets that will be freed. */ + for (struct os_mbuf *mbuf = om; mbuf; mbuf = SLIST_NEXT(mbuf, om_next)) { + if (mbuf->om_len == 0) { + (*pkt_freed)++; + } + } + + return os_mbuf_trim_front(om); +} + +static int +ble_ll_isoal_mux_framed_event_done(struct ble_ll_isoal_mux *mux) +{ + struct os_mbuf_pkthdr *pkthdr; + struct os_mbuf_pkthdr *pkthdr_temp; + struct os_mbuf *om; + uint8_t num_sdu; + uint8_t num_pdu; + uint8_t pdu_len = 0; + uint8_t frag_len = 0; + uint8_t hdr_len = 0; + int pkt_freed = 0; + os_sr_t sr; + + num_sdu = mux->sdu_in_event; + if (num_sdu == 0) { + return 0; + } + + num_pdu = mux->bn; + +#if MYNEWT_VAL(BLE_LL_ISO_HCI_DISCARD_THRESHOLD) + /* Drop queued SDUs if number of queued SDUs exceeds defined threshold. + * Threshold is defined as number of ISO events. If number of queued SDUs + * exceeds number of SDUs required for single event (i.e. including pt) + * and number of subsequent ISO events defined by threshold value, we'll + * drop any excessive SDUs and notify host as if they were sent. + */ + uint32_t thr = MYNEWT_VAL(BLE_LL_ISO_HCI_DISCARD_THRESHOLD); + if (mux->sdu_q_len > mux->sdu_per_event + thr * mux->sdu_per_interval) { + num_sdu = mux->sdu_q_len - mux->sdu_per_event - + thr * mux->sdu_per_interval; + } +#endif + + /* Iterate over all queued SDUs. */ + STAILQ_FOREACH_SAFE(pkthdr, &mux->sdu_q, omp_next, pkthdr_temp) { + if (num_sdu == 0) { + break; + } + + BLE_LL_ASSERT(mux->sdu_q_len > 0); + + /* Remove the SDU from the queue, as we are about to free some buffers from a chain. + * Otherwise, it will result in invalid head pointed by sdu_q entry. + */ + OS_ENTER_CRITICAL(sr); + STAILQ_REMOVE_HEAD(&mux->sdu_q, omp_next); + mux->sdu_q_len--; + OS_EXIT_CRITICAL(sr); + + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + + /* Iterate over all buffers in the SDU chain. */ + while (num_pdu > 0 && OS_MBUF_PKTLEN(om) > 0) { + hdr_len = mux->sc ? 2 /* Segmentation Header */ + : 5 /* Segmentation Header + TimeOffset */; + + /* If the next SDU fragment header size exceeds remaining space in the PDU, advance to next PDU. */ + if (mux->max_pdu <= hdr_len + pdu_len) { + pdu_len = 0; + num_pdu--; + continue; + } + + /* "Put" the header in the PDU. */ + pdu_len += hdr_len; + + /* SDU fragment length that can be fit in the PDU. */ + frag_len = min(OS_MBUF_PKTLEN(om), mux->max_pdu - pdu_len); + + /* Increase PDU length by the length of the SDU fragment. */ + pdu_len += frag_len; + + os_mbuf_adj(om, frag_len); + + /* If the SDU fragment does not fit in the PDU, set the SC flag. */ + if (OS_MBUF_PKTLEN(om) > frag_len) { + mux->sc = 1; + } else { + mux->sc = 0; + } + } + + om = ble_ll_isoal_sdu_trim(om, &pkt_freed); + if (OS_MBUF_PKTLEN(om) > 0) { + /* If there is still data in the SDU chain, place the SDU back in the queue. */ + OS_ENTER_CRITICAL(sr); + STAILQ_INSERT_HEAD(&mux->sdu_q, pkthdr, omp_next); + mux->sdu_q_len++; + OS_EXIT_CRITICAL(sr); + } else { + /* If there are no more data in the SDU chain, free the SDU chain. */ + os_mbuf_free_chain(om); + num_sdu--; + } + + if (num_pdu == 0) { + break; + } + } + + mux->sdu_in_event = 0; + + return pkt_freed; +} + int +ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux) +{ + struct os_mbuf_pkthdr *pkthdr; + struct ble_mbuf_hdr *blehdr; + struct os_mbuf *om; + + pkthdr = STAILQ_FIRST(&mux->sdu_q); + if (pkthdr) { + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + blehdr = BLE_MBUF_HDR_PTR(om); + mux->last_tx_timestamp = mux->event_tx_timestamp; + mux->last_tx_packet_seq_num = blehdr->txiso.packet_seq_num; + } + + if (mux->framed) { + return ble_ll_isoal_mux_framed_event_done(mux); + } + + return ble_ll_isoal_mux_unframed_event_done(mux); +} + +static int ble_ll_isoal_mux_unframed_get(struct ble_ll_isoal_mux *mux, uint8_t idx, uint8_t *llid, void *dptr) { struct os_mbuf_pkthdr *pkthdr; struct os_mbuf *om; + int32_t rem_len; uint8_t sdu_idx; uint8_t pdu_idx; uint16_t sdu_offset; - uint16_t rem_len; uint8_t pdu_len; sdu_idx = idx / mux->pdu_per_sdu; pdu_idx = idx - sdu_idx * mux->pdu_per_sdu; if (sdu_idx >= mux->sdu_in_event) { - *llid = 1; + *llid = 0; return 0; } @@ -206,7 +344,7 @@ ble_ll_isoal_mux_unframed_get(struct ble_ll_isoal_mux *mux, uint8_t idx, } if (!pkthdr) { - *llid = 1; + *llid = 0; return 0; } @@ -214,11 +352,21 @@ ble_ll_isoal_mux_unframed_get(struct ble_ll_isoal_mux *mux, uint8_t idx, sdu_offset = pdu_idx * mux->max_pdu; rem_len = OS_MBUF_PKTLEN(om) - sdu_offset; - if ((int32_t)rem_len <= 0) { + if (OS_MBUF_PKTLEN(om) == 0) { + /* LLID = 0b00: Zero-Length SDU (complete SDU) */ + *llid = 0; + pdu_len = 0; + } else if (rem_len <= 0) { + /* LLID = 0b01: ISO Data PDU used as padding */ *llid = 1; pdu_len = 0; } else { - *llid = (pdu_idx < mux->pdu_per_sdu - 1); + /* LLID = 0b00: Data remaining fits the ISO Data PDU size, + * it's end fragment of an SDU or complete SDU. + * LLID = 0b01: Data remaining exceeds the ISO Data PDU size, + * it's start or continuation fragment of an SDU. + */ + *llid = rem_len > mux->max_pdu; pdu_len = min(mux->max_pdu, rem_len); } @@ -227,180 +375,143 @@ ble_ll_isoal_mux_unframed_get(struct ble_ll_isoal_mux *mux, uint8_t idx, return pdu_len; } -static void -ble_ll_isoal_tx_pkt_in(struct ble_npl_event *ev) +static int +ble_ll_isoal_mux_framed_get(struct ble_ll_isoal_mux *mux, uint8_t idx, + uint8_t *llid, uint8_t *dptr) { - struct os_mbuf *om; + struct ble_mbuf_hdr *blehdr; struct os_mbuf_pkthdr *pkthdr; - struct ble_hci_iso *hci_iso; - struct ble_hci_iso_data *hci_iso_data; - struct ble_ll_isoal_mux *mux; - uint16_t data_hdr_len; - uint16_t handle; - uint16_t conn_handle; - uint16_t length; - uint16_t pb_flag; - uint16_t ts_flag; - uint32_t timestamp = 0; - os_sr_t sr; + struct os_mbuf *om; + uint32_t time_offset; + uint16_t seghdr; + uint16_t rem_len = 0; + uint16_t sdu_offset = 0; + uint8_t num_sdu; + uint8_t num_pdu; + uint8_t frag_len; + uint8_t pdu_offset = 0; + bool sc = mux->sc; + uint8_t hdr_len = 0; - while (STAILQ_FIRST(&ll_isoal_tx_q)) { - pkthdr = STAILQ_FIRST(&ll_isoal_tx_q); - om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + *llid = 0b10; - OS_ENTER_CRITICAL(sr); - STAILQ_REMOVE_HEAD(&ll_isoal_tx_q, omp_next); - OS_EXIT_CRITICAL(sr); - - hci_iso = (void *)om->om_data; + num_sdu = mux->sdu_in_event; + if (num_sdu == 0) { + return 0; + } - handle = le16toh(hci_iso->handle); - conn_handle = BLE_HCI_ISO_CONN_HANDLE(handle); - pb_flag = BLE_HCI_ISO_PB_FLAG(handle); - ts_flag = BLE_HCI_ISO_TS_FLAG(handle); - length = BLE_HCI_ISO_LENGTH(le16toh(hci_iso->length)); + num_pdu = idx; - data_hdr_len = 0; - if ((pb_flag == BLE_HCI_ISO_PB_FIRST) || - (pb_flag == BLE_HCI_ISO_PB_COMPLETE)) { - if (ts_flag) { - timestamp = get_le32(om->om_data + sizeof(*hci_iso)); - data_hdr_len += sizeof(uint32_t); - } + /* Skip the idx PDUs */ + pkthdr = STAILQ_FIRST(&mux->sdu_q); + while (pkthdr && num_sdu > 0 && num_pdu > 0) { + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); - hci_iso_data = (void *)(om->om_data + sizeof(*hci_iso) + data_hdr_len); - data_hdr_len += sizeof(*hci_iso_data); - } - os_mbuf_adj(om, sizeof(*hci_iso) + data_hdr_len); + rem_len = OS_MBUF_PKTLEN(om) - sdu_offset; + hdr_len = sc ? 2 /* Segmentation Header */ + : 5 /* Segmentation Header + TimeOffset */; - if (OS_MBUF_PKTLEN(om) != length - data_hdr_len) { - os_mbuf_free_chain(om); + if (mux->max_pdu <= hdr_len + pdu_offset) { + /* Advance to next PDU */ + pdu_offset = 0; + num_pdu--; continue; } - switch (BLE_LL_CONN_HANDLE_TYPE(conn_handle)) { - case BLE_LL_CONN_HANDLE_TYPE_BIS: - mux = ble_ll_iso_big_find_mux_by_handle(conn_handle); - ble_ll_isoal_mux_tx_pkt_in(mux, om, pb_flag, timestamp); - break; - default: - os_mbuf_free_chain(om); - break; + frag_len = min(rem_len, mux->max_pdu - hdr_len - pdu_offset); + + pdu_offset += hdr_len + frag_len; + + if (frag_len == rem_len) { + /* Process next SDU */ + sdu_offset = 0; + num_sdu--; + pkthdr = STAILQ_NEXT(pkthdr, omp_next); + + sc = 0; + } else { + sdu_offset += frag_len; + + sc = 1; } } -} -int -ble_ll_isoal_hci_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_setup_iso_data_path_cp *cmd = (const void *)cmdbuf; - struct ble_hci_le_setup_iso_data_path_rp *rsp = (void *)rspbuf; - struct ble_ll_iso_bis *bis; - uint16_t conn_handle; - - conn_handle = le16toh(cmd->conn_handle); - switch (BLE_LL_CONN_HANDLE_TYPE(conn_handle)) { - case BLE_LL_CONN_HANDLE_TYPE_BIS: - bis = ble_ll_iso_big_find_bis_by_handle(conn_handle); - if (bis) { + if (num_pdu > 0) { + return 0; + } + + BLE_LL_ASSERT(pdu_offset == 0); + + while (pkthdr && num_sdu > 0) { + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + + rem_len = OS_MBUF_PKTLEN(om) - sdu_offset; + hdr_len = sc ? 2 /* Segmentation Header */ + : 5 /* Segmentation Header + TimeOffset */; + + if (mux->max_pdu <= hdr_len + pdu_offset) { break; } - default: - return BLE_ERR_UNK_CONN_ID; - } - /* Only input for now since we only support BIS */ - if (cmd->data_path_dir) { - return BLE_ERR_CMD_DISALLOWED; - } + frag_len = min(rem_len, mux->max_pdu - hdr_len - pdu_offset); - /* We do not (yet) support any vendor-specific data path */ - if (cmd->data_path_id) { - return BLE_ERR_CMD_DISALLOWED; - } + /* Segmentation Header */ + seghdr = BLE_LL_ISOAL_SEGHDR(sc, frag_len == rem_len, frag_len + hdr_len - 2); + put_le16(dptr + pdu_offset, seghdr); + pdu_offset += 2; - rsp->conn_handle = cmd->conn_handle; - *rsplen = sizeof(*rsp); + /* Time Offset */ + if (hdr_len > 2) { + blehdr = BLE_MBUF_HDR_PTR(om); - return 0; -} + time_offset = mux->event_tx_timestamp - + blehdr->txiso.cpu_timestamp; + put_le24(dptr + pdu_offset, time_offset); + pdu_offset += 3; + } -int -ble_ll_isoal_hci_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_remove_iso_data_path_cp *cmd = (const void *)cmdbuf; - struct ble_hci_le_remove_iso_data_path_rp *rsp = (void *)rspbuf; + /* ISO Data Fragment */ + os_mbuf_copydata(om, sdu_offset, frag_len, dptr + pdu_offset); + pdu_offset += frag_len; - /* XXX accepts anything for now */ - rsp->conn_handle = cmd->conn_handle; - *rsplen = sizeof(*rsp); + if (frag_len == rem_len) { + /* Process next SDU */ + sdu_offset = 0; + num_sdu--; + pkthdr = STAILQ_NEXT(pkthdr, omp_next); - return 0; -} + sc = 0; + } else { + sdu_offset += frag_len; -int -ble_ll_isoal_hci_read_tx_sync(const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen) -{ - const struct ble_hci_le_read_iso_tx_sync_cp *cmd = (const void *)cmdbuf; - struct ble_hci_le_read_iso_tx_sync_rp *rsp = (void *)rspbuf; - struct ble_ll_isoal_mux *mux; - uint16_t handle; - - handle = le16toh(cmd->conn_handle); - switch (BLE_LL_CONN_HANDLE_TYPE(handle)) { - case BLE_LL_CONN_HANDLE_TYPE_BIS: - mux = ble_ll_iso_big_find_mux_by_handle(handle); - if (!mux) { - return BLE_ERR_UNK_CONN_ID; + sc = 1; } - break; - default: - return BLE_ERR_UNK_CONN_ID; } - rsp->conn_handle = cmd->conn_handle; - rsp->packet_seq_num = htole16(mux->last_tx_packet_seq_num); - rsp->tx_timestamp = htole32(mux->last_tx_timestamp); - put_le24(rsp->time_offset, 0); + return pdu_offset; +} - *rsplen = sizeof(*rsp); +int +ble_ll_isoal_mux_pdu_get(struct ble_ll_isoal_mux *mux, uint8_t idx, + uint8_t *llid, void *dptr) +{ + if (mux->framed) { + return ble_ll_isoal_mux_framed_get(mux, idx, llid, dptr); + } - return 0; + return ble_ll_isoal_mux_unframed_get(mux, idx, llid, dptr); } void ble_ll_isoal_init(void) { - STAILQ_INIT(&ll_isoal_tx_q); - ble_npl_event_init(&ll_isoal_tx_pkt_in, ble_ll_isoal_tx_pkt_in, NULL); } void ble_ll_isoal_reset(void) { - STAILQ_INIT(&ll_isoal_tx_q); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &ll_isoal_tx_pkt_in); -} - -int -ble_ll_isoal_data_in(struct os_mbuf *om) -{ - struct os_mbuf_pkthdr *hdr; - os_sr_t sr; - - hdr = OS_MBUF_PKTHDR(om); - - OS_ENTER_CRITICAL(sr); - STAILQ_INSERT_TAIL(&ll_isoal_tx_q, hdr, omp_next); - OS_EXIT_CRITICAL(sr); - - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ll_isoal_tx_pkt_in); - - return 0; } #endif /* BLE_LL_ISO */ + #endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_pdu.c b/src/nimble/nimble/controller/src/ble_ll_pdu.c index bd2541998..66b50ec60 100644 --- a/src/nimble/nimble/controller/src/ble_ll_pdu.c +++ b/src/nimble/nimble/controller/src/ble_ll_pdu.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,8 @@ * under the License. */ -#include -#include +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" static const uint16_t syncword_len[] = { [BLE_PHY_MODE_1M] = (BLE_LL_PDU_PREAMBLE_1M_LEN + BLE_LL_PDU_AA_LEN) * 8, @@ -56,3 +58,5 @@ ble_ll_pdu_us(uint8_t payload_len, uint8_t phy_mode) { return payload0_len[phy_mode] + (payload_len * us_per_octet[phy_mode]); } + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_priv.h b/src/nimble/nimble/controller/src/ble_ll_priv.h index 8152ccab1..f0498fea8 100644 --- a/src/nimble/nimble/controller/src/ble_ll_priv.h +++ b/src/nimble/nimble/controller/src/ble_ll_priv.h @@ -57,7 +57,7 @@ int ble_ll_is_busy(unsigned int flags); #ifdef MYNEWT #include "syscfg/syscfg.h" -#include "nimble/porting/nimble/include/hal/hal_gpio.h" +#include "hal/hal_gpio.h" #define BLE_LL_DEBUG_GPIO_INIT(_name) \ if (MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name) >= 0) { \ diff --git a/src/nimble/nimble/controller/src/ble_ll_rand.c b/src/nimble/nimble/controller/src/ble_ll_rand.c index bc3bb42f4..48152fd3c 100644 --- a/src/nimble/nimble/controller/src/ble_ll_rand.c +++ b/src/nimble/nimble/controller/src/ble_ll_rand.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM /* for jrand48 */ #define _XOPEN_SOURCE @@ -218,4 +219,4 @@ ble_ll_rand_init(void) return 0; } -#endif +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_resolv.c b/src/nimble/nimble/controller/src/ble_ll_resolv.c index c0e60409d..9b71efeb4 100644 --- a/src/nimble/nimble/controller/src/ble_ll_resolv.c +++ b/src/nimble/nimble/controller/src/ble_ll_resolv.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,8 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include @@ -50,6 +50,16 @@ struct ble_ll_resolv_data g_ble_ll_resolv_data; __attribute__((aligned(4))) struct ble_ll_resolv_entry g_ble_ll_resolv_list[MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)]; +#if MYNEWT_VAL(BLE_LL_HCI_VS_LOCAL_IRK) +struct local_irk_data { + uint8_t is_set; + uint8_t irk[16]; + uint8_t rpa[6]; +}; +/* 0 is for public, 1 is for static address */ +static struct local_irk_data g_local_irk[2]; +#endif + /** * Called to determine if a change is allowed to the resolving list at this * time. We are not allowed to modify the resolving list if address translation @@ -72,6 +82,30 @@ ble_ll_resolv_list_chg_allowed(void) return rc; } +static void +generate_rpa(const uint8_t *irk, uint8_t *rpa) +{ + uint8_t *prand; + struct ble_encryption_block ecb; + + /* Get prand */ + prand = rpa + 3; + ble_ll_rand_prand_get(prand); + + /* Calculate hash, hash = ah(local IRK, prand) */ + memcpy(ecb.key, irk, 16); + memset(ecb.plain_text, 0, 13); + ecb.plain_text[13] = prand[2]; + ecb.plain_text[14] = prand[1]; + ecb.plain_text[15] = prand[0]; + + /* Calculate hash */ + ble_hw_encrypt_block(&ecb); + + rpa[0] = ecb.cipher_text[15]; + rpa[1] = ecb.cipher_text[14]; + rpa[2] = ecb.cipher_text[13]; +} /** * Called to generate a resolvable private address in rl structure @@ -83,8 +117,6 @@ static void ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local) { uint8_t *irk; - uint8_t *prand; - struct ble_encryption_block ecb; uint8_t *addr; BLE_LL_ASSERT(rl != NULL); @@ -97,23 +129,7 @@ ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local) irk = rl->rl_peer_irk; } - /* Get prand */ - prand = addr + 3; - ble_ll_rand_prand_get(prand); - - /* Calculate hash, hash = ah(local IRK, prand) */ - memcpy(ecb.key, irk, 16); - memset(ecb.plain_text, 0, 13); - ecb.plain_text[13] = prand[2]; - ecb.plain_text[14] = prand[1]; - ecb.plain_text[15] = prand[0]; - - /* Calculate hash */ - ble_hw_encrypt_block(&ecb); - - addr[0] = ecb.cipher_text[15]; - addr[1] = ecb.cipher_text[14]; - addr[2] = ecb.cipher_text[13]; + generate_rpa(irk, addr); } /** @@ -126,6 +142,10 @@ ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev) int i; os_sr_t sr; struct ble_ll_resolv_entry *rl; +#if MYNEWT_VAL(BLE_LL_HCI_VS_LOCAL_IRK) + struct local_irk_data *irk_data; + uint8_t rpa[6]; +#endif rl = &g_ble_ll_resolv_list[0]; for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) { @@ -143,6 +163,18 @@ ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev) ++rl; } +#if MYNEWT_VAL(BLE_LL_HCI_VS_LOCAL_IRK) + for (i = 0; i < ARRAY_SIZE(g_local_irk); i++) { + irk_data = &g_local_irk[i]; + if (irk_data->is_set) { + generate_rpa(irk_data->irk, rpa); + OS_ENTER_CRITICAL(sr); + memcpy(irk_data->rpa, rpa, 6); + OS_EXIT_CRITICAL(sr); + } + } +#endif + ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, g_ble_ll_resolv_data.rpa_tmo); @@ -639,6 +671,58 @@ ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, int local) return 0; } +#if MYNEWT_VAL(BLE_LL_HCI_VS_LOCAL_IRK) +int +ble_ll_resolv_local_irk_set(uint8_t own_addr_type, const uint8_t *irk) +{ + struct local_irk_data *irk_data; + int i; + + if (own_addr_type >= 2) { + return -1; + } + + irk_data = &g_local_irk[own_addr_type]; + + memcpy(irk_data->irk, irk, 16); + + irk_data->is_set = 0; + + for (i = 0; i < 16; i++) { + if (irk[i]) { + irk_data->is_set = 1; + break; + } + } + + if (irk_data->is_set) { + generate_rpa(irk_data->irk, irk_data->rpa); + } + + return 0; +} + +int +ble_ll_resolv_local_rpa_get(uint8_t own_addr_type, uint8_t *rpa) +{ + struct local_irk_data *irk_data; + + if (own_addr_type >= 2) { + return -1; + } + + irk_data = &g_local_irk[own_addr_type]; + + if (!irk_data->is_set) { + return -1; + } + + memcpy(rpa, irk_data->rpa, 6); + + return 0; +} +#endif + /** * Resolve a Resolvable Private Address * @@ -740,7 +824,13 @@ ble_ll_resolv_init(void) &g_ble_ll_data.ll_evq, ble_ll_resolv_rpa_timer_cb, NULL); + +#if MYNEWT_VAL(BLE_LL_HCI_VS_LOCAL_IRK) + memset(&g_local_irk, 0, sizeof(g_local_irk)); +#endif } #endif /* if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) */ -#endif + + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c b/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c index d71f1e800..f3fca8ef5 100644 --- a/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c +++ b/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM #include #include @@ -349,4 +350,5 @@ ble_ll_rfmgmt_init(void) } #endif -#endif + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_scan.c b/src/nimble/nimble/controller/src/ble_ll_scan.c index e41cda13c..d74cf672e 100644 --- a/src/nimble/nimble/controller/src/ble_ll_scan.c +++ b/src/nimble/nimble/controller/src/ble_ll_scan.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include @@ -177,7 +177,7 @@ ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success) BLE_LL_ASSERT(scansm->backoff_count <= 256); } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +#if MYNEWT_VAL(BLE_LL_SCAN_ACTIVE_SCAN_NRPA) static void ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm) { @@ -193,17 +193,13 @@ ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm) scansm->scan_nrpa_timer = now + ble_ll_resolv_get_rpa_tmo(); } } +#endif -uint8_t * -ble_ll_get_scan_nrpa(void) +struct ble_ll_scan_sm * +ble_ll_scan_sm_get(void) { - struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm; - - ble_ll_scan_refresh_nrpa(scansm); - - return scansm->scan_nrpa; + return &g_ble_ll_scan_sm; } -#endif uint8_t ble_ll_scan_get_own_addr_type(void) @@ -243,30 +239,26 @@ ble_ll_scan_backoff_update(int success) ble_ll_scan_req_backoff(scansm, success); } -static void -ble_ll_scan_req_pdu_prepare(struct ble_ll_scan_sm *scansm, - const uint8_t *adv_addr, uint8_t adv_addr_type, - int8_t rpa_index) +void +ble_ll_scan_make_req_pdu(struct ble_ll_scan_sm *scansm, uint8_t *pdu, + uint8_t *hdr_byte, uint8_t adva_type, + const uint8_t *adva, int rpa_index) { - uint8_t hdr_byte; - struct ble_ll_scan_pdu_data *pdu_data; uint8_t *scana; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) struct ble_ll_resolv_entry *rl; uint8_t rpa[BLE_DEV_ADDR_LEN]; #endif - pdu_data = &scansm->pdu_data; - /* Construct first PDU header byte */ - hdr_byte = BLE_ADV_PDU_TYPE_SCAN_REQ; - if (adv_addr_type) { - hdr_byte |= BLE_ADV_PDU_HDR_RXADD_RAND; + *hdr_byte = BLE_ADV_PDU_TYPE_SCAN_REQ; + if (adva_type) { + *hdr_byte |= BLE_ADV_PDU_HDR_RXADD_RAND; } /* Determine ScanA */ if (scansm->own_addr_type & 0x01) { - hdr_byte |= BLE_ADV_PDU_HDR_TXADD_RAND; + *hdr_byte |= BLE_ADV_PDU_HDR_TXADD_RAND; scana = g_random_addr; } else { scana = g_dev_addr; @@ -280,28 +272,42 @@ ble_ll_scan_req_pdu_prepare(struct ble_ll_scan_sm *scansm, rl = NULL; } - /* - * If device is on RL and we have local IRK, we use RPA generated using - * that IRK as ScanA. Otherwise we use NRPA as ScanA to prevent our - * device from being tracked when doing an active scan (Core 5.1, Vol 6, - * Part B, section 6.3) - */ + /* Check if we should use RPA/NRPA instead of public/random address: + * - use RPA if device is on RL and has local IRK set + * - use RPA generated from local IRK if set + * - use NRPA if allowed by configuration + * */ + if (rl && rl->rl_has_local) { ble_ll_resolv_get_priv_addr(rl, 1, rpa); scana = rpa; } else { - ble_ll_scan_refresh_nrpa(scansm); - scana = scansm->scan_nrpa; + if (ble_ll_resolv_local_rpa_get(scansm->own_addr_type & 0x01, rpa) == 0) { + scana = rpa; + } else { +#if MYNEWT_VAL(BLE_LL_SCAN_ACTIVE_SCAN_NRPA) + ble_ll_scan_refresh_nrpa(scansm); + scana = scansm->scan_nrpa; +#endif + } } - hdr_byte |= BLE_ADV_PDU_HDR_TXADD_RAND; + *hdr_byte |= BLE_ADV_PDU_HDR_TXADD_RAND; } #endif - /* Save scan request data */ - pdu_data->hdr_byte = hdr_byte; - memcpy(pdu_data->scana, scana, BLE_DEV_ADDR_LEN); - memcpy(pdu_data->adva, adv_addr, BLE_DEV_ADDR_LEN); + memcpy(pdu, scana, BLE_DEV_ADDR_LEN); + memcpy(pdu + 6, adva, BLE_DEV_ADDR_LEN); +} + +static void +ble_ll_scan_req_pdu_prepare(struct ble_ll_scan_sm *scansm, + const uint8_t *adv_addr, uint8_t adv_addr_type, + int8_t rpa_index) +{ + ble_ll_scan_make_req_pdu(scansm, scansm->pdu_data.scana, + &scansm->pdu_data.hdr_byte, adv_addr_type, adv_addr, + rpa_index); } static uint8_t @@ -751,7 +757,7 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm) int rc; struct ble_ll_scan_phy *scanp = scansm->scanp; uint8_t chan; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) uint8_t phy_mode; int phy; #endif @@ -781,7 +787,7 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm) } #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) phy = scanp->phy; phy_mode = ble_ll_phy_to_phy_mode(phy, BLE_HCI_LE_PHY_CODED_ANY); ble_phy_mode_set(phy_mode, phy_mode); @@ -1612,14 +1618,27 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) goto scan_rx_isr_ignore; } + if (!scansm->scan_enabled) { + STATS_INC(ble_ll_stats, rx_pdu_on_scan_disabled); + goto scan_rx_isr_ignore; + } + rxbuf = rxpdu->om_data; pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK; switch (pdu_type) { case BLE_ADV_PDU_TYPE_ADV_IND: case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND: + rc = ble_ll_scan_rx_isr_end_on_adv(pdu_type, rxbuf, hdr, &addrd); + break; case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND: case BLE_ADV_PDU_TYPE_ADV_SCAN_IND: +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + if (scansm->scanp->scan_type == BLE_SCAN_TYPE_INITIATE) { + rc = -1; + break; + } +#endif rc = ble_ll_scan_rx_isr_end_on_adv(pdu_type, rxbuf, hdr, &addrd); break; case BLE_ADV_PDU_TYPE_SCAN_RSP: @@ -1989,8 +2008,10 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om, void ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hdr) { +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_HCI_VS_SET_SCAN_CFG) + struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo; +#endif #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) - struct ble_mbuf_hdr_rxinfo *rxinfo; uint8_t *targeta; #endif struct ble_ll_scan_sm *scansm; @@ -2012,6 +2033,26 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd return; } +#if MYNEWT_VAL(BLE_LL_HCI_VS_SET_SCAN_CFG) + if ((scansm->vs_config.ignore_ext) && + (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND)) { + ble_ll_scan_chk_resume(); + return; + } + + if ((scansm->vs_config.ignore_legacy) && + (ptype != BLE_ADV_PDU_TYPE_ADV_EXT_IND)) { + ble_ll_scan_chk_resume(); + return; + } + + if ((scansm->vs_config.rssi_filter) && + (rxinfo->rssi < scansm->vs_config.rssi_threshold)) { + ble_ll_scan_chk_resume(); + return; + } +#endif + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (ptype == BLE_ADV_PDU_TYPE_ADV_EXT_IND) { ble_ll_scan_aux_pkt_in_on_ext(om, hdr); @@ -2023,7 +2064,6 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, struct os_mbuf *om, struct ble_mbuf_hdr *hd switch (scansm->scanp->scan_type) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_SCAN_TYPE_INITIATE: - rxinfo = &hdr->rxinfo; if (rxinfo->flags & BLE_MBUF_HDR_F_CONNECT_IND_TXD) { /* We need to keep original TargetA in case it was resolved, so rl * can be updated properly. @@ -2124,9 +2164,9 @@ ble_ll_scan_check_phy_params(uint8_t type, uint16_t itvl, uint16_t window) /* Check interval and window */ if ((itvl < BLE_HCI_SCAN_ITVL_MIN) || - // (itvl > BLE_HCI_SCAN_ITVL_MAX_EXT) || + (itvl > BLE_HCI_SCAN_ITVL_MAX_EXT) || (window < BLE_HCI_SCAN_WINDOW_MIN) || - // (window > BLE_HCI_SCAN_WINDOW_MAX_EXT) || + (window > BLE_HCI_SCAN_WINDOW_MAX_EXT) || (itvl < window)) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -2170,11 +2210,13 @@ ble_ll_scan_hci_set_ext_params(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } - /* Check if no reserved bits in PHYS are set and that at least one valid PHY - * is set. - */ - if (!(cmd->phys & SCAN_VALID_PHY_MASK) || - (cmd->phys & ~SCAN_VALID_PHY_MASK)) { + /* Check if valid phy is specified */ + if (cmd->phys & ~SCAN_VALID_PHY_MASK) { + return BLE_ERR_UNSUPPORTED; + } + + /* Check if at least one valid phy is specified */ + if (!(cmd->phys & SCAN_VALID_PHY_MASK)) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -2247,6 +2289,27 @@ ble_ll_scan_hci_set_ext_params(const uint8_t *cmdbuf, uint8_t len) #endif +#if MYNEWT_VAL(BLE_LL_HCI_VS_SET_SCAN_CFG) +int +ble_ll_scan_set_vs_config(uint32_t flags, int8_t rssi_threshold) +{ + struct ble_ll_scan_sm *scansm; + + scansm = &g_ble_ll_scan_sm; + + if (scansm->scan_enabled || scansm->connsm) { + return 1; + } + + scansm->vs_config.ignore_legacy = !!(flags & BLE_HCI_VS_SET_SCAN_CFG_FLAG_NO_LEGACY); + scansm->vs_config.ignore_ext = !!(flags & BLE_HCI_VS_SET_SCAN_CFG_FLAG_NO_EXT); + scansm->vs_config.rssi_filter = !!(flags & BLE_HCI_VS_SET_SCAN_CFG_FLAG_RSSI_FILTER); + scansm->vs_config.rssi_threshold = rssi_threshold; + + return 0; +} +#endif + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static void ble_ll_scan_duration_period_timers_restart(struct ble_ll_scan_sm *scansm) @@ -2694,7 +2757,7 @@ ble_ll_scan_common_init(void) scansm->scan_phys[PHY_CODED].phy = BLE_PHY_CODED; #endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +#if MYNEWT_VAL(BLE_LL_SCAN_ACTIVE_SCAN_NRPA) /* Make sure we'll generate new NRPA if necessary */ scansm->scan_nrpa_timer = ble_npl_time_get(); #endif @@ -2778,4 +2841,5 @@ ble_ll_scan_init(void) } #endif -#endif \ No newline at end of file + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_scan_aux.c b/src/nimble/nimble/controller/src/ble_ll_scan_aux.c index 135db7ccd..729dac08a 100644 --- a/src/nimble/nimble/controller/src/ble_ll_scan_aux.c +++ b/src/nimble/nimble/controller/src/ble_ll_scan_aux.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#ifndef ESP_PLATFORM - #include #if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) @@ -86,6 +86,9 @@ struct ble_ll_scan_aux_data { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) int8_t rpa_index; #endif +#if MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) + uint8_t pri_phy_mode; +#endif }; #define AUX_MEMPOOL_SIZE (OS_MEMPOOL_SIZE( \ @@ -113,7 +116,7 @@ static int ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch) { struct ble_ll_scan_aux_data *aux = sch->cb_arg; -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) uint8_t phy_mode; #endif uint8_t lls; @@ -139,7 +142,7 @@ ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch) } #endif -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) phy_mode = ble_ll_phy_to_phy_mode(aux->sec_phy, BLE_HCI_LE_PHY_CODED_ANY); ble_phy_mode_set(phy_mode, phy_mode); #endif @@ -218,7 +221,8 @@ ble_ll_scan_aux_need_truncation(struct ble_ll_scan_aux_data *aux) } static struct ble_hci_ev * -ble_ll_hci_ev_alloc_ext_adv_report_for_aux(struct ble_ll_scan_addr_data *addrd, +ble_ll_hci_ev_alloc_ext_adv_report_for_aux(struct ble_mbuf_hdr_rxinfo *rxinfo, + struct ble_ll_scan_addr_data *addrd, struct ble_ll_scan_aux_data *aux) { struct ble_hci_ev_le_subev_ext_adv_rpt *hci_subev; @@ -259,6 +263,16 @@ ble_ll_hci_ev_alloc_ext_adv_report_for_aux(struct ble_ll_scan_addr_data *addrd, report->tx_power = 0x7f; report->rssi = 0x7f; report->periodic_itvl = 0; + +#if MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) + if (aux->pri_phy_mode == BLE_PHY_MODE_CODED_500KBPS) { + report->pri_phy = 0x04; + } + if (rxinfo->phy_mode == BLE_PHY_MODE_CODED_500KBPS) { + report->sec_phy = 0x04; + } +#endif + if (addrd->targeta) { report->evt_type |= BLE_HCI_ADV_DIRECT_MASK; report->dir_addr_type = addrd->targeta_type; @@ -328,6 +342,12 @@ ble_ll_hci_ev_update_ext_adv_report_from_aux(struct ble_hci_ev *hci_ev, } report->sec_phy = rxhdr->rxinfo.phy; +#if MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) + if (rxhdr->rxinfo.phy_mode == BLE_PHY_MODE_CODED_500KBPS) { + report->sec_phy = 0x04; + } +#endif + /* Strip PDU header and ext header, leave only AD */ os_mbuf_adj(rxpdu, 3 + eh_len); @@ -390,7 +410,6 @@ ble_ll_hci_ev_update_ext_adv_report_from_ext(struct ble_hci_ev *hci_ev, #endif uint8_t pdu_hdr; uint8_t adv_mode; - uint8_t eh_len; uint8_t eh_flags; uint8_t *eh_data; uint8_t *rxbuf; @@ -399,7 +418,6 @@ ble_ll_hci_ev_update_ext_adv_report_from_ext(struct ble_hci_ev *hci_ev, pdu_hdr = rxbuf[0]; adv_mode = rxbuf[2] >> 6; - eh_len = rxbuf[2] & 0x3f; eh_flags = rxbuf[3]; eh_data = &rxbuf[4]; @@ -423,11 +441,17 @@ ble_ll_hci_ev_update_ext_adv_report_from_ext(struct ble_hci_ev *hci_ev, report->periodic_itvl = 0; report->data_len = 0; +#if MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) + if (rxinfo->phy_mode == BLE_PHY_MODE_CODED_500KBPS) { + report->pri_phy = 0x04; + } +#endif + /* Now parse extended header... */ if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (rxinfo->rpa_index >= 0) { + if (rxinfo->flags & BLE_MBUF_HDR_F_RESOLVED) { rl = &g_ble_ll_resolv_list[rxinfo->rpa_index]; report->addr_type = rl->rl_addr_type + 2; memcpy(report->addr, rl->rl_identity_addr, 6); @@ -486,8 +510,10 @@ ble_ll_hci_ev_update_ext_adv_report_from_ext(struct ble_hci_ev *hci_ev, report->tx_power = 0x7f; } - /* Strip PDU header and ext header, leave only AD */ - os_mbuf_adj(rxpdu, 3 + eh_len); + /* AdvData in ADV_EXT_IND is RFU so we should ignore it, i.e. we can just + * remove any data left in mbuf + */ + os_mbuf_adj(rxpdu, os_mbuf_len(rxpdu)); } @@ -611,7 +637,7 @@ ble_ll_hci_ev_send_ext_adv_report_for_aux(struct os_mbuf *rxpdu, hci_ev = aux->hci_ev; aux->hci_ev = NULL; } else { - hci_ev = ble_ll_hci_ev_alloc_ext_adv_report_for_aux(addrd, aux); + hci_ev = ble_ll_hci_ev_alloc_ext_adv_report_for_aux(&rxhdr->rxinfo, addrd, aux); if (!hci_ev) { aux->hci_state = BLE_LL_SCAN_AUX_H_DONE; return -1; @@ -853,9 +879,10 @@ ble_ll_scan_aux_parse_to_aux_data(struct ble_ll_scan_aux_data *aux, /* Now parse extended header... */ - /* AdvA is only valid in 1st PDU, ignore in AUX_CHAIN_IND */ + /* AdvA is only valid in AUX_ADV_IND if not already present in ADV_EXT_IND */ if (eh_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { - if (!(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN)) { + if (!(aux->flags & BLE_LL_SCAN_AUX_F_HAS_ADVA) && + !(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN)) { memcpy(aux->adva, eh_data, 6); aux->adva_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_TXADD_MASK); aux->flags |= BLE_LL_SCAN_AUX_F_HAS_ADVA; @@ -866,9 +893,10 @@ ble_ll_scan_aux_parse_to_aux_data(struct ble_ll_scan_aux_data *aux, eh_data += BLE_LL_EXT_ADV_ADVA_SIZE; } - /* TargetA is only valid in 1st PDU, ignore in AUX_CHAIN_IND */ + /* TargetA is only valid in AUX_ADV_IND if not already present in ADV_EXT_IND */ if (eh_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { - if (!(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN)) { + if (!(aux->flags & BLE_LL_SCAN_AUX_F_HAS_TARGETA) && + !(aux->flags & BLE_LL_SCAN_AUX_F_AUX_CHAIN)) { memcpy(aux->targeta, eh_data, 6); aux->targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK); aux->flags |= BLE_LL_SCAN_AUX_F_HAS_TARGETA; @@ -903,7 +931,8 @@ ble_ll_scan_aux_parse_to_aux_data(struct ble_ll_scan_aux_data *aux, } } - if (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + /* AuxPtr is RFU if AdvMode!=0 so ignore in such case */ + if ((adv_mode == 0) && (eh_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { aux->aux_ptr = get_le24(eh_data); rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_AUX_PTR_WAIT; } @@ -1076,6 +1105,10 @@ ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm, aux->pri_phy = rxinfo->phy; aux->aux_ptr = aux_ptr; +#if MYNEWT_VAL(BLE_LL_ADV_CODING_SELECTION) + aux->pri_phy_mode = rxinfo->phy_mode; +#endif + if (addrd.adva) { memcpy(aux->adva, addrd.adva, 6); aux->adva_type = addrd.adva_type; @@ -1146,56 +1179,9 @@ static uint8_t ble_ll_scan_aux_scan_req_tx_pdu_cb(uint8_t *dptr, void *arg, uint8_t *hdr_byte) { struct ble_ll_scan_aux_data *aux = arg; - uint8_t *scana; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - struct ble_ll_resolv_entry *rl; - uint8_t rpa[BLE_DEV_ADDR_LEN]; -#endif - uint8_t hb; - - hb = BLE_ADV_PDU_TYPE_SCAN_REQ; - - /* ScanA */ - if (ble_ll_scan_get_own_addr_type() & 0x01) { - hb |= BLE_ADV_PDU_HDR_TXADD_RAND; - scana = g_random_addr; - } else { - scana = g_dev_addr; - } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (ble_ll_scan_get_own_addr_type() & 0x02) { - if (aux->rpa_index >=0) { - rl = &g_ble_ll_resolv_list[aux->rpa_index]; - } else { - rl = NULL; - } - - /* - * If device is on RL and we have local IRK, we use RPA generated using - * that IRK as ScanA. Otherwise we use NRPA as ScanA to prevent our - * device from being tracked when doing an active scan - * ref: Core 5.2, Vol 6, Part B, section 6.3) - */ - if (rl && rl->rl_has_local) { - ble_ll_resolv_get_priv_addr(rl, 1, rpa); - scana = rpa; - } else { - scana = ble_ll_get_scan_nrpa(); - } - - hb |= BLE_ADV_PDU_HDR_TXADD_RAND; - } -#endif - memcpy(dptr, scana, BLE_DEV_ADDR_LEN); - - /* AdvA */ - if (aux->adva_type) { - hb |= BLE_ADV_PDU_HDR_RXADD_RAND; - } - memcpy(dptr + BLE_DEV_ADDR_LEN, aux->adva, BLE_DEV_ADDR_LEN); - - *hdr_byte = hb; + ble_ll_scan_make_req_pdu(ble_ll_scan_sm_get(), dptr, hdr_byte, + aux->adva_type, aux->adva, aux->rpa_index); return BLE_DEV_ADDR_LEN * 2; } @@ -1461,8 +1447,8 @@ ble_ll_scan_aux_sync_check(struct os_mbuf *rxpdu, eh_data = &rxbuf[4]; /* Need ADI and SyncInfo */ - if (!(eh_flags & ((1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT) | - (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)))) { + if (!(eh_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) || + !(eh_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT))) { return; } @@ -1798,4 +1784,5 @@ ble_ll_scan_aux_init(void) } #endif /* BLE_LL_CFG_FEAT_LL_EXT_ADV */ -#endif /* ESP_PLATFORM */ \ No newline at end of file + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_sched.c b/src/nimble/nimble/controller/src/ble_ll_sched.c index ac795aa0c..73ca0d14b 100644 --- a/src/nimble/nimble/controller/src/ble_ll_sched.c +++ b/src/nimble/nimble/controller/src/ble_ll_sched.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,8 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include @@ -116,6 +116,16 @@ preempt_any_except_conn(struct ble_ll_sched_item *sch, return ble_ll_conn_is_lru(sch->cb_arg, item->cb_arg); } +static int +preempt_any_except_big(struct ble_ll_sched_item *sch, struct ble_ll_sched_item *item) +{ + if (item->sched_type == BLE_LL_SCHED_TYPE_BIG) { + return 0; + } + + return 1; +} + static inline int ble_ll_sched_check_overlap(struct ble_ll_sched_item *sch1, struct ble_ll_sched_item *sch2) @@ -153,27 +163,27 @@ ble_ll_sched_preempt(struct ble_ll_sched_item *sch, break; #endif #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) - case BLE_LL_SCHED_TYPE_ADV: - ble_ll_adv_event_rmvd_from_sched(entry->cb_arg); - break; + case BLE_LL_SCHED_TYPE_ADV: + ble_ll_adv_preempted(entry->cb_arg); + break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_LL_SCHED_TYPE_SCAN_AUX: ble_ll_scan_aux_break(entry->cb_arg); break; +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) case BLE_LL_SCHED_TYPE_PERIODIC: ble_ll_adv_periodic_rmvd_from_sched(entry->cb_arg); break; #endif -#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) case BLE_LL_SCHED_TYPE_SYNC: ble_ll_sync_rmvd_from_sched(entry->cb_arg); break; #endif #endif -#endif #if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) case BLE_LL_SCHED_TYPE_BIG: /* FIXME sometimes it may be useful to preempt... */ @@ -430,7 +440,7 @@ ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm, uint32_t orig_start_time; uint32_t earliest_start = 0; uint32_t min_win_offset; - uint32_t max_delay; + uint32_t max_delay = 0; uint32_t adv_rxend; bool calc_sch = true; os_sr_t sr; @@ -538,7 +548,6 @@ ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm, } else { connsm->css_period_idx = css->period_anchor_idx; } - max_delay = 0; } /* Calculate anchor point and move to next period if scheduled too @@ -749,7 +758,7 @@ ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, bool first_event) rc = ble_ll_sched_insert(sch, BLE_LL_SCHED_MAX_DELAY_ANY, preempt_none); } else { - rc = ble_ll_sched_insert(sch, 0, preempt_any); + rc = ble_ll_sched_insert(sch, 0, preempt_any_except_big); } OS_EXIT_CRITICAL(sr); @@ -846,14 +855,14 @@ ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch) #if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) int -ble_ll_sched_iso_big(struct ble_ll_sched_item *sch, int first) +ble_ll_sched_iso_big(struct ble_ll_sched_item *sch, int first, int fixed) { os_sr_t sr; int rc; OS_ENTER_CRITICAL(sr); - if (first) { + if (first && !fixed) { rc = ble_ll_sched_insert(sch, BLE_LL_SCHED_MAX_DELAY_ANY, preempt_none); } else { /* XXX provide better strategy for preemption */ @@ -923,10 +932,13 @@ ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb) OS_ENTER_CRITICAL(sr); first = TAILQ_FIRST(&g_ble_ll_sched_q); - if (first->sched_type == type) { - first_removed = 1; + if (!first) { + OS_EXIT_CRITICAL(sr); + return; } + first_removed = first->sched_type == type; + TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) { if (entry->sched_type != type) { continue; @@ -1285,4 +1297,5 @@ ble_ll_sched_css_get_conn_interval_us(void) #endif #endif -#endif + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_sync.c b/src/nimble/nimble/controller/src/ble_ll_sync.c index 7c7c9cafe..92ec54053 100644 --- a/src/nimble/nimble/controller/src/ble_ll_sync.c +++ b/src/nimble/nimble/controller/src/ble_ll_sync.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM #include #include @@ -65,6 +66,7 @@ #define BLE_LL_SYNC_SM_FLAG_HCI_TRUNCATED 0x0100 #define BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP 0x0200 #define BLE_LL_SYNC_SM_FLAG_CHAIN 0x0400 +#define BLE_LL_SYNC_SM_FLAG_DUPLICATES 0x0800 #define BLE_LL_SYNC_ITVL_USECS 1250 @@ -122,6 +124,10 @@ struct ble_ll_sync_sm { uint16_t event_cntr_last_received; uint8_t adv_addr_rpa[6]; #endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + uint16_t prev_adi; +#endif }; static struct ble_ll_sync_sm g_ble_ll_sync_sm[BLE_LL_SYNC_CNT]; @@ -229,7 +235,7 @@ ble_ll_sync_sm_clear(struct ble_ll_sync_sm *sm) static uint8_t ble_ll_sync_phy_mode_to_hci(int8_t phy_mode) { -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) switch (phy_mode) { case BLE_PHY_MODE_1M: return BLE_HCI_LE_PHY_1M; @@ -476,7 +482,7 @@ ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch) ble_phy_encrypt_disable(); #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) ble_phy_mode_set(sm->phy_mode, sm->phy_mode); #endif @@ -549,7 +555,7 @@ 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, - uint8_t **acad, uint8_t *acad_len) + uint8_t **acad, uint8_t *acad_len, uint16_t **adi) { uint8_t *rxbuf = om->om_data; uint8_t ext_hdr_flags; @@ -588,8 +594,10 @@ ble_ll_sync_parse_ext_hdr(struct os_mbuf *om, uint8_t **aux, int8_t *tx_power, i += BLE_LL_EXT_ADV_CTE_INFO_SIZE; } - /* there should be no ADI in Sync or chain, skip it */ if (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) { + *adi = (uint16_t *) ext_hdr + i; + } i += BLE_LL_EXT_ADV_DATA_INFO_SIZE; } @@ -1137,11 +1145,13 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) int8_t tx_power = 127; /* defaults to not available */ uint8_t *aux = NULL; uint8_t *acad = NULL; - uint8_t acad_len; + uint8_t acad_len = 0; + uint16_t *adi = NULL; const uint8_t *biginfo = NULL; uint8_t biginfo_len = 0; int datalen; bool reports_enabled; + bool is_duplicate = false; BLE_LL_ASSERT(sm); @@ -1187,14 +1197,22 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) } /* get ext header data */ - datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power, &acad, &acad_len); + datalen = ble_ll_sync_parse_ext_hdr(rxpdu, &aux, &tx_power, &acad, &acad_len, &adi); if (datalen < 0) { /* we got bad packet, end event */ goto end_event; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + if (adi != NULL) { + is_duplicate = (sm->flags & BLE_LL_SYNC_SM_FLAG_DUPLICATES) && (*adi == sm->prev_adi); + sm->prev_adi = *adi; + } +#endif + reports_enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT) && - !(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED); + !(sm->flags & BLE_LL_SYNC_SM_FLAG_DISABLED) && + !is_duplicate; /* no need to schedule for chain if reporting is disabled */ if (reports_enabled) { @@ -1540,6 +1558,12 @@ ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd, } #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT) + if (g_ble_ll_sync_create_params.options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DUPLICATES) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_DUPLICATES; + } +#endif + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_RESERVED; sm->flags |= BLE_LL_SYNC_SM_FLAG_ESTABLISHING; sm->flags |= BLE_LL_SYNC_SM_FLAG_SYNC_INFO; @@ -1584,7 +1608,8 @@ ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } if (!(cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED) && - (cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DUPLICATES)) { + (cmd->options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DUPLICATES) && + !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)) { /* We do not support ADI in periodic advertising thus cannot enable * duplicate filtering. */ @@ -1871,7 +1896,8 @@ ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len) if (MYNEWT_VAL(BLE_VERSION) >= 53) { if (cmd->enable > 0x03) { return BLE_ERR_INV_HCI_CMD_PARMS; - } else if (cmd->enable == 0x03) { + } else if ((cmd->enable == 0x03) && + !MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_ADI_SUPPORT)) { /* We do not support ADI in periodic advertising thus cannot enable * duplicate filtering. */ @@ -1899,8 +1925,14 @@ ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_UNK_ADV_INDENT; } - if (cmd->enable) { + if (cmd->enable & 0x1) { sm->flags &= ~BLE_LL_SYNC_SM_FLAG_DISABLED; + + if (cmd->enable & 0x2) { + sm->flags |= BLE_LL_SYNC_SM_FLAG_DUPLICATES; + } else { + sm->flags &= ~BLE_LL_SYNC_SM_FLAG_DUPLICATES; + } } else { sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED; } @@ -1941,7 +1973,7 @@ ble_ll_sync_transfer_get(const uint8_t *addr, uint8_t addr_type, uint8_t sid) void ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, - const uint8_t *sync_ind, bool reports_disabled, + const uint8_t *sync_ind, uint8_t mode, uint16_t max_skip, uint32_t sync_timeout) { const uint8_t *syncinfo = sync_ind + 2; @@ -1967,6 +1999,10 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, uint8_t sca; os_sr_t sr; + if (!mode) { + return; + } + phy_mode = ble_ll_ctrl_phy_from_phy_mask(sync_ind[25]); itvl = get_le16(syncinfo + 2); /* ignore if sync params are not valid */ @@ -2095,8 +2131,8 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, /* get anchor for specified conn event */ conn_event_count = get_le16(sync_ind + 20); - ble_ll_conn_get_anchor(connsm, conn_event_count, &sm->anchor_point, - &sm->anchor_point_usecs); + ble_ll_conn_anchor_event_cntr_get(connsm, conn_event_count, &sm->anchor_point, + &sm->anchor_point_usecs); /* Set last anchor point */ sm->last_anchor_point = sm->anchor_point - (last_pa_diff * sm->itvl_ticks); @@ -2104,8 +2140,8 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, /* calculate extra window widening */ sync_conn_event_count = get_le16(sync_ind + 32); sca = sync_ind[24] >> 5; - ble_ll_conn_get_anchor(connsm, sync_conn_event_count, &sync_anchor, - &sync_anchor_usecs); + ble_ll_conn_anchor_event_cntr_get(connsm, sync_conn_event_count, &sync_anchor, + &sync_anchor_usecs); ww_adjust = ble_ll_utils_calc_window_widening(connsm->anchor_point, sync_anchor, sca); @@ -2134,8 +2170,15 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, sm->anchor_point = sm->sch.start_time + g_ble_ll_sched_offset_ticks; sm->anchor_point_usecs = sm->sch.remainder; - if (reports_disabled) { + switch (mode) { + case 0x1: sm->flags |= BLE_LL_SYNC_SM_FLAG_DISABLED; + break; + case 0x3: + sm->flags |= BLE_LL_SYNC_SM_FLAG_DUPLICATES; + break; + default: + break; } } @@ -2156,7 +2199,7 @@ ble_ll_sync_put_syncinfo(struct ble_ll_sync_sm *syncsm, /* get anchor for conn event that is before periodic_adv_event_start_time */ while (LL_TMR_GT(anchor, syncsm->anchor_point)) { - ble_ll_conn_get_anchor(connsm, --conn_cnt, &anchor, &anchor_usecs); + ble_ll_conn_anchor_event_cntr_get(connsm, --conn_cnt, &anchor, &anchor_usecs); } offset = ble_ll_tmr_t2u(syncsm->anchor_point - anchor); @@ -2390,4 +2433,5 @@ ble_ll_sync_init(void) } } #endif -#endif + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_trace.c b/src/nimble/nimble/controller/src/ble_ll_trace.c index e51f852f0..dc0be80dd 100644 --- a/src/nimble/nimble/controller/src/ble_ll_trace.c +++ b/src/nimble/nimble/controller/src/ble_ll_trace.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,7 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM + #include #include "syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os_trace_api.h" @@ -54,4 +56,5 @@ ble_ll_trace_init(void) ble_ll_trace_module_send_desc); } #endif -#endif + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_utils.c b/src/nimble/nimble/controller/src/ble_ll_utils.c index acf15849b..bc42b7118 100644 --- a/src/nimble/nimble/controller/src/ble_ll_utils.c +++ b/src/nimble/nimble/controller/src/ble_ll_utils.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,7 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM #include #include @@ -478,4 +479,5 @@ ble_ll_utils_calc_window_widening(uint32_t anchor_point, return window_widening; } -#endif + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_whitelist.c b/src/nimble/nimble/controller/src/ble_ll_whitelist.c index a7881308b..eeb5b447f 100644 --- a/src/nimble/nimble/controller/src/ble_ll_whitelist.c +++ b/src/nimble/nimble/controller/src/ble_ll_whitelist.c @@ -1,3 +1,5 @@ +#ifndef ESP_PLATFORM + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -16,8 +18,6 @@ * specific language governing permissions and limitations * under the License. */ -#ifndef ESP_PLATFORM - #include #include #include @@ -294,4 +294,4 @@ ble_ll_whitelist_disable(void) #endif } -#endif +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/drivers/nrf51/src/ble_hw.c b/src/nimble/nimble/drivers/nrf51/src/ble_hw.c index 5f851fb49..915558d05 100644 --- a/src/nimble/nimble/drivers/nrf51/src/ble_hw.c +++ b/src/nimble/nimble/drivers/nrf51/src/ble_hw.c @@ -1,3 +1,5 @@ +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) - #include #include #include @@ -33,7 +33,7 @@ #include "mcu/cmsis_nvic.h" #else #include "core_cm0.h" -#include +#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" #endif #include "nimble/porting/nimble/include/os/os_trace_api.h" @@ -454,7 +454,7 @@ ble_hw_resolv_list_rmv(int index) if (index < g_nrf_num_irks) { --g_nrf_num_irks; - irk_entry = &g_nrf_irk_list[index]; + irk_entry = &g_nrf_irk_list[4 * index]; if (g_nrf_num_irks > index) { memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index)); } diff --git a/src/nimble/nimble/drivers/nrf51/src/ble_phy.c b/src/nimble/nimble/drivers/nrf51/src/ble_phy.c index ebb0527f8..e38bd4712 100644 --- a/src/nimble/nimble/drivers/nrf51/src/ble_phy.c +++ b/src/nimble/nimble/drivers/nrf51/src/ble_phy.c @@ -1,3 +1,5 @@ +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) - #include #include #include @@ -50,7 +50,7 @@ #endif #ifndef min -#define min(a, b) ((a)<(b)?(a):(b)) +#define min(a, b) ((a) < (b) ? (a) : (b)) #endif static uint32_t diff --git a/src/nimble/nimble/drivers/nrf5x/include/ble/xcvr.h b/src/nimble/nimble/drivers/nrf5x/include/ble/xcvr.h index b8c7a0f8e..bb2da5684 100644 --- a/src/nimble/nimble/drivers/nrf5x/include/ble/xcvr.h +++ b/src/nimble/nimble/drivers/nrf5x/include/ble/xcvr.h @@ -17,8 +17,6 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) - #ifndef H_BLE_XCVR_ #define H_BLE_XCVR_ @@ -61,4 +59,3 @@ extern "C" { #endif #endif /* H_BLE_XCVR_ */ -#endif /* defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) */ diff --git a/src/nimble/nimble/drivers/nrf5x/src/ble_hw.c b/src/nimble/nimble/drivers/nrf5x/src/ble_hw.c index 7525926d6..9cac75aa8 100644 --- a/src/nimble/nimble/drivers/nrf5x/src/ble_hw.c +++ b/src/nimble/nimble/drivers/nrf5x/src/ble_hw.c @@ -1,3 +1,5 @@ +#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES)) + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) - #include #include #include @@ -35,7 +35,7 @@ #ifdef NRF52_SERIES #include "core_cm4.h" #endif -#include +#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" #endif #include "nimble/porting/nimble/include/os/os_trace_api.h" #include @@ -484,7 +484,7 @@ ble_hw_resolv_list_rmv(int index) if (index < g_nrf_num_irks) { --g_nrf_num_irks; - irk_entry = &g_nrf_irk_list[index]; + irk_entry = &g_nrf_irk_list[4 * index]; if (g_nrf_num_irks > index) { memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index)); } @@ -520,4 +520,4 @@ ble_hw_resolv_list_match(void) } #endif -#endif /* defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) */ +#endif /* ARDUINO_ARCH_NRF5 && NRF52_SERIES */ diff --git a/src/nimble/nimble/drivers/nrf5x/src/ble_phy.c b/src/nimble/nimble/drivers/nrf5x/src/ble_phy.c index d3d690bdb..88ac8bdcb 100644 --- a/src/nimble/nimble/drivers/nrf5x/src/ble_phy.c +++ b/src/nimble/nimble/drivers/nrf5x/src/ble_phy.c @@ -1,3 +1,5 @@ +#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES)) + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,12 +19,10 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) - #include #include #include -#include +#include "nimble/nimble/controller/include/controller/ble_fem.h" #include #include #include @@ -48,7 +48,7 @@ #include #endif #include "mcu/cmsis_nvic.h" -#include "nimble/porting/nimble/include/hal/hal_gpio.h" +#include "hal/hal_gpio.h" #else #include #ifdef NRF52_SERIES @@ -58,13 +58,17 @@ #include #include "phy_priv.h" +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) #if !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52840) && \ !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52811) && \ !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF5340_NET) && \ !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52833) && \ !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52820) -#error LE Coded PHY can only be enabled on nRF52811, nRF52820, nRF52833, nRF52840 or nRF5340 +#error LE Coded PHY can only be enabled on nRF52811, nRF52840, nRF52833, nRF52820 or nRF5340 #endif #endif @@ -72,11 +76,7 @@ extern void tm_tick(void); #endif -#include - -#ifndef min -#define min(a, b) ((a)<(b)?(a):(b)) -#endif +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" /* * NOTE: This code uses a couple of PPI channels so care should be taken when @@ -191,7 +191,7 @@ static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = { 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */ }; -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) /* packet start offsets (in usecs) */ static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = { [BLE_PHY_MODE_1M] = 40, @@ -230,15 +230,22 @@ static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { #else /* delay between EVENTS_READY and start of tx */ static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 4, - [BLE_PHY_MODE_2M] = 3, + [BLE_PHY_MODE_1M] = 6, + [BLE_PHY_MODE_2M] = 5, [BLE_PHY_MODE_CODED_125KBPS] = 5, [BLE_PHY_MODE_CODED_500KBPS] = 5 }; +/* delay between EVENTS_ADDRESS and txd access address */ +static const uint8_t g_ble_phy_t_txaddrdelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 7, + [BLE_PHY_MODE_2M] = 5, + [BLE_PHY_MODE_CODED_125KBPS] = 17, + [BLE_PHY_MODE_CODED_500KBPS] = 17 +}; /* delay between EVENTS_END and end of txd packet */ static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 4, - [BLE_PHY_MODE_2M] = 3, + [BLE_PHY_MODE_1M] = 6, + [BLE_PHY_MODE_2M] = 4, [BLE_PHY_MODE_CODED_125KBPS] = 9, [BLE_PHY_MODE_CODED_500KBPS] = 3 }; @@ -251,8 +258,8 @@ static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = { }; /* delay between end of rxd packet and EVENTS_END */ static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 6, - [BLE_PHY_MODE_2M] = 2, + [BLE_PHY_MODE_1M] = 4, + [BLE_PHY_MODE_2M] = 1, [BLE_PHY_MODE_CODED_125KBPS] = 27, [BLE_PHY_MODE_CODED_500KBPS] = 22 }; @@ -346,7 +353,33 @@ struct nrf_ccm_data struct nrf_ccm_data g_nrf_ccm_data; #endif -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +static void +timer0_reset(void) +{ + /* Reset CC registers to avoid triggering spurious COMPARE events */ + NRF_TIMER0->CC[0] = 0; + NRF_TIMER0->CC[1] = 0; + NRF_TIMER0->CC[2] = 0; + NRF_TIMER0->CC[3] = 0; +} + +static bool +timer0_did_miss(int cc, int cc_scratch) +{ + uint32_t now, target; + + nrf_timer_task_trigger(NRF_TIMER0, nrf_timer_capture_task_get(cc_scratch)); + target = NRF_TIMER0->CC[cc]; + now = NRF_TIMER0->CC[cc_scratch]; + + /* COMPARE event is not triggered when CC is set to the current value of + * TIMER0 (at the time it was set), so the case of equal CC values without + * a COMPARE event should be also considered a miss here. + */ + return (now >= target) && !NRF_TIMER0->EVENTS_COMPARE[cc]; +} + +#if MYNEWT_VAL(BLE_LL_PHY) /* Packet start offset (in usecs). This is the preamble plus access address. * For LE Coded PHY this also includes CI and TERM1. */ @@ -459,7 +492,7 @@ ble_phy_mode_pdu_start_off(int phy_mode) static int ble_phy_get_cur_phy(void) { -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) switch (g_ble_phy_data.phy_cur_phy_mode) { case BLE_PHY_MODE_1M: return BLE_PHY_1M; @@ -703,6 +736,8 @@ ble_phy_set_start_time(uint32_t cputime, uint8_t rem_us, bool tx) return -1; } + timer0_reset(); + /* Clear and set TIMER0 to fire off at proper time */ nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); nrf_timer_cc_set(NRF_TIMER0, 0, radio_rem_us + rem_us_corr); @@ -860,6 +895,8 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) * by waiting 1 usec more. */ end_time += 1; + + end_time += MYNEWT_VAL(BLE_PHY_EXTENDED_TIFS); } else { /* * RX shall start no later than wfr_usecs after RX enabled. @@ -880,27 +917,24 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) /* Adjust for delay between actual access address RX and EVENT_ADDRESS */ end_time += g_ble_phy_t_rxaddrdelay[phy]; - /* wfr_secs is the time from rxen until timeout */ - nrf_timer_cc_set(NRF_TIMER0, 3, end_time); - NRF_TIMER0->EVENTS_COMPARE[3] = 0; - /* Enable wait for response PPI */ + NRF_TIMER0->EVENTS_COMPARE[3] = 0; phy_ppi_wfr_enable(); + nrf_timer_cc_set(NRF_TIMER0, 3, end_time); /* - * It may happen that if CPU is halted for a brief moment (e.g. during flash - * erase or write), TIMER0 already counted past CC[3] and thus wfr will not - * fire as expected. In case this happened, let's just disable PPIs for wfr - * and trigger wfr manually (i.e. disable radio). + * It may happen that if CPU is halted for a brief moment (e.g. during + * flash, erase or write), TIMER0 already counted past CC[3] and thus wfr + * will not fire as expected. In case this happened, let's just disable + * PPIs for wfr and trigger wfr manually (i.e. disable radio). * * Note that the same applies to RX start time set in CC[0] but since it * should fire earlier than wfr, fixing wfr is enough. * - * CC[1] is only used as a reference on RX start, we do not need it here so - * it can be used to read TIMER0 counter. + * CC[1] is only used as a reference on RX start. We do not need it here, + * so we can use it as a scratch register. */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE1); - if (NRF_TIMER0->CC[1] > NRF_TIMER0->CC[3]) { + if (timer0_did_miss(3, 1)) { phy_ppi_wfr_disable(); nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE); } @@ -910,7 +944,7 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) static uint32_t ble_phy_get_ccm_datarate(void) { -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) switch (g_ble_phy_data.phy_cur_phy_mode) { case BLE_PHY_MODE_1M: return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; @@ -987,7 +1021,7 @@ ble_phy_rx_xcvr_setup(void) g_ble_phy_data.phy_rx_started = 0; g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; -#if BLE_LL_BT5_PHY_SUPPORTED +#if MYNEWT_VAL(BLE_LL_PHY) /* * On Coded PHY there are CI and TERM1 fields before PDU starts so we need * to take this into account when setting up BCC. @@ -1073,7 +1107,7 @@ ble_phy_tx_end_isr(void) } if (transition == BLE_PHY_TRANSITION_TX_RX) { -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); #endif @@ -1091,15 +1125,15 @@ ble_phy_tx_end_isr(void) #if PHY_USE_FEM_LNA fem_time = rx_time - MYNEWT_VAL(BLE_FEM_LNA_TURN_ON_US); - nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); NRF_TIMER0->EVENTS_COMPARE[2] = 0; phy_fem_enable_lna(); + nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); #endif radio_time = rx_time - BLE_PHY_T_RXENFAST; - nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); NRF_TIMER0->EVENTS_COMPARE[0] = 0; phy_ppi_timer0_compare0_to_radio_rxen_enable(); + nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); /* In case TIMER0 did already count past CC[0] and/or CC[2], radio * and/or LNA may not be enabled. In any case we won't be stuck since @@ -1110,25 +1144,24 @@ ble_phy_tx_end_isr(void) */ } else if (transition == BLE_PHY_TRANSITION_TX_TX) { if (g_ble_phy_data.txtx_time_anchor) { - /* Schedule next TX relative to current TX end. TX end timestamp is - * captured in CC[2]. - */ - tx_time = NRF_TIMER0->CC[2] + g_ble_phy_data.txtx_time_us; - } else { - /* Schedule next TX relative to current TX start. AA timestamp is - * captured in CC[1], we need to adjust for sync word to get TX - * start. - */ - tx_time = NRF_TIMER0->CC[1] - ble_ll_pdu_syncword_us(tx_phy_mode) + - g_ble_phy_data.txtx_time_us; - /* Adjust for delay between EVENT_ADDRESS and actual address TX time */ - /* FIXME assume this is the same as EVENT_END to end, but we should - * measure this to be sure */ + /* Calculate TX anchor relative to current TX end */ + + /* TX end timestamp is captured in CC[2] */ + tx_time = NRF_TIMER0->CC[2]; + /* Adjust for delay between EVENT_END and actual TX end time */ tx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; + } else { + /* Calculate TX anchor relative to current TX start */ + + /* AA timestamp is captured in CC[1] */ + tx_time = NRF_TIMER0->CC[1]; + /* Adjust for delay between EVENT_ADDRESS and actual AA time ota */ + tx_time += g_ble_phy_t_txaddrdelay[tx_phy_mode]; + /* Adjust by sync word length to get TX start time */ + tx_time -= ble_ll_pdu_syncword_us(tx_phy_mode); } - /* Adjust for delay between EVENT_END and actual TX end time */ - tx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; + tx_time += g_ble_phy_data.txtx_time_us; #if PHY_USE_FEM_PA fem_time = tx_time - MYNEWT_VAL(BLE_FEM_PA_TURN_ON_US); @@ -1138,18 +1171,17 @@ ble_phy_tx_end_isr(void) tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; radio_time = tx_time - BLE_PHY_T_TXENFAST; - nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); NRF_TIMER0->EVENTS_COMPARE[0] = 0; phy_ppi_timer0_compare0_to_radio_txen_enable(); + nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); #if PHY_USE_FEM_PA - nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); NRF_TIMER0->EVENTS_COMPARE[2] = 0; phy_fem_enable_pa(); + nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); #endif - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); - if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) { + if (timer0_did_miss(0, 3)) { phy_ppi_timer0_compare0_to_radio_txen_disable(); g_ble_phy_data.phy_transition_late = 1; } @@ -1250,7 +1282,7 @@ ble_phy_rx_end_isr(void) #endif } -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); #endif @@ -1288,14 +1320,14 @@ ble_phy_rx_end_isr(void) tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; radio_time = tx_time - BLE_PHY_T_TXENFAST; - nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); NRF_TIMER0->EVENTS_COMPARE[0] = 0; phy_ppi_timer0_compare0_to_radio_txen_enable(); + nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); #if PHY_USE_FEM_PA - nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); NRF_TIMER0->EVENTS_COMPARE[2] = 0; phy_fem_enable_pa(); + nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); #endif /* Need to check if TIMER0 did not already count past CC[0] and/or CC[2], so @@ -1304,11 +1336,9 @@ ble_phy_rx_end_isr(void) * * Note: CC[3] is used only for wfr which we do not need here. */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); - is_late = (NRF_TIMER0->CC[3] > radio_time) && !NRF_TIMER0->EVENTS_COMPARE[0]; + is_late = timer0_did_miss(0, 3); #if PHY_USE_FEM_PA - is_late = is_late || - ((NRF_TIMER0->CC[3] > fem_time) && !NRF_TIMER0->EVENTS_COMPARE[2]); + is_late = is_late || timer0_did_miss(2, 3); #endif if (is_late) { phy_ppi_timer0_compare0_to_radio_txen_disable(); @@ -1533,7 +1563,7 @@ ble_phy_isr(void) os_trace_isr_exit(); } -#if PHY_USE_HEADERMASK_WORKAROUND +#if PHY_USE_HEADERMASK_WORKAROUND && MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) static void ble_phy_ccm_isr(void) { @@ -1818,7 +1848,7 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs); -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); #endif @@ -1860,7 +1890,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs); -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_PHY) ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); #endif @@ -2294,6 +2324,22 @@ void ble_phy_disable_dtm(void) /* Enable whitening */ NRF_RADIO->PCNF1 |= RADIO_PCNF1_WHITEEN_Msk; } + +#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) +int +ble_phy_dtm_carrier(uint8_t rf_channel) +{ + /* based on Nordic DTM sample */ + ble_phy_disable(); + ble_phy_enable_dtm(); + ble_phy_mode_apply(BLE_PHY_MODE_1M); + nrf_radio_shorts_enable(NRF_RADIO, NRF_RADIO_SHORT_READY_START_MASK); + NRF_RADIO->FREQUENCY = g_ble_phy_chan_freq[rf_channel]; + nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN); + + return 0; +} +#endif #endif void @@ -2333,4 +2379,4 @@ ble_phy_tifs_txtx_set(uint16_t usecs, uint8_t anchor) g_ble_phy_data.txtx_time_anchor = anchor; } -#endif /* defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) */ +#endif /* ARDUINO_ARCH_NRF5 && NRF52_SERIES */ diff --git a/src/nimble/nimble/drivers/nrf5x/src/ble_phy_trace.c b/src/nimble/nimble/drivers/nrf5x/src/ble_phy_trace.c index ce395b11c..47008639e 100644 --- a/src/nimble/nimble/drivers/nrf5x/src/ble_phy_trace.c +++ b/src/nimble/nimble/drivers/nrf5x/src/ble_phy_trace.c @@ -1,3 +1,5 @@ +#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES)) + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) - #include #include "syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os_trace_api.h" @@ -45,4 +45,4 @@ ble_phy_trace_init(void) } #endif -#endif /* defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) */ +#endif /* ARDUINO_ARCH_NRF5 && NRF52_SERIES */ diff --git a/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy.c b/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy.c index a2b04db99..f29fa345b 100644 --- a/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy.c +++ b/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy.c @@ -1,3 +1,5 @@ +#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES)) + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,11 +19,9 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) - #include #include -#include +#include "nimble/nimble/controller/include/controller/ble_fem.h" #include "nimble/nimble/drivers/nrf5x/src/phy_priv.h" #if PHY_USE_DEBUG @@ -190,31 +190,6 @@ phy_txpower_set(int8_t dbm) int8_t phy_txpower_round(int8_t dbm) { -/* "Rail" power level if outside supported range */ -#ifdef RADIO_TXPOWER_TXPOWER_Pos8dBm - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm; - } -#endif - -#ifdef RADIO_TXPOWER_TXPOWER_Pos7dBm - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm; - } -#endif - -#ifdef RADIO_TXPOWER_TXPOWER_Pos6dBm - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm; - } -#endif - -#ifdef RADIO_TXPOWER_TXPOWER_Pos5dBm - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm; - } -#endif - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { return (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm; } @@ -246,4 +221,4 @@ phy_txpower_round(int8_t dbm) return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; } -#endif /* defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) */ +#endif /* ARDUINO_ARCH_NRF5 && NRF52_SERIES */ diff --git a/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h b/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h index 3f9e931ce..a77b71833 100644 --- a/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h +++ b/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h @@ -20,8 +20,6 @@ #ifndef H_PHY_PPI_ #define H_PHY_PPI_ -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) - #include static inline void @@ -113,4 +111,3 @@ phy_ppi_disable(void) } #endif /* H_PHY_PPI_ */ -#endif /* ARDUINO_ARCH_NRF5 && NRF52_SERIES */ \ No newline at end of file diff --git a/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy.c b/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy.c deleted file mode 100644 index 016ebf29e..000000000 --- a/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF53) - -#include -#include -#include -#include "nimble/nimble/drivers/nrf5x/src/phy_priv.h" - -/* - * When the radio is operated on high voltage (see VREQCTRL - Voltage request - * control on page 62 for how to control voltage), the output power is increased - * by 3 dB. I.e. if the TXPOWER value is set to 0 dBm and high voltage is - * requested using VREQCTRL, the output power will be +3 - * */ -#define NRF_TXPOWER_VREQH 3 - -#if PHY_USE_DEBUG -void -phy_debug_init(void) -{ -#if PHY_USE_DEBUG_1 - phy_gpiote_configure(PHY_GPIOTE_DEBUG_1, - MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); - - NRF_RADIO->PUBLISH_READY = DPPI_CH_PUB(RADIO_EVENTS_READY); - NRF_DPPIC->CHENSET = DPPI_CH_MASK(RADIO_EVENTS_READY); - - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_DEBUG_1] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); - NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_1] = DPPI_CH_SUB(RADIO_EVENTS_READY); -#endif - -#if PHY_USE_DEBUG_2 - phy_gpiote_configure(PHY_GPIOTE_DEBUG_2, - MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); - - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_DEBUG_2] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_2] = DPPI_CH_SUB(RADIO_EVENTS_END); -#endif - -#if PHY_USE_DEBUG_3 - phy_gpiote_configure(PHY_GPIOTE_DEBUG_3, MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); - - NRF_RADIO->PUBLISH_RXREADY = DPPI_CH_PUB(RADIO_EVENTS_READY); - NRF_RADIO->PUBLISH_DISABLED = DPPI_CH_PUB(RADIO_EVENTS_DISABLED); - NRF_DPPIC->CHENSET = DPPI_CH_MASK(RADIO_EVENTS_RXREADY) | - DPPI_CH_MASK(RADIO_EVENTS_DISABLED); - - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_DEBUG_3] = DPPI_CH_SUB(RADIO_EVENTS_RXREADY); - - /* TODO figure out how (if?) to subscribe task to multiple DPPI channels - * Currently only last one is working. Also using multiple GPIOTE for same - * PIN doesn't work... - */ - NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_3] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED); - NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_3] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_3] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_3); - -#endif -} -#endif /* PHY_USE_DEBUG */ - -#if PHY_USE_FEM -void -phy_fem_init() -{ - /* We can keep clear tasks subscribed and published channels always enabled, - * it's enough to just (un)subscribe set tasks when needed. - * TODO: check if this affects power consumption - */ - - NRF_TIMER0->PUBLISH_COMPARE[2] = DPPI_CH_PUB(TIMER0_EVENTS_COMPARE_2); - NRF_RADIO->PUBLISH_DISABLED = DPPI_CH_PUB(RADIO_EVENTS_DISABLED); - -#if PHY_USE_FEM_SINGLE_GPIO -#if PHY_USE_FEM_PA - phy_gpiote_configure(PHY_GPIOTE_FEM, MYNEWT_VAL(BLE_FEM_PA_GPIO)); -#else - phy_gpiote_configure(PHY_GPIOTE_FEM, MYNEWT_VAL(BLE_FEM_LNA_GPIO)); -#endif - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM] = - DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); - NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_FEM] = - DPPI_CH_SUB(RADIO_EVENTS_DISABLED); - NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM] = 1; -#else -#if PHY_USE_FEM_PA - phy_gpiote_configure(PHY_GPIOTE_FEM_PA, MYNEWT_VAL(BLE_FEM_PA_GPIO)); - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_PA] = - DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); - NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_FEM_PA] = - DPPI_CH_SUB(RADIO_EVENTS_DISABLED); - NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA] = 1; -#endif -#if PHY_USE_FEM_LNA - phy_gpiote_configure(PHY_GPIOTE_FEM_LNA, MYNEWT_VAL(BLE_FEM_LNA_GPIO)); - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_LNA] = - DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); - NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_FEM_LNA] = - DPPI_CH_SUB(RADIO_EVENTS_DISABLED); - NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA] = 1; -#endif -#endif /* PHY_USE_FEM_SINGLE_GPIO */ - - NRF_DPPIC->CHENSET = DPPI_CH_MASK_FEM; -} - -#if PHY_USE_FEM_PA -void -phy_fem_enable_pa(void) -{ - ble_fem_pa_enable(); - -#if PHY_USE_FEM_SINGLE_GPIO - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM] = - DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_2); -#else - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_PA] = - DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_2); -#endif -} -#endif - -#if PHY_USE_FEM_LNA -void -phy_fem_enable_lna(void) -{ - ble_fem_lna_enable(); - -#if PHY_USE_FEM_SINGLE_GPIO - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM] = - DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_2); -#else - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_LNA] = - DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_2); -#endif -} -#endif - -void -phy_fem_disable(void) -{ -#if PHY_USE_FEM_SINGLE_GPIO - NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM] = 1; -#else -#if PHY_USE_FEM_PA - NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA] = 1; -#endif -#if PHY_USE_FEM_LNA - NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA] = 1; -#endif -#endif -} -#endif /* PHY_USE_FEM */ - -void -phy_ppi_init(void) -{ - /* Publish events */ - NRF_TIMER0->PUBLISH_COMPARE[0] = DPPI_CH_PUB(TIMER0_EVENTS_COMPARE_0); - NRF_TIMER0->PUBLISH_COMPARE[3] = DPPI_CH_PUB(TIMER0_EVENTS_COMPARE_3); - NRF_RADIO->PUBLISH_END = DPPI_CH_PUB(RADIO_EVENTS_END); - NRF_RADIO->PUBLISH_BCMATCH = DPPI_CH_PUB(RADIO_EVENTS_BCMATCH); - NRF_RADIO->PUBLISH_ADDRESS = DPPI_CH_PUB(RADIO_EVENTS_ADDRESS); - NRF_RTC0->PUBLISH_COMPARE[0] = DPPI_CH_PUB(RTC0_EVENTS_COMPARE_0); - - /* Enable channels we publish on */ - NRF_DPPIC->CHENSET = DPPI_CH_ENABLE_ALL; - - /* radio_address_to_timer0_capture1 */ - NRF_TIMER0->SUBSCRIBE_CAPTURE[1] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - /* radio_end_to_timer0_capture2 */ - NRF_TIMER0->SUBSCRIBE_CAPTURE[2] = DPPI_CH_SUB(RADIO_EVENTS_END); -} - -void -phy_txpower_set(int8_t dbm) -{ -#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) - switch (dbm) { - case ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH: - case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH: - case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH: - case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH: - case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH: - case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH: - case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH: - NRF_VREQCTRL->VREGRADIO.VREQH = 1; - dbm -= NRF_TXPOWER_VREQH; - break; - default: - NRF_VREQCTRL->VREGRADIO.VREQH = 0; - break; - } -#endif - - NRF_RADIO->TXPOWER = dbm; -} - -int8_t -phy_txpower_round(int8_t dbm) -{ -#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) - /* +3 dBm */ - if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH) { - return ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH; - } - - /* +2 dBm */ - if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH) { - return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH; - } - - /* +1 dBm */ - if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH) { - return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH; - } -#endif - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; - } - -#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) - /* -9 dBm */ - if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH) { - return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH; - } -#endif - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; - } - -#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) - /* -13 dBm */ - if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH) { - return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH; - } -#endif - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm; - } - -#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) - /* -17 dBm */ - if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH) { - return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH; - } -#endif - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; - } - -#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) - /* -37 dBm */ - if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH) { - return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH; - } -#endif - - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; -} - -#endif /* ARDUINO_ARCH_NRF5 && NRF53 */ - diff --git a/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy_ppi.h b/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy_ppi.h deleted file mode 100644 index 6412f3275..000000000 --- a/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy_ppi.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_PHY_PPI_ -#define H_PHY_PPI_ - -#define DPPI_CH_PUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (1 << 31)) -#define DPPI_CH_SUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (1 << 31)) -#define DPPI_CH_UNSUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (0 << 31)) -#define DPPI_CH_MASK(_ch) (1 << (DPPI_CH_ ## _ch)) - -/* Channels 0..5 are always used. - * Channels 6 and 7 are used for PA/LNA (optionally). - * Channels 7..9 are used for GPIO debugging (optionally). - */ - -#define DPPI_CH_TIMER0_EVENTS_COMPARE_0 0 -#define DPPI_CH_TIMER0_EVENTS_COMPARE_3 1 -#define DPPI_CH_RADIO_EVENTS_END 2 -#define DPPI_CH_RADIO_EVENTS_BCMATCH 3 -#define DPPI_CH_RADIO_EVENTS_ADDRESS 4 -#define DPPI_CH_RTC0_EVENTS_COMPARE_0 5 -#define DPPI_CH_TIMER0_EVENTS_COMPARE_2 6 -#define DPPI_CH_RADIO_EVENTS_DISABLED 7 -#define DPPI_CH_RADIO_EVENTS_READY 8 -#define DPPI_CH_RADIO_EVENTS_RXREADY 9 - -#define DPPI_CH_ENABLE_ALL (DPPIC_CHEN_CH0_Msk | DPPIC_CHEN_CH1_Msk | \ - DPPIC_CHEN_CH2_Msk | DPPIC_CHEN_CH3_Msk | \ - DPPIC_CHEN_CH4_Msk | DPPIC_CHEN_CH5_Msk) - -#define DPPI_CH_MASK_FEM (DPPI_CH_MASK(TIMER0_EVENTS_COMPARE_2) | \ - DPPI_CH_MASK(RADIO_EVENTS_DISABLED)) - -static inline void -phy_ppi_rtc0_compare0_to_timer0_start_enable(void) -{ - NRF_TIMER0->SUBSCRIBE_START = DPPI_CH_SUB(RTC0_EVENTS_COMPARE_0); -} - -static inline void -phy_ppi_rtc0_compare0_to_timer0_start_disable(void) -{ - NRF_TIMER0->SUBSCRIBE_START = DPPI_CH_UNSUB(RTC0_EVENTS_COMPARE_0); - NRF_TIMER0->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); -} - -static inline void -phy_ppi_timer0_compare0_to_radio_txen_enable(void) -{ - NRF_RADIO->SUBSCRIBE_TXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); -} - -static inline void -phy_ppi_timer0_compare0_to_radio_txen_disable(void) -{ - NRF_RADIO->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); -} - -static inline void -phy_ppi_timer0_compare0_to_radio_rxen_enable(void) -{ - NRF_RADIO->SUBSCRIBE_RXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); -} - -static inline void -phy_ppi_timer0_compare0_to_radio_rxen_disable(void) -{ - NRF_RADIO->SUBSCRIBE_RXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); -} - -static inline void -phy_ppi_radio_address_to_ccm_crypt_enable(void) -{ - NRF_CCM->SUBSCRIBE_CRYPT = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); -} - -static inline void -phy_ppi_radio_address_to_ccm_crypt_disable(void) -{ - NRF_CCM->SUBSCRIBE_CRYPT = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); -} - -static inline void -phy_ppi_radio_bcmatch_to_aar_start_enable(void) -{ - NRF_AAR->SUBSCRIBE_START = DPPI_CH_SUB(RADIO_EVENTS_BCMATCH); -} - -static inline void -phy_ppi_radio_bcmatch_to_aar_start_disable(void) -{ - NRF_AAR->SUBSCRIBE_START = DPPI_CH_UNSUB(RADIO_EVENTS_BCMATCH); -} - -static inline void -phy_ppi_wfr_enable(void) -{ - NRF_TIMER0->SUBSCRIBE_CAPTURE[3] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO->SUBSCRIBE_DISABLE = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_3); -} - -static inline void -phy_ppi_wfr_disable(void) -{ - NRF_TIMER0->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); -} - -static inline void -phy_ppi_fem_disable(void) -{ -#if PHY_USE_FEM_SINGLE_GPIO - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM] = - DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); -#else -#if PHY_USE_FEM_PA - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_PA] = - DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); -#endif -#if PHY_USE_FEM_LNA - NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_LNA] = - DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); -#endif -#endif -} - -static inline void -phy_ppi_disable(void) -{ - NRF_TIMER0->SUBSCRIBE_START = DPPI_CH_UNSUB(RTC0_EVENTS_COMPARE_0); - NRF_TIMER0->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); - NRF_RADIO->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - NRF_RADIO->SUBSCRIBE_RXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - NRF_AAR->SUBSCRIBE_START = DPPI_CH_UNSUB(RADIO_EVENTS_BCMATCH); - NRF_CCM->SUBSCRIBE_CRYPT = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - - phy_ppi_fem_disable(); -} - -#endif /* H_PHY_PPI_ */ \ No newline at end of file diff --git a/src/nimble/nimble/drivers/nrf5x/src/phy_priv.h b/src/nimble/nimble/drivers/nrf5x/src/phy_priv.h index aac5e52fd..0fd15a53b 100644 --- a/src/nimble/nimble/drivers/nrf5x/src/phy_priv.h +++ b/src/nimble/nimble/drivers/nrf5x/src/phy_priv.h @@ -53,14 +53,16 @@ #define PHY_GPIOTE_FEM_LNA (PHY_GPIOTE_FEM_PA - PHY_USE_FEM_LNA) #endif +#if PHY_USE_DEBUG static inline void phy_gpiote_configure(int idx, int pin) { nrf_gpio_cfg_output(pin); - nrf_gpiote_task_configure(NRF_GPIOTE, idx, pin, GPIOTE_CONFIG_POLARITY_None/*NRF_GPIOTE_POLARITY_NONE*/, + nrf_gpiote_task_configure(NRF_GPIOTE, idx, pin, NRF_GPIOTE_POLARITY_NONE, NRF_GPIOTE_INITIAL_VALUE_LOW); nrf_gpiote_task_enable(NRF_GPIOTE, idx); } +#endif #if PHY_USE_DEBUG void phy_debug_init(void); diff --git a/src/nimble/nimble/host/include/host/ble_aes_ccm.h b/src/nimble/nimble/host/include/host/ble_aes_ccm.h index 1895c81d9..8b2292c64 100644 --- a/src/nimble/nimble/host/include/host/ble_aes_ccm.h +++ b/src/nimble/nimble/host/include/host/ble_aes_ccm.h @@ -11,12 +11,6 @@ #include "nimble/porting/nimble/include/os/queue.h" #include "nimble/nimble/host/include/host/ble_hs.h" -#if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#else -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/src/nimble/nimble/host/include/host/ble_att.h b/src/nimble/nimble/host/include/host/ble_att.h index fb8f72a9c..a1277bae3 100644 --- a/src/nimble/nimble/host/include/host/ble_att.h +++ b/src/nimble/nimble/host/include/host/ble_att.h @@ -109,9 +109,22 @@ struct os_mbuf; /**Insufficient Resources to complete the request. */ #define BLE_ATT_ERR_INSUFFICIENT_RES 0x11 -#define BLE_ATT_ERR_DB_OUT_OF_SYNC 0x12 + +/**Requested value is not allowed. */ #define BLE_ATT_ERR_VALUE_NOT_ALLOWED 0x13 +/**Write Request Rejected. */ +#define BLE_ATT_ERR_WRITE_REQ_REJECTED 0xFC + +/**Client Characteristic Configuration Descriptor Improperly Configured. */ +#define BLE_ATT_ERR_CCCD_IMPORER_CONF 0xFD + +/**Procedure Already in Progress. */ +#define BLE_ATT_ERR_PROC_IN_PROGRESS 0xFE + +/**Out of Range. */ +#define BLE_ATT_ERR_OUT_OF_RANGE 0xFF + /** @} */ /** @@ -120,7 +133,6 @@ struct os_mbuf; */ /** Error Response. */ - #define BLE_ATT_OP_ERROR_RSP 0x01 /** MTU Request. */ @@ -189,12 +201,6 @@ struct os_mbuf; /** Execute Write Response. */ #define BLE_ATT_OP_EXEC_WRITE_RSP 0x19 -/** Read Multiple Variable Lenght Request */ -#define BLE_ATT_OP_READ_MULT_VAR_REQ 0x20 - -/** Read Multiple Variable Lenght Response */ -#define BLE_ATT_OP_READ_MULT_VAR_RSP 0x21 - /** Notify Request. */ #define BLE_ATT_OP_NOTIFY_REQ 0x1b @@ -204,15 +210,17 @@ struct os_mbuf; /** Indicate Response. */ #define BLE_ATT_OP_INDICATE_RSP 0x1e -/** Multiple Handle Value Length Notification Request */ -#define BLE_ATT_OP_NOTIFY_MULTI_REQ 0x23 +/** Read Multiple Variable Lenght Request */ +#define BLE_ATT_OP_READ_MULT_VAR_REQ 0x20 + +/** Read Multiple Variable Lenght Response */ +#define BLE_ATT_OP_READ_MULT_VAR_RSP 0x21 +/** Notify Multiple Request */ +#define BLE_ATT_OP_NOTIFY_MULTI_REQ 0x23 /** Write Command. */ #define BLE_ATT_OP_WRITE_CMD 0x52 -/** Signed Write Command */ -#define BLE_ATT_OP_SIGNED_WRITE_CMD 0xD2 - /** @} */ /** Maximum length of an Attribute Protocol (ATT) attribute. */ @@ -347,9 +355,6 @@ uint16_t ble_att_preferred_mtu(void); */ int ble_att_set_preferred_mtu(uint16_t mtu); -int ble_att_set_default_bearer_using_cid(uint16_t conn_handle, uint16_t cid); -uint16_t ble_att_get_default_bearer_cid(uint16_t conn_handle); - #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/host/include/host/ble_cs.h b/src/nimble/nimble/host/include/host/ble_cs.h new file mode 100644 index 000000000..3abbd11e6 --- /dev/null +++ b/src/nimble/nimble/host/include/host/ble_cs.h @@ -0,0 +1,57 @@ +/* + * 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. + */ + +/* All Channel Sounding APIs are experimental and subject to change at any time */ + +#ifndef H_BLE_CS_ +#define H_BLE_CS_ +#include "syscfg/syscfg.h" + +#define BLE_CS_EVENT_CS_PROCEDURE_COMPLETE (0) + +struct ble_cs_event { + uint8_t type; + union + { + struct + { + uint16_t conn_handle; + uint8_t status; + } procedure_complete; + }; + +}; + +typedef int ble_cs_event_fn(struct ble_cs_event *event, void *arg); + +struct ble_cs_initiator_procedure_start_params { + uint16_t conn_handle; + ble_cs_event_fn *cb; + void *cb_arg; +}; + +struct ble_cs_reflector_setup_params { + ble_cs_event_fn *cb; + void *cb_arg; +}; + +int ble_cs_initiator_procedure_start(const struct ble_cs_initiator_procedure_start_params *params); +int ble_cs_initiator_procedure_terminate(uint16_t conn_handle); +int ble_cs_reflector_setup(struct ble_cs_reflector_setup_params *params); +#endif diff --git a/src/nimble/nimble/host/include/host/ble_eddystone.h b/src/nimble/nimble/host/include/host/ble_eddystone.h index 76b7e2b01..3b75fdccf 100644 --- a/src/nimble/nimble/host/include/host/ble_eddystone.h +++ b/src/nimble/nimble/host/include/host/ble_eddystone.h @@ -34,30 +34,79 @@ extern "C" { struct ble_hs_adv_fields; +/** + * @defgroup ble_eddystone Eddystone Constants + * @ingroup bt_host + * @{ + */ + +/** Maximum number of 16-bit UUIDs in Eddystone advertisement data. */ #define BLE_EDDYSTONE_MAX_UUIDS16 3 + +/** Maximum length of Eddystone URL. */ #define BLE_EDDYSTONE_URL_MAX_LEN 17 + +/** Eddystone URL Scheme: "http://www." prefix. */ #define BLE_EDDYSTONE_URL_SCHEME_HTTP_WWW 0 + +/** Eddystone URL Scheme: "https://www." prefix. */ #define BLE_EDDYSTONE_URL_SCHEME_HTTPS_WWW 1 + +/** Eddystone URL Scheme: "http://" prefix. */ #define BLE_EDDYSTONE_URL_SCHEME_HTTP 2 + +/** Eddystone URL Scheme: "https://" prefix. */ #define BLE_EDDYSTONE_URL_SCHEME_HTTPS 3 + +/** Eddystone URL Suffix: ".com/". */ #define BLE_EDDYSTONE_URL_SUFFIX_COM_SLASH 0x00 + +/** Eddystone URL Suffix: ".org/". */ #define BLE_EDDYSTONE_URL_SUFFIX_ORG_SLASH 0x01 + +/** Eddystone URL Suffix: ".edu/". */ #define BLE_EDDYSTONE_URL_SUFFIX_EDU_SLASH 0x02 + +/** Eddystone URL Suffix: ".net/". */ #define BLE_EDDYSTONE_URL_SUFFIX_NET_SLASH 0x03 + +/** Eddystone URL Suffix: ".info/". */ #define BLE_EDDYSTONE_URL_SUFFIX_INFO_SLASH 0x04 + +/** Eddystone URL Suffix: ".biz/". */ #define BLE_EDDYSTONE_URL_SUFFIX_BIZ_SLASH 0x05 + +/** Eddystone URL Suffix: ".gov/". */ #define BLE_EDDYSTONE_URL_SUFFIX_GOV_SLASH 0x06 + +/** Eddystone URL Suffix: ".com". */ #define BLE_EDDYSTONE_URL_SUFFIX_COM 0x07 + +/** Eddystone URL Suffix: ".org". */ #define BLE_EDDYSTONE_URL_SUFFIX_ORG 0x08 + +/** Eddystone URL Suffix: ".edu". */ #define BLE_EDDYSTONE_URL_SUFFIX_EDU 0x09 + +/** Eddystone URL Suffix: ".net". */ #define BLE_EDDYSTONE_URL_SUFFIX_NET 0x0a + +/** Eddystone URL Suffix: ".info". */ #define BLE_EDDYSTONE_URL_SUFFIX_INFO 0x0b + +/** Eddystone URL Suffix: ".biz". */ #define BLE_EDDYSTONE_URL_SUFFIX_BIZ 0x0c + +/** Eddystone URL Suffix: ".gov". */ #define BLE_EDDYSTONE_URL_SUFFIX_GOV 0x0d + +/** Eddystone URL Suffix: None. */ #define BLE_EDDYSTONE_URL_SUFFIX_NONE 0xff +/** @} */ + /** * Configures the device to advertise Eddystone UID beacons. * @@ -103,7 +152,7 @@ int ble_eddystone_set_adv_data_uid(struct ble_hs_adv_fields *adv_fields, */ int ble_eddystone_set_adv_data_url(struct ble_hs_adv_fields *adv_fields, uint8_t url_scheme, char *url_body, - uint8_t url_body_len, uint8_t suffix, + uint8_t url_body_len, uint8_t url_suffix, int8_t measured_power); #ifdef __cplusplus diff --git a/src/nimble/nimble/host/include/host/ble_esp_gap.h b/src/nimble/nimble/host/include/host/ble_esp_gap.h deleted file mode 100644 index c94d81eb5..000000000 --- a/src/nimble/nimble/host/include/host/ble_esp_gap.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#ifndef H_BLE_ESP_GAP_ -#define H_BLE_ESP_GAP_ - -#ifdef __cplusplus -extern "C" { -#endif - -enum gap_status { - BLE_GAP_STATUS_ADV = 0, - BLE_GAP_STATUS_EXT_ADV, - BLE_GAP_STATUS_SCAN, - BLE_GAP_STATUS_CONN, - BLE_GAP_STATUS_PAIRED, - BLE_GAP_STATUS_GATTS, - BLE_GAP_STATUS_HOST_PRIVACY, - BLE_GAP_STATUS_PERIODIC, -}; - -typedef enum gap_status gap_status_t; - -#define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_ADV_ADDR 0 -#define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_LINK_ID 1 -#define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_BEACON_TYPE 2 -#define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROV_SRV_ADV 3 -#define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROXY_SRV_ADV 4 - -#define ESP_BLE_VENDOR_LEGACY_SCAN_REQ_EVT_MASK BIT(0) -#define ESP_BLE_VENDOR_CHAN_MAP_UPDATE_CMPL_EVT_MASK BIT(1) -#define ESP_BLE_VENDOR_TL_RUNNING_STATUS_EVT_MASK BIT(2) -#define ESP_BLE_VENDOR_SLEEP_WAKEUP_EVT_MASK BIT(3) -#define ESP_BLE_VENDOR_CONNECT_IND_REQ_EVT_MASK BIT(4) -#define ESP_BLE_VENDOR_AUX_CONNECT_RSP_EVT_MASK BIT(5) - -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) -#ifdef CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT -#define MAX_REATTEMPT_ALLOWED CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT -#else -#define MAX_REATTEMPT_ALLOWED 0 -#endif -#endif - -/** - * Configure LE Data Length in controller (OGF = 0x08, OCF = 0x0022). - * - * @param conn_handle Connection handle. - * @param tx_octets The preferred value of payload octets that the Controller - * should use for a new connection (Range - * 0x001B-0x00FB). - * @param tx_time The preferred maximum number of microseconds that the local Controller - * should use to transmit a single link layer packet - * (Range 0x0148-0x4290). - * - * @return 0 on success, - * other error code on failure. - */ -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); - -/** - * Removes the address from controller's white list. - * - * @param addrs The entry to be removed from the white list. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_wl_tx_rmv(const ble_addr_t *addrs); - -/** - * Adds the address in controller's white list. - * - * @param addrs The entry to be added in the white list. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_wl_tx_add(const ble_addr_t *addrs); - -/** - * Clears all addresses from controller's white list. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_wl_tx_clear(void); - -/** - * Retrieves the size of the controller's white list. - * - * @param size On success, total size of whitelist will be stored here. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_wl_read_size(uint8_t *size); - -/** - * This API gives the current status of various stack operations - * - * @return 0 on success; nonzero bits indicating different - * operations as per enum gap_status. - */ -int ble_gap_host_check_status(void); - -/** - * This API is called to get local used address and address type. - * - * @param addr On success, locally used address will be stored here. - * - * @return 0 on success; nonzero on failure. -*/ -int ble_gap_get_local_used_addr(ble_addr_t *addr); - -/** - * This API is called to get ADV data for a specific type. - - * - * @param adv_data Pointer of ADV data which to be resolved. - * @param adv_type Finding ADV data type. - * @param adv_data_len Total length of Advertising data. - * @param length Return the length of ADV data not including type. - * - * @return Pointer of type specific ADV data. - */ -uint8_t* ble_resolve_adv_data(const uint8_t *adv_data, uint8_t adv_type, uint8_t adv_data_len , uint8_t * length); - -#if MYNEWT_VAL(BLE_HCI_VS) -#if MYNEWT_VAL(BLE_POWER_CONTROL) - -#define ESP_1M_LOW (-70) -#define ESP_1M_HIGH (-60) -#define ESP_2M_LOW (-68) -#define ESP_2M_HIGH (-58) -#define ESP_S2_LOW (-75) -#define ESP_S2_HIGH (-65) -#define ESP_S8_LOW (-80) -#define ESP_S8_HIGH (-70) -#define ESP_MIN_TIME (15) - -/* Represents the set of lower / upper values of rssi of given chip - * - * Lower Limit Values Range: -54 to -80 - * Upper Limit Values Range: -40 to -70 - * - * */ -struct ble_gap_set_auto_pcl_params { - - /* Connection Handle of the ACL Link */ - int16_t conn_handle; - - /* The Lower RSSI limit when 1M phy is used */ - int8_t m1_lower_limit; - - /* The Upper RSSI limit when 1M phy is used */ - int8_t m1_upper_limit; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - /* The Lower RSSI limit when 2M phy is used */ - int8_t m2_lower_limit; - - /* The Upper RSSI limit when 2M phy is used */ - int8_t m2_upper_limit; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* The Lower RSSI limit when S2 Coded phy is used */ - int8_t s2_lower_limit; - - /* The Upper RSSI limit when S2 Coded phy is used */ - int8_t s2_upper_limit; - - /* The Lower RSSI limit when S8 Coded phy is used */ - int8_t s8_lower_limit; - - /* The Upper RSSI limit when S8 Coded phy is used */ - int8_t s8_upper_limit; -#endif - - /* Number of tx/rx packets to wait before initiating the LE power control Request. - * The default value is (min time spent variable = (tx/rxpackets 15)).*/ - uint8_t min_time_spent; -}; - -/** - * This API is used to initiate the LE Power Control Request Procedure for the ACL connection - * identified by the conn_handle parameter and other parameters. - * - * The parameters passed are used by controller for the subsquent LE Power Control Requests - * that get initiated across all the connections. - * - * The Min_Time_Spent parameter indicates the number of tx/rx packets that the Controller - * shall observe the RSSI has crossed the threshold (upper and lower limit of active phy) - * before the controller initiates the LE POWER CONTROL PROCEDURE in the link layer. - * - * @param params Instance of ble_gap_set_auto_pcl_params with different parameters - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_set_auto_pcl_param(struct ble_gap_set_auto_pcl_params *params); -#endif - -/** - * This API is used to send the Duplicate Exception list VSC to controller - * - * @param subcode The operation to be done (add/remove/clean) - * - * @param type Exception list type - * - * @param value Device address - * - * @cb Registered callback - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_duplicate_exception_list(uint8_t subcode, uint8_t type, uint8_t *value, void *cb); - -/** - * This API is used to clean up residue memory in controller for legacy advertisement - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_clear_legacy_adv(void); - -/** - * This API is used to let controller know which CSA to use. Not applicable for ESP32 - * - * @return 0 on success; nonzero of failure. - */ -int ble_gap_set_chan_select(uint8_t select); - -#endif - -/** - * Authorizes or deauthorizes a BLE device for a connection. - * - * This function updates the security flags of a BLE connection to authorize or - * deauthorize a device for the specified connection. - * - * @param conn_handle The handle corresponding to the connection to - * authorize. - * @param authorized Authorized the device or not. - * - * @return 0 on success; - * BLE_HS_ENOTCONN if the connection handle is not found. - * BLE_HS_EAUTHOR if the device is not authenticated before authorization. - */ -int -ble_gap_dev_authorization(uint16_t conn_handle, bool authorized); - -/** - * Sets the vendor-specific event mask for BLE host. - * - * This function configures the vendor-specific event mask, enabling or disabling - * specific vendor-defined events from being reported by the controller. - * - * @param event_mask Bitmask representing the events to enable. - * - * @return 0 on success; - * A nonzero value indicating an error if the command fails. - */ -int -ble_hs_send_vs_event_mask(uint32_t event_mask); - -void ble_gap_rx_test_evt(const void *buf, uint8_t len); -void ble_gap_tx_test_evt(const void *buf, uint8_t len); -void ble_gap_end_test_evt(const void *buf, uint8_t len); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/nimble/nimble/host/include/host/ble_esp_gatt.h b/src/nimble/nimble/host/include/host/ble_esp_gatt.h deleted file mode 100644 index aa93090ec..000000000 --- a/src/nimble/nimble/host/include/host/ble_esp_gatt.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#ifndef H_BLE_ESP_GATT_ -#define H_BLE_ESP_GATT_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Resets the GATT configuration parameters and deallocates the memory of attributes. - * - */ -void ble_gatts_stop(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/nimble/nimble/host/include/host/ble_esp_hs.h b/src/nimble/nimble/host/include/host/ble_esp_hs.h deleted file mode 100644 index f381816d0..000000000 --- a/src/nimble/nimble/host/include/host/ble_esp_hs.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#ifndef H_BLE_ESP_HS_ -#define H_BLE_ESP_HS_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Deinitializes the NimBLE host. This function must be called after the - * NimBLE host stop procedure is complete. - */ -void ble_hs_deinit(void); - -#if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) -/** - * Initializes the Bluetooth advertising list and associated mutex lock. - */ -void ble_adv_list_init(void); - -/** - * Deinitializes the Bluetooth advertising list, releasing allocated memory and resources. - */ -void ble_adv_list_deinit(void); - -/** - * Adds a Bluetooth advertising packet to the list. - */ -void ble_adv_list_add_packet(void *data); - -/** - * Returns the count of Bluetooth advertising packets in the list. - */ -uint32_t ble_get_adv_list_length(void); - -/** - * Clears and refreshes the Bluetooth advertising list. - */ -void ble_adv_list_refresh(void); - -/** - * Checks if a Bluetooth address is present in the advertising list; if not, adds it to the list. - */ -bool ble_check_adv_list(const uint8_t *addr, uint8_t addr_type); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/nimble/nimble/host/include/host/ble_gap.h b/src/nimble/nimble/host/include/host/ble_gap.h index 442abafa5..aac89c87f 100644 --- a/src/nimble/nimble/host/include/host/ble_gap.h +++ b/src/nimble/nimble/host/include/host/ble_gap.h @@ -31,11 +31,6 @@ #include "nimble/nimble/host/include/host/ble_hs.h" #include "nimble/nimble/host/include/host/ble_hs_adv.h" #include "syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_esp_gap.h" - -#if MYNEWT_VAL(ENC_ADV_DATA) -#include "nimble/nimble/host/src/ble_hs_hci_priv.h" -#endif #ifdef __cplusplus extern "C" { @@ -44,31 +39,44 @@ extern "C" { struct hci_le_conn_complete; struct hci_conn_update; +/** + * @defgroup ble_gap_ms_convert Generic Access Profile (GAP) Time Conversion Macros + * @{ + */ + +/** Convert advertising interval from milliseconds to BLE HCI units. */ #define BLE_GAP_ADV_ITVL_MS(t) ((t) * 1000 / BLE_HCI_ADV_ITVL) + +/** Convert scan interval from milliseconds to BLE HCI units. */ #define BLE_GAP_SCAN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL) + +/** Convert scan window from milliseconds to BLE HCI units. */ #define BLE_GAP_SCAN_WIN_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL) + +/** Convert connection interval from milliseconds to BLE HCI units. */ #define BLE_GAP_CONN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_CONN_ITVL) + +/** Convert supervision timeout from milliseconds to BLE HCI units. */ #define BLE_GAP_SUPERVISION_TIMEOUT_MS(t) ((t) / 10) + +/** Convert periodic advertising interval from milliseconds to BLE HCI units. */ #define BLE_GAP_PERIODIC_ITVL_MS(t) ((t) * 1000 / BLE_HCI_PERIODIC_ADV_ITVL) -#if MYNEWT_VAL(BLE_HIGH_DUTY_ADV_ITVL) -/** 5 ms. */ -#define BLE_GAP_ADV_FAST_INTERVAL1_MIN BLE_GAP_ADV_ITVL_MS(5) -#else +/** @} */ + +/** + * @defgroup ble_gap_intervals Generic Access Profile (GAP) Intervals and Durations + * @{ + */ + /** 30 ms. */ #define BLE_GAP_ADV_FAST_INTERVAL1_MIN BLE_GAP_ADV_ITVL_MS(30) -#endif /** 60 ms. */ #define BLE_GAP_ADV_FAST_INTERVAL1_MAX BLE_GAP_ADV_ITVL_MS(60) -#if MYNEWT_VAL(BLE_HIGH_DUTY_ADV_ITVL) -/** 5 ms. */ -#define BLE_GAP_ADV_FAST_INTERVAL2_MIN BLE_GAP_ADV_ITVL_MS(5) -#else /** 100 ms. */ #define BLE_GAP_ADV_FAST_INTERVAL2_MIN BLE_GAP_ADV_ITVL_MS(100) -#endif /** 150 ms. */ #define BLE_GAP_ADV_FAST_INTERVAL2_MAX BLE_GAP_ADV_ITVL_MS(150) @@ -88,7 +96,7 @@ struct hci_conn_update; /** 30 ms; active scanning. */ #define BLE_GAP_SCAN_FAST_WINDOW BLE_GAP_SCAN_WIN_MS(30) -/* 30.72 seconds; active scanning. */ +/** 30.72 seconds; active scanning. */ #define BLE_GAP_SCAN_FAST_PERIOD BLE_GAP_SCAN_ITVL_MS(30.72) /** 1.28 seconds; background scanning. */ @@ -109,75 +117,156 @@ struct hci_conn_update; /** 5 seconds. */ #define BLE_GAP_CONN_PAUSE_PERIPHERAL (5 * 1000) -/* 30 ms. */ +/** 30 ms. */ #define BLE_GAP_INITIAL_CONN_ITVL_MIN BLE_GAP_CONN_ITVL_MS(30) -/* 50 ms. */ +/** 50 ms. */ #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 +/** + * @defgroup ble_gap_initial_conn_params Generic Access Profile (GAP) Initial Connection Parameters + * @{ + */ + +/** Initial connection latency. */ #define BLE_GAP_INITIAL_CONN_LATENCY 0 + +/** Initial supervision timeout. */ #define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100 + +/** Initial minimum connection event length. */ #define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0000 + +/** Initial maximum connection event length. */ #define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0000 +/** @} */ + +/** + * @defgroup ble_gap_roles Generic Access Profile (GAP) Roles + * @{ + */ + +/** GAP role: Master */ #define BLE_GAP_ROLE_MASTER 0 + +/** GAP role: Slave */ #define BLE_GAP_ROLE_SLAVE 1 +/** @} */ + +/** + * @defgroup ble_gap_events Generic Access Profile (GAP) Events + * @{ + */ + +/** GAP event: Connection established */ #define BLE_GAP_EVENT_CONNECT 0 + +/** GAP event: Connection terminated */ #define BLE_GAP_EVENT_DISCONNECT 1 + +/** GAP event: Reserved for future use */ /* Reserved 2 */ + +/** GAP event: Connection update */ #define BLE_GAP_EVENT_CONN_UPDATE 3 + +/** GAP event: Connection update request */ #define BLE_GAP_EVENT_CONN_UPDATE_REQ 4 + +/** GAP event: L2CAP update request */ #define BLE_GAP_EVENT_L2CAP_UPDATE_REQ 5 + +/** GAP event: Termination failure */ #define BLE_GAP_EVENT_TERM_FAILURE 6 + +/** GAP event: Discovery event */ #define BLE_GAP_EVENT_DISC 7 + +/** GAP event: Discovery complete */ #define BLE_GAP_EVENT_DISC_COMPLETE 8 + +/** GAP event: Advertising complete */ #define BLE_GAP_EVENT_ADV_COMPLETE 9 + +/** GAP event: Encryption change */ #define BLE_GAP_EVENT_ENC_CHANGE 10 + +/** GAP event: Passkey action */ #define BLE_GAP_EVENT_PASSKEY_ACTION 11 + +/** GAP event: Notification received */ #define BLE_GAP_EVENT_NOTIFY_RX 12 + +/** GAP event: Notification transmitted */ #define BLE_GAP_EVENT_NOTIFY_TX 13 + +/** GAP event: Subscription */ #define BLE_GAP_EVENT_SUBSCRIBE 14 + +/** GAP event: MTU event */ #define BLE_GAP_EVENT_MTU 15 + +/** GAP event: Identity resolved */ #define BLE_GAP_EVENT_IDENTITY_RESOLVED 16 + +/** GAP event: Repeat pairing */ #define BLE_GAP_EVENT_REPEAT_PAIRING 17 + +/** GAP event: PHY update complete */ #define BLE_GAP_EVENT_PHY_UPDATE_COMPLETE 18 + +/** GAP event: Extended discovery */ #define BLE_GAP_EVENT_EXT_DISC 19 + +/** GAP event: Periodic synchronization */ #define BLE_GAP_EVENT_PERIODIC_SYNC 20 + +/** GAP event: Periodic report */ #define BLE_GAP_EVENT_PERIODIC_REPORT 21 + +/** GAP event: Periodic synchronization lost */ #define BLE_GAP_EVENT_PERIODIC_SYNC_LOST 22 + +/** GAP event: Scan request received */ #define BLE_GAP_EVENT_SCAN_REQ_RCVD 23 + +/** GAP event: Periodic transfer */ #define BLE_GAP_EVENT_PERIODIC_TRANSFER 24 + +/** GAP event: Pathloss threshold */ #define BLE_GAP_EVENT_PATHLOSS_THRESHOLD 25 + +/** GAP event: Transmit power */ #define BLE_GAP_EVENT_TRANSMIT_POWER 26 -#define BLE_GAP_EVENT_PARING_COMPLETE 27 + +/** GAP event: Pairing complete */ +#define BLE_GAP_EVENT_PAIRING_COMPLETE 27 + +/** GAP event: Pairing complete (deprecated) */ +#define BLE_GAP_EVENT_PARING_COMPLETE BLE_GAP_EVENT_PAIRING_COMPLETE + +/** GAP event: Subrate change */ #define BLE_GAP_EVENT_SUBRATE_CHANGE 28 -#define BLE_GAP_EVENT_VS_HCI 29 + +/** GAP event: Unhandled HCI event */ +#define BLE_GAP_EVENT_UNHANDLED_HCI_EVENT 29 + +/** GAP event: BIG (Broadcast Isochronous Group) information report */ #define BLE_GAP_EVENT_BIGINFO_REPORT 30 -#define BLE_GAP_EVENT_REATTEMPT_COUNT 31 -#define BLE_GAP_EVENT_AUTHORIZE 32 -#define BLE_GAP_EVENT_TEST_UPDATE 33 -#define BLE_GAP_EVENT_DATA_LEN_CHG 34 -#define BLE_GAP_EVENT_CONNLESS_IQ_REPORT 35 -#define BLE_GAP_EVENT_CONN_IQ_REPORT 36 -#define BLE_GAP_EVENT_CTE_REQ_FAILED 37 - -//TODO : Deprecate the EVENT_LINK_ESTAB going ahead -#define BLE_GAP_EVENT_LINK_ESTAB 38 -#define BLE_GAP_EVENT_EATT 39 -#define BLE_GAP_EVENT_PER_SUBEV_DATA_REQ 40 -#define BLE_GAP_EVENT_PER_SUBEV_RESP 41 -#define BLE_GAP_EVENT_PERIODIC_TRANSFER_V2 42 - -/* DTM events */ -#define BLE_GAP_DTM_TX_START_EVT 0 -#define BLE_GAP_DTM_RX_START_EVT 1 -#define BLE_GAP_DTM_END_EVT 2 - -/*** Reason codes for the subscribe GAP event. */ + +/** @} */ + +/** + * @defgroup ble_gap_subscribe_reasons Generic Access Profile (GAP) Subscribe Event Reason Codes + * @{ + */ /** Peer's CCCD subscription state changed due to a descriptor write. */ #define BLE_GAP_SUBSCRIBE_REASON_WRITE 1 @@ -191,24 +280,20 @@ struct hci_conn_update; */ #define BLE_GAP_SUBSCRIBE_REASON_RESTORE 3 -#define BLE_GAP_REPEAT_PAIRING_RETRY 1 -#define BLE_GAP_REPEAT_PAIRING_IGNORE 2 +/** @} */ /** - * @defgroup Mask for checking random address validity + * @defgroup ble_gap_repeat_pairing_options Generic Access Profile (GAP) Repeat Pairing Options * @{ */ -/** Static random address check mask. */ -#define BLE_STATIC_RAND_ADDR_MASK 0xC0 -/** Non RPA check mask. */ -#define BLE_NON_RPA_MASK 0x3F +/** GAP repeat pairing option: Retry the pairing procedure. */ +#define BLE_GAP_REPEAT_PAIRING_RETRY 1 -/** @} */ +/** GAP repeat pairing option: Ignore the pairing procedure. */ +#define BLE_GAP_REPEAT_PAIRING_IGNORE 2 -/* Response values for gatt read/write authorization event */ -#define BLE_GAP_AUTHORIZE_ACCEPT 1 -#define BLE_GAP_AUTHORIZE_REJECT 2 +/** @} */ /** Connection security state */ struct ble_gap_sec_state { @@ -223,21 +308,6 @@ struct ble_gap_sec_state { /** Size of a key used for encryption */ unsigned key_size:5; - - /** Current device security state*/ - unsigned authorize:1; -}; - -/** Read Remote Version parameters **/ -struct ble_gap_read_rem_ver_params { - /** Version of the Current LMP **/ - uint8_t version; - - /** Company Identifier **/ - uint16_t manufacturer; - - /** Revision of the LMP **/ - uint16_t subversion; }; /** Advertising parameters */ @@ -507,84 +577,55 @@ struct ble_gap_disc_desc { ble_addr_t direct_addr; }; +/** + * Represents a repeat pairing operation between two devices. + * + * This structure contains information about a repeat pairing operation between + * two devices. The host can use this information to determine whether it needs + * to initiate a pairing procedure with a remote device again. + */ struct ble_gap_repeat_pairing { /** The handle of the relevant connection. */ uint16_t conn_handle; /** Properties of the existing bond. */ + /** The size of the current encryption key in octets. */ uint8_t cur_key_size; + + /** A flag indicating whether the current connection is authenticated. */ uint8_t cur_authenticated:1; + + /** + * A flag indicating whether the current connection is using secure + * connections. + */ uint8_t cur_sc:1; /** * Properties of the imminent secure link if the pairing procedure is * allowed to continue. */ - uint8_t new_key_size; - uint8_t new_authenticated:1; - uint8_t new_sc:1; - uint8_t new_bonding:1; -}; - -#define BLE_GAP_PER_ADV_DATA_STATUS_COMPLETE 0x00 -#define BLE_GAP_PER_ADV_DATA_STATUS_INCOMPLETE 0x01 -#define BLE_GAP_PER_ADV_DATA_STATUS_TRUNCATED 0x02 -#define BLE_GAP_PER_ADV_DATA_STATUS_RX_FAILED 0xFF - -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) -struct ble_gap_periodic_adv_response { - /** The subevent in which the response is received */ - uint8_t subevent; + /** The size of the imminent encryption key in octets. */ + uint8_t new_key_size; - /** Status of the subevent indication. - * - * 0 if subevent indication was transmitted. - * 1 if subevent indication was not transmitted. - * All other values RFU. + /** + * A flag indicating whether the imminent connection will be authenticated. */ + uint8_t new_authenticated:1; - /** The adv handle of the adv */ - uint8_t adv_handle; - - uint8_t tx_status; - - /** The TX power of the response in dBm */ - int8_t tx_power; - - /** The RSSI of the response in dBm */ - int8_t rssi; - - /** The Constant Tone Extension (CTE) of the advertisement */ - uint8_t cte_type; - - /** The response slot */ - uint8_t response_slot; - - /** Data status */ - uint8_t data_status; - - /** Data length */ - uint8_t data_length; - - /** response data */ - const uint8_t *data; -}; - -struct ble_gap_periodic_adv_response_params { - /** The periodic advertsing event for which response shall be sent in */ - uint16_t request_event; - - /** The request subevent for which response shall be sent in */ - uint8_t request_subevent; - - /** The subevent the response shall be sent in */ - uint8_t response_subevent; + /** + * A flag indicating whether the imminent connection will use secure + * connections. + */ + uint8_t new_sc:1; - /** The response slot the response shall be sent in */ - uint8_t response_slot; + /** + * A flag indicating whether the pairing procedure will result in a new + * bonding, + */ + uint8_t new_bonding:1; }; -#endif /** * Represents a GAP-related event. When such an event occurs, the host @@ -619,63 +660,8 @@ struct ble_gap_event { /** The handle of the relevant connection. */ uint16_t conn_handle; -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) - /* - * Adv_Handle is used to identify an advertising set. - * If the connection is established from periodic advertising with responses - * and Role is 0x00 then the Advertising_Handle parameter shall be set - * according to the periodic advertising train the connection was established from - */ - uint8_t adv_handle; - - /* - * Sync_Handle identifying the periodic advertising train - * If the connection is established from periodic advertising with responses - * and Role is 0x01, then the Sync_Handle parameter shall be set according - * to the periodic advertising train the connection was established from - */ - uint16_t sync_handle; -#endif } connect; - /** - * Represents a successful Link establishment attempt. Sometimes, in noisy environment, - * even if BLE_GAP_EVENT_CONNECT is posted, the link syncronization procedure may fail - * and link gets disconnected with reason 0x3E. Application can wait for below event to ensure - * the link syncronization is completed. Valid for the following event - * types: - * o BLE_GAP_EVENT_LINK_ESTAB - */ - - struct { - /** - * The final status of the link establishment; - * o 0: the connection was successfully established. - * o BLE host error code: the connection attempt failed for - * the specified reason. - */ - int status; - - /** The handle of the relevant connection. */ - uint16_t conn_handle; -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) - /* - * Adv_Handle is used to identify an advertising set. - * If the connection is established from periodic advertising with responses - * and Role is 0x00 then the Advertising_Handle parameter shall be set - * according to the periodic advertising train the connection was established from - */ - uint8_t adv_handle; - /* - * Sync_Handle identifying the periodic advertising train - * If the connection is established from periodic advertising with responses - * and Role is 0x01, then the Sync_Handle parameter shall be set according - * to the periodic advertising train the connection was established from - */ - uint16_t sync_handle; -#endif - } link_estab; - /** * Represents a terminated connection. Valid for the following event * types: @@ -1058,18 +1044,6 @@ struct ble_gap_event { /** Advertiser clock accuracy */ uint8_t adv_clk_accuracy; -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) - /** Number of subevents. If zero, the periodic advertiser will be a broadcaster, - * without responses. - */ - uint8_t num_subevents; - /** Interval between subevents (N * 1.25 ms) */ - uint8_t subevent_interval; - /** Time between the advertising packet and the first response slot (N * 1.25 ms). */ - uint8_t response_slot_delay; - /** Time between response slots (N * 0.125 ms) */ - uint8_t response_slot_spacing; -#endif } periodic_sync; /** @@ -1087,24 +1061,10 @@ struct ble_gap_event { /** Received signal strength indication in dBm (127 if unavailable) */ int8_t rssi; -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) - /** - * It indicates the periodic advertising event counter (paEventCounter) of - * the event that the periodic advertising packet was received in. - */ - uint16_t event_counter; - /** - * It indicates Periodic Advertising with Responses subevent in which - * the periodic advertising packet was received in. - */ - uint8_t subevent; -#endif - /** Advertising data status, can be one of following constants: * - BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE * - BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE * - BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED - * - BLE_HCI_PERIODIC_DATA_STATUS_RX_FAILED */ uint8_t data_status; @@ -1186,18 +1146,6 @@ struct ble_gap_event { /** Advertiser clock accuracy */ uint8_t adv_clk_accuracy; -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) - /** Number of subevents. If zero, the periodic advertiser will be a broadcaster,- - * without responses. - */ - uint8_t num_subevents; - /** Interval between subevents (N * 1.25 ms) */ - uint8_t subevent_interval; - /** Time between the advertising packet and the first response slot (N * 1.25 ms). */ - uint8_t response_slot_delay; - /** Time between response slots (N * 0.125 ms) */ - uint8_t response_slot_spacing; -#endif } periodic_transfer; #endif @@ -1286,21 +1234,22 @@ struct ble_gap_event { /** Advertising PHY */ uint8_t phy; - /** Transmit power Level */ - int8_t transmit_power_level; + /** Transmit power Level */ + int8_t transmit_power_level; /** Transmit Power Level Flag */ uint8_t transmit_power_level_flag; - /** Delta indicating change in transmit Power Level */ - int8_t delta; + /** Delta indicating change in transmit Power Level */ + int8_t delta; } transmit_power; #endif /** * Represents a received Pairing Complete message * * Valid for the following event types: - * o BLE_GAP_EVENT_PARING_COMPLETE + * o BLE_GAP_EVENT_PAIRING_COMPLETE + * o BLE_GAP_EVENT_PARING_COMPLETE (deprecated) */ struct { /** @@ -1342,401 +1291,89 @@ struct ble_gap_event { uint16_t supervision_tmo; } subrate_change; #endif -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) - /** - * Represents a periodic advertising subevent data request - * with parameters valid for the following event types: - * o BLE_GAP_EVENT_PER_SUBEV_DATA_REQ - */ - struct { - /** Advertising handle */ - uint8_t adv_handle; - - /** Subevent start */ - uint8_t subevent_start; - - /** Number of subevents */ - uint8_t subevent_data_count; - } periodic_adv_subev_data_req; - - /** - * Represents a periodic advertising response - * with parameters valid for the following event types: - * o BLE_GAP_EVENT_PER_SUBEV_RESP - */ - struct ble_gap_periodic_adv_response periodic_adv_response; -#endif -#if MYNEWT_VAL(BLE_HCI_VS) +#if MYNEWT_VAL(BLE_HS_GAP_UNHANDLED_HCI_EVENT) /** - * Represents a received vendor-specific HCI event + * Represents an HCI event received from controller that is not handled + * by the host. The event may be a regular event, LE meta event or + * vendor specific event which is denoted by included flags. * * Valid for the following event types: - * o BLE_GAP_EVENT_VS_HCI + * o BLE_GAP_EVENT_UNHANDLED_HCI_EVENT */ struct { + bool is_le_meta; + bool is_vs; const void *ev; uint8_t length; - } vs_hci; -#endif - - /** - * GATT Authorization Event. Ask the user to authorize a GATT - * read/write operation. - * - * Valid for the following event types: - * o BLE_GAP_EVENT_AUTHORIZE - * - * Valid responses from user: - * o BLE_GAP_AUTHORIZE_ACCEPT - * o BLE_GAP_AUTHORIZE_REJECT - */ - struct { - /* Connection Handle */ - uint16_t conn_handle; - - /* Attribute handle of the attribute being accessed. */ - uint16_t attr_handle; - - /* Weather the operation is a read or write operation. */ - int is_read; - - /* User's response */ - int out_response; - } authorize; - -#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 - /** - * EATT Event - * - * Valid for the following event types: - * o BLE_GAP_EVENT_EATT - * - */ - struct { - /* Connection Handle */ - uint16_t conn_handle; - - /** Connected Status - * - * EATT Connected: 0 - * EATT Disconnected: 1 - */ - uint8_t status; - - /* CID of the bearer */ - uint16_t cid; - - } eatt; + } unhandled_hci; #endif + }; +}; -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) - /** - * Represents a event mentioning connection reattempt - * count - * - * Valid for the following event types: - * o BLE_GAP_EVENT_REATTEMPT_COUNT - */ - struct { - /* Connection handle */ - uint16_t conn_handle; +/** Callback function type for handling BLE GAP events. */ +typedef int ble_gap_event_fn(struct ble_gap_event *event, void *arg); - /* Reattempt connection attempt count */ - uint8_t count; - } reattempt_cnt; -#endif - /** - * Represent a event for DTM test results - * - * Valid for the following event types: - * o BLE_GAP_EVENT_TEST_UPDATE - */ - struct { - /* Indicate DTM operation status */ - uint8_t status; +/** Callback function type for iterating through BLE connection handles. */ +typedef int ble_gap_conn_foreach_handle_fn(uint16_t conn_handle, void *arg); - /* DTM state change event. Can be following constants: - * o BLE_GAP_DTM_TX_START_EVT - * o BLE_GAP_DTM_RX_START_EVT - * o BLE_GAP_DTM_END_EVT - */ - uint8_t update_evt; - - /* Number of packets received. - * - * Valid only for BLE_GAP_DTM_END_EVT - * shall be 0 for a transmitter. - */ - uint16_t num_pkt; - } dtm_state; - /** - * Represent an event for LE Data length change - * - * Valid for the following event types: - * o BLE_GAP_EVENT_DATA_LEN_CHG - */ - struct { - /* Connection handle */ - uint16_t conn_handle; +/** + * @defgroup ble_gap_advertising_modes Generic Access Profile (GAP) Advertising Modes + * @{ + */ - /* Max Tx Payload octotes */ - uint16_t max_tx_octets; +/** Non-connectable mode for advertising. */ +#define BLE_GAP_CONN_MODE_NON 0 - /* Max Tx Time */ - uint16_t max_tx_time; +/** Directed connectable mode for advertising. */ +#define BLE_GAP_CONN_MODE_DIR 1 - /* Max Rx payload octet */ - uint16_t max_rx_octets; +/** Undirected connectable mode for advertising. */ +#define BLE_GAP_CONN_MODE_UND 2 - /* Max Rx Time */ - uint16_t max_rx_time; - } data_len_chg; -#if MYNEWT_VAL(BLE_AOA_AOD) - /** - * Represents a AOA/AOD connectionless iq report event - * Valid for the following event types: - * o BLE_GAP_EVENT_CONNLESS_IQ_RPT - */ - struct { - /** Sync_Handle identifying the periodic advertising train. - * Range: 0x0000 to 0x0EFF - * 0x0FFF indicates Receiver Test mode. - */ - uint16_t sync_handle; - /** The index of the channel on which the packet was received. - * Range: 0x00 to 0x27 - * Note: 0x25 to 0x27 can be used only for packets generated during test modes. - */ - uint8_t channel_index; +/** Non-discoverable mode for advertising. */ +#define BLE_GAP_DISC_MODE_NON 0 - /** RSSI of the packet. - * Range: -1270 to +200 (Units: 0.1 dBm). - */ - int16_t rssi; +/** Limited discoverable mode for advertising. */ +#define BLE_GAP_DISC_MODE_LTD 1 - /** Antenna ID used for receiving the packet. */ - uint8_t rssi_antenna_id; +/** General discoverable mode for advertising. */ +#define BLE_GAP_DISC_MODE_GEN 2 - /** Type of Constant Tone Extension (CTE). - * 0x00: AoA Constant Tone Extension - * 0x01: AoD Constant Tone Extension with 1 μs slots - * 0x02: AoD Constant Tone Extension with 2 μs slots - */ - uint8_t cte_type; +/** @} */ - /** Switching and sampling slot durations. - * 0x01: Switching and sampling slots are 1 μs each - * 0x02: Switching and sampling slots are 2 μs each - */ - uint8_t slot_durations; - /** Status of the packet. - * 0x00: CRC was correct - * 0x01: CRC was incorrect, but Length and CTETime fields were used to determine sampling points - * 0x02: CRC was incorrect, but the Controller determined the position and length of the CTE in another way - * 0xFF: Insufficient resources to sample (Channel_Index, CTE_Type, and Slot_Durations invalid) - */ - uint8_t packet_status; +/** + * Searches for a connection with the specified handle. If a matching + * connection is found, the supplied connection descriptor is filled + * correspondingly. + * + * @param handle The connection handle to search for. + * @param out_desc On success, this is populated with information relating to + * the matching connection. Pass NULL if you don't need this + * information. + * + * @return 0 on success, BLE_HS_ENOTCONN if no matching connection was + * found. + */ +int ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc); - /** Value of paEventCounter for the reported AUX_SYNC_IND PDU. */ - uint16_t periodic_event_counter; - - /** Total number of sample pairs (I and Q samples). - * 0x00: No samples provided (only permitted if Packet_Status is 0xFF) - * 0x09 to 0x52: Total number of sample pairs - */ - uint8_t sample_count; - - /** Array of I samples for the reported packet (signed integers). - * Each value represents an I sample at a specific sampling point. - * 0x80 indicates no valid sample available. - */ - int8_t *i_samples; - - /** Array of Q samples for the reported packet (signed integers). - * Each value represents a Q sample at a specific sampling point. - * 0x80 indicates no valid sample available. - */ - int8_t *q_samples; - } connless_iq_report; - - /** - * Represents a connection iq report. - * Valid for the following event types: - * o BLE_GAP_EVENT_CONN_IQ_RPT - */ - struct { - /** Connection handle identifying the connection. */ - uint16_t conn_handle; - - /** PHY used for receiving the packet. - * 0x01: LE 1M PHY - * 0x02: LE 2M PHY - */ - uint8_t rx_phy; - - /** The index of the data channel on which the packet was received. */ - uint8_t data_channel_index; - - /** RSSI of the packet. - * Range: -1270 to +200 (Units: 0.1 dBm). - */ - int16_t rssi; - - /** Antenna ID used for receiving the packet. */ - uint8_t rssi_antenna_id; - - /** Type of Constant Tone Extension (CTE). - * 0x00: AoA Constant Tone Extension - * 0x01: AoD Constant Tone Extension with 1 μs slots - * 0x02: AoD Constant Tone Extension with 2 μs slots - */ - uint8_t cte_type; - - /** Switching and sampling slot durations. - * 0x01: Switching and sampling slots are 1 μs each - * 0x02: Switching and sampling slots are 2 μs each - */ - uint8_t slot_durations; - - /** Status of the packet. - * 0x00: CRC was correct - * 0x01: CRC was incorrect, but Length and CTETime fields were used to determine sampling points - * 0x02: CRC was incorrect, but the Controller determined the position and length of the CTE in another way - * 0xFF: Insufficient resources to sample (Channel_Index, CTE_Type, and Slot_Durations invalid) - */ - uint8_t packet_status; - - /** Value of the connection event counter for the reported packet. */ - uint16_t conn_event_counter; - - /** Total number of sample pairs (I and Q samples). - * 0x00: No samples provided (only permitted if Packet_Status is 0xFF) - * 0x09 to 0x52: Total number of sample pairs - */ - uint8_t sample_count; - - /** Array of I samples for the reported packet (signed integers). - * Each value represents an I sample at a specific sampling point. - * 0x80 indicates no valid sample available. - */ - int8_t *i_samples; - - /** Array of Q samples for the reported packet (signed integers). - * Each value represents a Q sample at a specific sampling point. - * 0x80 indicates no valid sample available. - */ - int8_t *q_samples; - } conn_iq_report; - - /** - * Represents a cte req failed event - * Valid for the following event types: - * o BLE_GAP_EVENT_CTE_REQ_FAILED - */ - struct { - /** Status indicating the reason for failure. - * Refer to HCI error codes for detailed status values. - */ - uint8_t status; - - /** Connection handle identifying the connection. */ - uint16_t conn_handle; - } cte_req_fail; - -#endif - }; -}; - -#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN) -/** @brief multiple Connection parameters */ -struct ble_gap_multi_conn_params { - /** The type of address the stack should use for itself. */ - uint8_t own_addr_type; - -#if MYNEWT_VAL(BLE_EXT_ADV) - /** Define on which PHYs connection attempt should be done */ - uint8_t phy_mask; -#endif // MYNEWT_VAL(BLE_EXT_ADV) - - /** The address of the peer to connect to. */ - const ble_addr_t *peer_addr; - - /** The duration of the discovery procedure. */ - int32_t duration_ms; - - /** - * Additional arguments specifying the particulars of the connect procedure. When extended - * adv is disabled or BLE_GAP_LE_PHY_1M_MASK is set in phy_mask this parameter can't be - * specified to null. - */ - const struct ble_gap_conn_params *phy_1m_conn_params; - -#if MYNEWT_VAL(BLE_EXT_ADV) - /** - * Additional arguments specifying the particulars of the connect procedure. When - * BLE_GAP_LE_PHY_2M_MASK is set in phy_mask this parameter can't be specified to null. - */ - const struct ble_gap_conn_params *phy_2m_conn_params; - - /** - * Additional arguments specifying the particulars of the connect procedure. When - * BLE_GAP_LE_PHY_CODED_MASK is set in phy_mask this parameter can't be specified to null. - */ - const struct ble_gap_conn_params *phy_coded_conn_params; -#endif // MYNEWT_VAL(BLE_EXT_ADV) - - /** - * The minimum length occupied by this connection in scheduler. 0 means disable the - * optimization for this connection. - */ - uint32_t scheduling_len_us; -}; -#endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN) - -typedef int ble_gap_event_fn(struct ble_gap_event *event, void *arg); -typedef int ble_gap_conn_foreach_handle_fn(uint16_t conn_handle, void *arg); - -#define BLE_GAP_CONN_MODE_NON 0 -#define BLE_GAP_CONN_MODE_DIR 1 -#define BLE_GAP_CONN_MODE_UND 2 - -#define BLE_GAP_DISC_MODE_NON 0 -#define BLE_GAP_DISC_MODE_LTD 1 -#define BLE_GAP_DISC_MODE_GEN 2 - -/** - * Searches for a connection with the specified handle. If a matching - * connection is found, the supplied connection descriptor is filled - * correspondingly. - * - * @param handle The connection handle to search for. - * @param out_desc On success, this is populated with information relating to - * the matching connection. Pass NULL if you don't need this - * information. - * - * @return 0 on success, BLE_HS_ENOTCONN if no matching connection was - * found. - */ -int ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc); - -/** - * Searches for a connection with a peer with the specified address. - * If a matching connection is found, the supplied connection descriptor - * is filled correspondingly. - * - * @param addr The ble address of a connected peer device to search for. - * @param out_desc On success, this is populated with information relating to - * the matching connection. Pass NULL if you don't need this - * information. - * - * @return 0 on success, BLE_HS_ENOTCONN if no matching connection was - * found. - */ -int ble_gap_conn_find_by_addr(const ble_addr_t *addr, - struct ble_gap_conn_desc *out_desc); +/** + * Searches for a connection with a peer with the specified address. + * If a matching connection is found, the supplied connection descriptor + * is filled correspondingly. + * + * @param addr The ble address of a connected peer device to search for. + * @param out_desc On success, this is populated with information relating to + * the matching connection. Pass NULL if you don't need this + * information. + * + * @return 0 on success, BLE_HS_ENOTCONN if no matching connection was + * found. + */ +int ble_gap_conn_find_by_addr(const ble_addr_t *addr, + struct ble_gap_conn_desc *out_desc); /** * Configures a connection to use the specified GAP event callback. A @@ -1850,13 +1487,13 @@ int ble_gap_adv_rsp_set_data(const uint8_t *data, int data_len); * fit in an advertisement, * other error code on failure. */ -int ble_gap_adv_set_fields(const struct ble_hs_adv_fields *rsp_fields); +int ble_gap_adv_set_fields(const struct ble_hs_adv_fields *adv_fields); /** * Configures the fields to include in subsequent scan responses. This is a * convenience wrapper for ble_gap_adv_rsp_set_data(). * - * @param adv_fields Specifies the scan response data. + * @param rsp_fields Specifies the scan response data. * * @return 0 on success, * BLE_HS_EBUSY if advertising is in progress, @@ -1866,44 +1503,6 @@ int ble_gap_adv_set_fields(const struct ble_hs_adv_fields *rsp_fields); */ int ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields); -#if MYNEWT_VAL(ENC_ADV_DATA) -/** - * @brief Bluetooth data serialized size. - * - * Get the size of a serialized @ref bt_data given its data length. - * - * Size of 'AD Structure'->'Length' field, equal to 1. - * Size of 'AD Structure'->'Data'->'AD Type' field, equal to 1. - * Size of 'AD Structure'->'Data'->'AD Data' field, equal to data_len. - * - * See Core Specification Version 5.4 Vol. 3 Part C, 11, Figure 11.1. - */ -#define BLE_GAP_DATA_SERIALIZED_SIZE(data_len) ((data_len) + 2) -#define BLE_GAP_ENC_ADV_DATA 0x31 -struct enc_adv_data { - uint8_t len; - uint8_t type; - uint8_t *data; -}; - -/** - * @brief Helper to declare elements of enc_adv_data arrays - * - * This macro is mainly for creating an array of struct enc_adv_data - * elements which is then passed to e.g. @ref ble_gap_adv_start(). - * - * @param _type Type of advertising data field - * @param _data Pointer to the data field payload - * @param _data_len Number of bytes behind the _data pointer - */ -#define ENC_ADV_DATA(_type, _data, _data_len) \ - { \ - .type = (_type), \ - .len = (_data_len), \ - .data = (uint8_t *)(_data), \ - } -#endif - #if MYNEWT_VAL(BLE_EXT_ADV) /** @brief Extended advertising parameters */ struct ble_gap_ext_adv_params { @@ -2103,6 +1702,16 @@ int ble_gap_ext_adv_clear(void); * */ int ble_gap_ext_adv_active(uint8_t instance); + +/** + * Finds first not configured advertising instance. + * + * @param[out] out_adv_instance Pointer to be filled with found advertising instance + * + * @return 0 if free advertising instance was found, error code otherwise + * + */ +int ble_gap_adv_get_free_instance(uint8_t *out_adv_instance); #endif /* Periodic Advertising */ @@ -2122,55 +1731,31 @@ struct ble_gap_periodic_adv_params { * defaults */ uint16_t itvl_max; - -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) - /** Number of subevents - * If zero, the periodic advertiser will be a broadcaster, without responses. - */ - uint8_t num_subevents; - - /** Interval between subevents (N * 1.25 ms) - * Shall be between 7.5ms and 318.75 ms. - */ - uint8_t subevent_interval; - - /** Time between the advertising packet in a subevent and the - * first response slot (N * 1.25 ms) - * - */ - uint8_t response_slot_delay; - - /** Time between response slots (N * 0.125 ms) - * Shall be between 0.25 and 31.875 ms. - */ - uint8_t response_slot_spacing; - - /** Number of subevent response slots - * If zero, response_slot_delay and response_slot_spacing are ignored. - */ - uint8_t num_response_slots; -#endif /* PERIODIC_ADV_WITH_RESPONSES */ }; -#if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) /** @brief Periodic advertising enable parameters */ struct ble_gap_periodic_adv_start_params { +#if MYNEWT_VAL(BLE_VERSION) >= 53 /** If include adi in aux_sync_ind PDU */ - unsigned int include_adi:1; + unsigned int include_adi : 1; +#endif }; /** @brief Periodic advertising sync reporting parameters */ struct ble_gap_periodic_adv_sync_reporting_params { +#if MYNEWT_VAL(BLE_VERSION) >= 53 /** If filter duplicates */ - unsigned int filter_duplicates:1; + unsigned int filter_duplicates : 1; +#endif }; /** @brief Periodic adv set data parameters */ struct ble_gap_periodic_adv_set_data_params { +#if MYNEWT_VAL(BLE_VERSION) >= 53 /** If include adi in aux_sync_ind PDU */ - unsigned int update_did:1; -}; + unsigned int update_did : 1; #endif +}; /** @brief Periodic sync parameters */ struct ble_gap_periodic_sync_params { @@ -2184,114 +1769,14 @@ struct ble_gap_periodic_sync_params { uint16_t sync_timeout; /** If reports should be initially disabled when sync is created */ - unsigned int reports_disabled:1; + unsigned int reports_disabled : 1; -#if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) +#if MYNEWT_VAL(BLE_VERSION) >= 53 /** If duplicate filtering should be should be initially enabled when sync is - created */ - unsigned int filter_duplicates:1; -#endif -#if MYNEWT_VAL(BLE_AOA_AOD) - /** - * Specifies the type of Constant Tone Extension (CTE) to which the receiver should not synchronize. - * This parameter determines which types of packets with specific CTE configurations are ignored during synchronization. - * - * Possible values: - * 0: Do not sync to packets with an AoA Constant Tone Extension. - * 1: Do not sync to packets with an AoD Constant Tone Extension with 1 μs slots. - * 2: Do not sync to packets with an AoD Constant Tone Extension with 2 μs slots. - * 3: Do not sync to packets with a type 3 Constant Tone Extension (currently reserved for future use). - * 4: Do not sync to packets without a Constant Tone Extension. - */ - uint8_t sync_cte_type; -#endif -}; - - -#if MYNEWT_VAL(BLE_AOA_AOD) -#define BLE_GAP_CTE_TYPE_AOA 0x0 -#define BLE_GAP_CTE_TYPE_AOD_1US 0x1 -#define BLE_GAP_CTE_TYPE_AOD_2US 0x2 - -#define BLE_GAP_CTE_RSP_ALLOW_AOA_MASK BLE_HCI_CTE_RSP_ALLOW_AOA_MASK -#define BLE_GAP_CTE_RSP_ALLOW_AOD_1US_MASK BLE_HCI_CTE_RSP_ALLOW_AOD_1US_MASK -#define BLE_GAP_CTE_RSP_ALLOW_AOD_2US_MASK BLE_HCI_CTE_RSP_ALLOW_AOD_2US_MASK - - -/** @brief Periodic advertising parameters */ -struct ble_gap_periodic_adv_cte_params { - /** - * Constant Tone Extension length in 8 µs units (Range: 0x02 to 0x14) - */ - uint8_t cte_length; - - /** - * Constant Tone Extension type - * 0x00 : AoA Constant Tone Extension - * 0x01 : AoD Constant Tone Extension with 1 µs slots - * 0x02 : AoD Constant Tone Extension with 2 µs slots - */ - uint8_t cte_type; - - /** - * The number of Constant Tone Extensions to transmit in each periodic - * advertising interval (Range: 0x01 to 0x10) - */ - uint8_t cte_count; - - /** - * The number of Antenna IDs in the pattern - * (Range: 0x02 to 0x4B) - */ - uint8_t switching_pattern_length; - - /** - * Antenna ID in the pattern. - * there is a pattern pointer - */ - uint8_t* antenna_ids; - -}; - -struct ble_gap_cte_sampling_params { - /** - * The sampling rate used by the Controller - * 0x01 : Switching and sampling slots are 1 μs each - * 0x02 : Switching and sampling slots are 2 μs each - */ - uint8_t slot_durations; - - /** - * The number of Antenna IDs in the pattern - * (Range: 0x02 to 0x4B) - */ - uint8_t switching_pattern_length; - - /** - * Antenna ID in the pattern. - * there is a pattern pointer - */ - uint8_t* antenna_ids; - -}; - + created */ + unsigned int filter_duplicates : 1; #endif - -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) -struct ble_gap_set_periodic_adv_subev_data_params { - /** The subevent to set data for */ - uint8_t subevent; - - /** The first response slot to listen to */ - uint8_t response_slot_start; - - /** The number of response slots to listen to */ - uint8_t response_slot_count; - - /** The data to send */ - struct os_mbuf *data; }; -#endif /** * Configure periodic advertising for specified advertising instance @@ -2308,7 +1793,6 @@ struct ble_gap_set_periodic_adv_subev_data_params { int ble_gap_periodic_adv_configure(uint8_t instance, const struct ble_gap_periodic_adv_params *params); -#if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) /** * Start periodic advertising for specified advertising instance. * @@ -2322,16 +1806,6 @@ int ble_gap_periodic_adv_start(uint8_t instance, const struct ble_gap_periodic_adv_start_params *params); -#else -/** - * Start periodic advertising for specified advertising instance. - * - * @param instance Instance ID - * - * @return 0 on success, error code on failure. - */ -int ble_gap_periodic_adv_start(uint8_t instance); -#endif /** * Stop periodic advertising for specified advertising instance. @@ -2342,7 +1816,6 @@ int ble_gap_periodic_adv_start(uint8_t instance); */ int ble_gap_periodic_adv_stop(uint8_t instance); -#if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) /** * Configures the data to include in periodic advertisements for specified * advertising instance. @@ -2356,22 +1829,13 @@ int ble_gap_periodic_adv_stop(uint8_t instance); */ int ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data, - struct ble_gap_periodic_adv_set_data_params *params); -#else -/** - * Configures the data to include in periodic advertisements for specified - * advertising instance. - * - * @param instance Instance ID - * @param data Chain containing the periodic advertising data. - * - * @return 0 on success or error code on failure. - */ -int ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data); -#endif + const struct ble_gap_periodic_adv_set_data_params *params); /** - * Performs the Synchronization procedure with periodic advertiser. + * Schedule the Synchronization procedure with periodic advertiser. + * Procedure is performed as soon as Extended Discovery procedure is started. + * If Extended Discovery is already active when issuing this procedure, + * it will be performed immediately. It is up to application to start Extended Discovery. * * @param addr Peer address to synchronize with. If NULL than * peers from periodic list are used. @@ -2407,7 +1871,6 @@ int ble_gap_periodic_adv_sync_create_cancel(void); int ble_gap_periodic_adv_sync_terminate(uint16_t sync_handle); #if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) -#if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) /** * Disable or enable periodic reports for specified sync. * @@ -2421,17 +1884,7 @@ int ble_gap_periodic_adv_sync_terminate(uint16_t sync_handle); int ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, bool enable, const struct ble_gap_periodic_adv_sync_reporting_params *params); -#else -/** - * Disable or enable periodic reports for specified sync. - * - * @param sync_handle Handle identifying synchronization. - * @param enable If reports should be enabled. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, bool enable); -#endif + /** * Initialize sync transfer procedure for specified handles. * @@ -2466,6 +1919,7 @@ int ble_gap_periodic_adv_sync_set_info(uint8_t instance, * Set the default periodic sync transfer params. * * + * @param conn_handle Handle identifying connection. * @param params Default Parameters for periodic sync transfer. * * @return 0 on success; nonzero on failure. @@ -2535,122 +1989,6 @@ int ble_gap_clear_periodic_adv_list(void); * @return 0 on success; nonzero on failure. */ int ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size); - - - -#if MYNEWT_VAL(BLE_AOA_AOD) - -/** - * Set connectionless Constant Tone Extension (CTE) transmission parameters. - * - * @param instance Periodic advertising instance ID. - * @param params Pointer to the CTE transmission parameters. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_set_connless_cte_transmit_params(uint8_t instance, - const struct ble_gap_periodic_adv_cte_params *params); - -/** - * Enable or disable connectionless CTE transmission. - * - * @param instance Periodic advertising instance ID. - * @param cte_enable 0x00 to disable, 0x01 to enable CTE transmission. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_set_connless_cte_transmit_enable(uint8_t instance, uint8_t cte_enable); - -/** - * Enable or disable connectionless IQ sampling for periodic advertising. - * - * @param sync_handle Sync handle identifying the periodic advertiser. - * @param sampling_enable 0x00 to disable, 0x01 to enable IQ sampling. - * @param max_sampled_ctes Maximum number of sampled CTEs. - * @param cte_sampling_params Pointer to the CTE sampling parameters. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_set_connless_iq_sampling_enable(uint16_t sync_handle, uint8_t sampling_enable, - uint8_t max_sampled_ctes, - const struct ble_gap_cte_sampling_params *cte_sampling_params); - -/** - * Set connection CTE receive parameters. - * - * @param conn_handle Connection handle. - * @param sampling_enable 0x00 to disable, 0x01 to enable CTE sampling. - * @param cte_sampling_params Pointer to the CTE sampling parameters. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_set_conn_cte_recv_param(uint16_t conn_handle, uint8_t sampling_enable, - const struct ble_gap_cte_sampling_params *cte_sampling_params); - -/** - * Set connection CTE transmission parameters. - * - * @param conn_handle Connection handle. - * @param cte_types Bitfield specifying supported CTE types. - * @param switching_pattern_len Length of the antenna switching pattern. - * @param antenna_ids Pointer to the array of antenna IDs. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_set_conn_cte_transmit_param(uint16_t conn_handle, uint8_t cte_types, - uint8_t switching_pattern_len, const uint8_t *antenna_ids); - -/** - * Enable or disable connection CTE request. - * - * @param conn_handle Connection handle. - * @param enable 0x00 to disable, 0x01 to enable CTE request. - * @param cte_request_interval Interval between CTE requests in connection interval. - * @param requested_cte_length Requested CTE length in 8 µs units. - * @param requested_cte_type Requested CTE type. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_conn_cte_req_enable(uint16_t conn_handle, uint8_t enable, uint16_t cte_request_interval, - uint8_t requested_cte_length, uint8_t requested_cte_type); - -/** - * Enable or disable connection CTE response. - * - * @param conn_handle Connection handle. - * @param enable 0x00 to disable, 0x01 to enable CTE response. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_conn_cte_rsp_enable(uint16_t conn_handle, uint8_t enable); - -/** - * Read antenna information. - * - * @param switch_sampling_rates On success, stores the supported switching and sampling rates. - * @param num_antennae On success, stores the number of antennae. - * @param max_switch_pattern_len On success, stores the maximum switching pattern length. - * @param max_cte_len On success, stores the maximum CTE length. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_read_antenna_information(uint8_t *switch_sampling_rates, uint8_t *num_antennae, - uint8_t *max_switch_pattern_len, uint8_t *max_cte_len); - -#endif // MYNEWT_VAL(BLE_AOA_AOD) - -#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) -int -ble_gap_set_periodic_adv_subev_data(uint8_t instance, uint8_t num_subevents, - const struct ble_gap_set_periodic_adv_subev_data_params *params); - -int ble_gap_periodic_adv_set_response_data(uint16_t sync_handle, - struct ble_gap_periodic_adv_response_params *param, - struct os_mbuf *data); - -int ble_gap_periodic_adv_sync_subev(uint16_t sync_handle, uint8_t include_tx_power, - uint8_t num_subevents, uint8_t *subevents); -#endif #endif @@ -2780,7 +2118,7 @@ int ble_gap_disc_active(void); * On expiration, the procedure ends and a * BLE_GAP_EVENT_DISC_COMPLETE event is * reported. Units are milliseconds. - * @param conn_params Additional arguments specifying the particulars + * @param params Additional arguments specifying the particulars * of the connect procedure. Specify null for * default values. * @param cb The callback to associate with this connect @@ -2806,71 +2144,6 @@ int ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, const struct ble_gap_conn_params *params, ble_gap_event_fn *cb, void *cb_arg); -/** - * Initiates an Sync connect procedure for PAwR. - * - * @param own_addr_type The type of address the stack should use for - * itself during connection establishment. - * - BLE_OWN_ADDR_PUBLIC - * - BLE_OWN_ADDR_RANDOM - * - BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT - * - BLE_OWN_ADDR_RPA_RANDOM_DEFAULT - * @param advertising_handle The advertising_Handle identifying the periodic advertising train - * Range: 0x00 to 0xEF or 0xFF - * @param subevent The Subevent parameter is used to identify the subevent where a connection - request shall be initiated from a periodic advertising train. - The Advertising_Handle and Subevent parameters - shall be set to 0xFF if these - parameters are not used. - * @param peer_addr The address of the peer to connect to. - * If this parameter is NULL, the white list - * is used. - * @param duration_ms The duration of the discovery procedure. - * On expiration, the procedure ends and a - * BLE_GAP_EVENT_DISC_COMPLETE event is - * reported. Units are milliseconds. - * @param phy_mask Define on which PHYs connection attempt should - * be done - * @param phy_1m_conn_params Additional arguments specifying the - * particulars of the connect procedure. When - * BLE_GAP_LE_PHY_1M_MASK is set in phy_mask - * this parameter can be specify to null for - * default values. - * @param phy_2m_conn_params Additional arguments specifying the - * particulars of the connect procedure. When - * BLE_GAP_LE_PHY_2M_MASK is set in phy_mask - * this parameter can be specify to null for - * default values. - * @param phy_coded_conn_params Additional arguments specifying the - * particulars of the connect procedure. When - * BLE_GAP_LE_PHY_CODED_MASK is set in - * phy_mask this parameter can be specify to - * null for default values. - * @param cb The callback to associate with this connect - * procedure. When the connect procedure - * completes, the result is reported through - * this callback. If the connect procedure - * succeeds, the connection inherits this - * callback as its event-reporting mechanism. - * @param cb_arg The optional argument to pass to the callback - * function. - * - * @return 0 on success; - * BLE_HS_EALREADY if a connection attempt is - * already in progress; - * BLE_HS_EBUSY if initiating a connection is not - * possible because scanning is in progress; - * BLE_HS_EDONE if the specified peer is already - * connected; - * Other nonzero on error. - */ -int ble_gap_connect_with_synced(uint8_t own_addr_type, uint8_t advertising_handle, - uint8_t subevent, const ble_addr_t *peer_addr, - int32_t duration_ms, uint8_t phy_mask, - const struct ble_gap_conn_params *phy_1m_conn_params, - const struct ble_gap_conn_params *phy_2m_conn_params, - const struct ble_gap_conn_params *phy_coded_conn_params, - ble_gap_event_fn *cb, void *cb_arg); /** * Initiates an extended connect procedure. * @@ -2929,44 +2202,6 @@ int ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, const struct ble_gap_conn_params *phy_coded_conn_params, ble_gap_event_fn *cb, void *cb_arg); -#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN) -/** - * @brief Enable the optimization of multiple connections. - * - * @param enable Enable or disable the optimization. - * @param common_factor The greatest common factor of all intervals in 0.625ms units. - * @return 0 on success; - * - */ -int ble_gap_common_factor_set(bool enable, uint32_t common_factor); - -/** - * Initiates an extended connect procedure with optimization. - * - * @param multi_conn_params Additional arguments specifying the particulars - * of the connect procedure. - * @param cb The callback to associate with this connect - * procedure. When the connect procedure - * completes, the result is reported through - * this callback. If the connect procedure - * succeeds, the connection inherits this - * callback as its event-reporting mechanism. - * @param cb_arg The optional argument to pass to the callback - * function. - * - * @return 0 on success; - * BLE_HS_EALREADY if a connection attempt is - * already in progress; - * BLE_HS_EBUSY if initiating a connection is not - * possible because scanning is in progress; - * BLE_HS_EDONE if the specified peer is already - * connected; - * Other nonzero on error. - */ -int ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params, - ble_gap_event_fn *cb, void *cb_arg); -#endif - /** * Aborts a connect procedure in progress. * @@ -3010,6 +2245,15 @@ int ble_gap_terminate(uint16_t conn_handle, uint8_t hci_reason); */ int ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count); +/** + * Retrieves the size of whitelist supported by controller + * + * @param size On success, this holds the size of controller accept list + * + * @return 0 on success; nonzero on failure + */ +int ble_gap_wl_read_size(uint8_t *size); + /** * Initiates a connection parameter update procedure. * @@ -3087,37 +2331,6 @@ int ble_gap_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets, int ble_gap_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_t sugg_max_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. * @@ -3161,7 +2374,7 @@ int ble_gap_pair_initiate(uint16_t conn_handle); * start encryption. * @param key_size Encryption key size * @param ltk Long Term Key to be used for encryption. - * @param udiv Encryption Diversifier for LTK + * @param ediv Encryption Diversifier for LTK * @param rand_val Random Value for EDIV and LTK * @param auth If LTK provided is authenticated. * @@ -3233,9 +2446,20 @@ int ble_gap_unpair_oldest_peer(void); */ int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr); +/** + * @defgroup ble_gap_privacy_modes Generic Access Profile (GAP) Privacy Modes + * @{ + */ + +/** Network privacy mode. */ #define BLE_GAP_PRIVATE_MODE_NETWORK 0 + +/** Device privacy mode. */ #define BLE_GAP_PRIVATE_MODE_DEVICE 1 +/** @} */ + + /** * Set privacy mode for specified peer device * @@ -3249,9 +2473,22 @@ int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr); */ int ble_gap_set_priv_mode(const ble_addr_t *peer_addr, uint8_t priv_mode); +/** + * @defgroup ble_gap_physical_layers Generic Access Profile (GAP) Physical Layers + * @{ + */ + +/** Physical layer: 1M PHY. */ #define BLE_GAP_LE_PHY_1M 1 + +/** Physical layer: 2M PHY. */ #define BLE_GAP_LE_PHY_2M 2 + +/** Physical layer: Coded PHY. */ #define BLE_GAP_LE_PHY_CODED 3 + +/** @} */ + /** * Read PHYs used for specified connection. * @@ -3271,20 +2508,35 @@ int ble_gap_set_priv_mode(const ble_addr_t *peer_addr, uint8_t priv_mode); */ int ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy); +/** + * @defgroup ble_gap_phy_masks Generic Access Profile (GAP) PHY Masks + * @{ + */ + +/** Bitmask for 1M PHY. */ #define BLE_GAP_LE_PHY_1M_MASK 0x01 + +/** Bitmask for 2M PHY. */ #define BLE_GAP_LE_PHY_2M_MASK 0x02 + +/** Bitmask for Coded PHY. */ #define BLE_GAP_LE_PHY_CODED_MASK 0x04 + +/** Bitmask for any PHY. */ #define BLE_GAP_LE_PHY_ANY_MASK 0x0F + +/** @} */ + /** * Set preferred default PHYs to be used for connections. * - * @params tx_phys_mask Preferred TX PHY. Can be mask of following + * @param tx_phys_mask Preferred TX PHY. Can be mask of following * constants: * - BLE_GAP_LE_PHY_1M_MASK * - BLE_GAP_LE_PHY_2M_MASK * - BLE_GAP_LE_PHY_CODED_MASK * - BLE_GAP_LE_PHY_ANY_MASK - * @params rx_phys_mask Preferred RX PHY. Can be mask of following + * @param rx_phys_mask Preferred RX PHY. Can be mask of following * constants: * - BLE_GAP_LE_PHY_1M_MASK * - BLE_GAP_LE_PHY_2M_MASK @@ -3296,20 +2548,33 @@ int ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy); int ble_gap_set_prefered_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask); +/** + * @defgroup ble_gap_coded_phy_schemes Generic Access Profile (GAP) Coded PHY Schemes + * @{ + */ + +/** Coded PHY: any coding scheme. */ #define BLE_GAP_LE_PHY_CODED_ANY 0 + +/** Coded PHY: S2 coding scheme. */ #define BLE_GAP_LE_PHY_CODED_S2 1 + +/** Coded PHY: S8 coding scheme. */ #define BLE_GAP_LE_PHY_CODED_S8 2 + +/** @} */ + /** * Set preferred PHYs to be used for connection. * * @param conn_handle Connection handle - * @params tx_phys_mask Preferred TX PHY. Can be mask of following + * @param tx_phys_mask Preferred TX PHY. Can be mask of following * constants: * - BLE_GAP_LE_PHY_1M_MASK * - BLE_GAP_LE_PHY_2M_MASK * - BLE_GAP_LE_PHY_CODED_MASK * - BLE_GAP_LE_PHY_ANY_MASK - * @params rx_phys_mask Preferred RX PHY. Can be mask of following + * @param rx_phys_mask Preferred RX PHY. Can be mask of following * constants: * - BLE_GAP_LE_PHY_1M_MASK * - BLE_GAP_LE_PHY_2M_MASK @@ -3370,8 +2635,13 @@ ble_gap_subrate_req(uint16_t conn_handle, uint16_t subrate_min, uint16_t subrate * This should be used as an opaque structure and not modified manually. */ struct ble_gap_event_listener { + /** The function to call when a GAP event occurs. */ ble_gap_event_fn *fn; + + /** An optional argument to pass to the event handler function. */ void *arg; + + /** Singly-linked list entry. */ SLIST_ENTRY(ble_gap_event_listener) link; }; @@ -3403,6 +2673,25 @@ int ble_gap_event_listener_register(struct ble_gap_event_listener *listener, */ int ble_gap_event_listener_unregister(struct ble_gap_event_listener *listener); +/** + * Calls function defined by the user for every connection that is currently established + * + * @param cb Callback function + * @param arg Callback argument + */ +void ble_gap_conn_foreach_handle(ble_gap_conn_foreach_handle_fn *cb, void *arg); + +/** + * Looks for the connection with specified address. + * + * @param addr Address to look for + * @param out_conn_handle Pointer to the variable in which conn_handle will be saved if found + * + * @return 0 on success + * BLE_HS_ENOTCONN if connection with specified address was not found + */ +int ble_gap_conn_find_handle_by_addr(const ble_addr_t *addr, uint16_t *out_conn_handle); + #if MYNEWT_VAL(BLE_POWER_CONTROL) /** * Enable Set Path Loss Reporting. @@ -3479,111 +2768,6 @@ int ble_gap_set_path_loss_reporting_param(uint16_t conn_handle, uint8_t high_thr uint8_t high_hysteresis, uint8_t low_threshold, uint8_t low_hysteresis, uint16_t min_time_spent); #endif - -/** - * Set Data Related Address Changes Param - * - * @param adv_handle Advertising handle - * @param change_reason Reasons for refreshing addresses - * - * @return 0 on success; nonzero on failure. - */ -int ble_gap_set_data_related_addr_change_param(uint8_t adv_handle, uint8_t change_reason); - -/** - * Start a test where the DUT generates reference packets at a fixed interval. - * - * @param tx_chan Channel for sending test data, - * tx_channel = (Frequency -2402)/2, tx_channel range = 0x00-0x27, - * Frequency range = 2402 MHz to 2480 MHz. - * - * @param test_data_len Length in bytes of payload data in each packet - * @param payload Packet Payload type. Valid range: 0x00 - 0x07 - * - * @return 0 on success; nonzero on failure - */ - -int ble_gap_dtm_tx_start(uint8_t tx_chan, uint8_t test_data_len, uint8_t payload); - -/** - * Start a test where the DUT receives test reference packets at a fixed interval. - * - * @param rx_chan Channel for test data reception, - * rx_channel = (Frequency -2402)/2, tx_channel range = 0x00-0x27, - * Frequency range = 2402 MHz to 2480 MHz. - * - * @return 0 on success; nonzero on failure - */ - -int ble_gap_dtm_rx_start(uint8_t rx_chan); - -/** - * Stop any test which is in progress - * - * @return 0 on success; nonzero on failure - */ - -int ble_gap_dtm_stop(void); - -/** - * Start a test where the DUT generates reference packets at a fixed interval. - * - * @param tx_chan Channel for sending test data, - * tx_channel = (Frequency -2402)/2, tx_channel range = 0x00-0x27, - * Frequency range: 2402 MHz to 2480 MHz - * - * @param test_data_len Length in bytes of payload data in each packet - * @param payload Packet payload type. Valid range: 0x00 - 0x07 - * @param phy Phy used by transmitter 1M phy: 0x01, 2M phy:0x02, coded phy:0x03. - * - * @return 0 on sucess; nonzero on failure - */ -int ble_gap_dtm_enh_tx_start(uint8_t tx_chan, uint8_t test_data_len, uint8_t payload, - uint8_t phy); - -/** - * Start a test where the DUT receives test reference packets at fixed interval - * - * @param rx_chan Channel for test data reception, - * rx_channel = (Frequency -2402)/2, tx_channel range = 0x00-0x27, - * Frequency range: 2402 MHz to 2480 MHz - * - * @param index modulation index, 0x00:standard modulation index, 0x01:stable modulation index - * @param phy Phy type used by the receiver, 1M phy: 0x01, 2M phy:0x02, coded phy:0x03 - * - * @return 0 on success; nonzero on failure - */ -int ble_gap_dtm_enh_rx_start(uint8_t rx_chan, uint8_t index, uint8_t phy); - -/** - * Set Read Remote Version Information is used to retrieve the version, manufacturer, - * and subversion information of remote controller after connection established - * - * @param conn_handle Connection handle - * @param version Defines the specification version of the LE Controller - * @param manufacturer Indicates the manufacturer of the remote Controller - * @param subversion Manufacturer specific version - - * @return 0 on success; nonzero on failure -*/ - -int ble_gap_read_rem_ver_info(uint16_t conn_handle, uint8_t *version, uint16_t *manufacturer, uint16_t *subversion); - -/** - * Read local resolvable address command - * - * @param peer_addr_type Peer Identity Address type - * - * @param peer_addr Peer Identity Address - * - * @param out_addr Local Resolvable Address received from controller. - * - * @return 0 on success; nonzero on failure - */ - -int ble_gap_rd_local_resolv_addr(uint8_t peer_addr_type, const ble_addr_t *peer_addr, - uint8_t *out_addr); - #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/host/include/host/ble_gatt.h b/src/nimble/nimble/host/include/host/ble_gatt.h index 133b81b8a..a96fcc4c2 100644 --- a/src/nimble/nimble/host/include/host/ble_gatt.h +++ b/src/nimble/nimble/host/include/host/ble_gatt.h @@ -28,11 +28,8 @@ */ #include -#include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/host/include/host/ble_att.h" #include "nimble/nimble/host/include/host/ble_uuid.h" -#include "nimble/nimble/host/include/host/ble_esp_gatt.h" -#include "syscfg/syscfg.h" #ifdef __cplusplus extern "C" { #endif @@ -63,12 +60,13 @@ struct ble_hs_cfg; */ /** GATT service 16-bit UUID. */ -#define BLE_GATT_SVC_UUID16 0x1801 +#define BLE_GATT_SVC_UUID16 0x1801 /** GATT Client Characteristic Configuration descriptor 16-bit UUID. */ -#define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902 -#define BLE_GATT_DSC_CLT_PRE_FMT16 0x2904 -#define BLE_GATT_DSC_CLT_AGG_FMT16 0x2905 +#define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902 + +/** GATT Characteristic Extended Porperties descriptor 16-bit UUID. */ +#define BLE_GATT_DSC_EXT_PROP_UUID16 0x2900 /** @} */ @@ -126,49 +124,49 @@ struct ble_hs_cfg; * @{ */ -/** GATT Characteristic Flag: Broadcast. */ +/** GATT Characteristic Flag: Broadcast property. */ #define BLE_GATT_CHR_F_BROADCAST 0x0001 -/** GATT Characteristic Flag: Read. */ +/** GATT Characteristic Flag: Read property. */ #define BLE_GATT_CHR_F_READ 0x0002 -/** GATT Characteristic Flag: Write without Response. */ +/** GATT Characteristic Flag: Write without Response property. */ #define BLE_GATT_CHR_F_WRITE_NO_RSP 0x0004 -/** GATT Characteristic Flag: Write. */ +/** GATT Characteristic Flag: Write property. */ #define BLE_GATT_CHR_F_WRITE 0x0008 -/** GATT Characteristic Flag: Notify. */ +/** GATT Characteristic Flag: Notify property. */ #define BLE_GATT_CHR_F_NOTIFY 0x0010 -/** GATT Characteristic Flag: Indicate. */ +/** GATT Characteristic Flag: Indicate property. */ #define BLE_GATT_CHR_F_INDICATE 0x0020 -/** GATT Characteristic Flag: Authenticated Signed Writes. */ +/** GATT Characteristic Flag: Authenticated Signed Writes property. */ #define BLE_GATT_CHR_F_AUTH_SIGN_WRITE 0x0040 -/** GATT Characteristic Flag: Reliable Writes. */ +/** GATT Characteristic Flag: Reliable Writes property. */ #define BLE_GATT_CHR_F_RELIABLE_WRITE 0x0080 -/** GATT Characteristic Flag: Auxiliary Writes. */ +/** GATT Characteristic Flag: Auxiliary Writes permission. */ #define BLE_GATT_CHR_F_AUX_WRITE 0x0100 -/** GATT Characteristic Flag: Read Encrypted. */ +/** GATT Characteristic Flag: Read Encrypted permission. */ #define BLE_GATT_CHR_F_READ_ENC 0x0200 -/** GATT Characteristic Flag: Read Authenticated. */ +/** GATT Characteristic Flag: Read Authenticated permission. */ #define BLE_GATT_CHR_F_READ_AUTHEN 0x0400 -/** GATT Characteristic Flag: Read Authorized. */ +/** GATT Characteristic Flag: Read Authorized permission. */ #define BLE_GATT_CHR_F_READ_AUTHOR 0x0800 -/** GATT Characteristic Flag: Write Encrypted. */ +/** GATT Characteristic Flag: Write Encrypted permission. */ #define BLE_GATT_CHR_F_WRITE_ENC 0x1000 -/** GATT Characteristic Flag: Write Authenticated. */ +/** GATT Characteristic Flag: Write Authenticated permission. */ #define BLE_GATT_CHR_F_WRITE_AUTHEN 0x2000 -/** GATT Characteristic Flag: Write Authorized. */ +/** GATT Characteristic Flag: Write Authorized permission. */ #define BLE_GATT_CHR_F_WRITE_AUTHOR 0x4000 @@ -189,213 +187,19 @@ struct ble_hs_cfg; #define BLE_GATT_SVC_TYPE_SECONDARY 2 /** @} */ -/** - * Client Presentation Format - * GATT Format Types - * Ref: Assigned Numbers Specification - */ -#define BLE_GATT_CHR_FORMAT_BOOLEAN 0x01 -#define BLE_GATT_CHR_FORMAT_UINT2 0x02 -#define BLE_GATT_CHR_FORMAT_UINT4 0x03 -#define BLE_GATT_CHR_FORMAT_UINT8 0x04 -#define BLE_GATT_CHR_FORMAT_UINT12 0x05 -#define BLE_GATT_CHR_FORMAT_UINT16 0x06 -#define BLE_GATT_CHR_FORMAT_UINT24 0x07 -#define BLE_GATT_CHR_FORMAT_UINT32 0x08 -#define BLE_GATT_CHR_FORMAT_UINT48 0x09 -#define BLE_GATT_CHR_FORMAT_UINT64 0x0A -#define BLE_GATT_CHR_FORMAT_UINT128 0x0B -#define BLE_GATT_CHR_FORMAT_SINT8 0x0C -#define BLE_GATT_CHR_FORMAT_SINT12 0x0D -#define BLE_GATT_CHR_FORMAT_SINT16 0x0E -#define BLE_GATT_CHR_FORMAT_SINT24 0x0F -#define BLE_GATT_CHR_FORMAT_SINT32 0x10 -#define BLE_GATT_CHR_FORMAT_SINT48 0x11 -#define BLE_GATT_CHR_FORMAT_SINT64 0x12 -#define BLE_GATT_CHR_FORMAT_SINT128 0x13 -#define BLE_GATT_CHR_FORMAT_FLOAT32 0x14 -#define BLE_GATT_CHR_FORMAT_FLOAT64 0x15 -#define BLE_GATT_CHR_FORMAT_MEDFLOAT16 0x16 -#define BLE_GATT_CHR_FORMAT_MEDFLOAT32 0x17 -#define BLE_GATT_CHR_FORMAT_UINT16_2 0x18 -#define BLE_GATT_CHR_FORMAT_UTF8S 0x19 -#define BLE_GATT_CHR_FORMAT_UTF16S 0x1A -#define BLE_GATT_CHR_FORMAT_STRUCT 0x1B -#define BLE_GATT_CHR_FORMAT_MEDASN1 0x1C /** - * Client Presentation Format - * GATT Unit UUIDs - * Ref: Assigned Numbers Specification - */ -#define BLE_GATT_CHR_UNIT_UNITLESS 0x2700 /* Unitless */ -#define BLE_GATT_CHR_UNIT_METRE 0x2701 /* Length */ -#define BLE_GATT_CHR_UNIT_KILOGRAM 0x2702 /* Mass */ -#define BLE_GATT_CHR_UNIT_SECOND 0x2703 /* Time */ -#define BLE_GATT_CHR_UNIT_AMPERE 0x2704 /* Electric Current */ -#define BLE_GATT_CHR_UNIT_KELVIN 0x2705 /* Thermodynamic Temperature */ -#define BLE_GATT_CHR_UNIT_MOLE 0x2706 /* Amount Of Substance */ -#define BLE_GATT_CHR_UNIT_CANDELA 0x2707 /* Luminous Intensity */ -#define BLE_GATT_CHR_UNIT_SQUARE_METRES 0x2710 /* Area */ -#define BLE_GATT_CHR_UNIT_CUBIC_METRES 0x2711 /* Volume */ -#define BLE_GATT_CHR_UNIT_METRES_PER_SECOND 0x2712 /* Velocity */ -#define BLE_GATT_CHR_UNIT_METRES_PER_SECOND_SQUARED 0x2713 /* Acceleration */ -#define BLE_GATT_CHR_UNIT_RECIPROCAL_METRE 0x2714 /* Wavenumber */ -#define BLE_GATT_CHR_UNIT_KILOGRAM_PER_CUBIC_METRE_DENSITY 0x2715 /* Density */ -#define BLE_GATT_CHR_UNIT_KILOGRAM_PER_SQUARE_METRE 0x2716 /* Surface Density */ -#define BLE_GATT_CHR_UNIT_CUBIC_METRE_PER_KILOGRAM 0x2717 /* Specific Volume */ -#define BLE_GATT_CHR_UNIT_AMPERE_PER_SQUARE_METRE 0x2718 /* Current Density */ -#define BLE_GATT_CHR_UNIT_AMPERE_PER_METRE 0x2719 /* Magnetic Field Strength */ -#define BLE_GATT_CHR_UNIT_MOLE_PER_CUBIC_METRE 0x271A /* Amount Concentration */ -#define BLE_GATT_CHR_UNIT_KILOGRAM_PER_CUBIC_METRE_MASS_CONC 0x271B /* Mass Concentration */ -#define BLE_GATT_CHR_UNIT_CANDELA_PER_SQUARE_METRE 0x271C /* Luminance */ -#define BLE_GATT_CHR_UNIT_REFRACTIVE_INDEX 0x271D /* Refractive Index */ -#define BLE_GATT_CHR_UNIT_RELATIVE_PERMEABILITY 0x271E /* Relative Permeability */ -#define BLE_GATT_CHR_UNIT_RADIAN 0x2720 /* Plane Angle */ -#define BLE_GATT_CHR_UNIT_STERADIAN 0x2721 /* Solid Angle */ -#define BLE_GATT_CHR_UNIT_HERTZ 0x2722 /* Frequency */ -#define BLE_GATT_CHR_UNIT_NEWTON 0x2723 /* Force */ -#define BLE_GATT_CHR_UNIT_PASCAL 0x2724 /* Pressure */ -#define BLE_GATT_CHR_UNIT_JOULE 0x2725 /* Energy */ -#define BLE_GATT_CHR_UNIT_WATT 0x2726 /* Power */ -#define BLE_GATT_CHR_UNIT_COULOMB 0x2727 /* Electric Charge */ -#define BLE_GATT_CHR_UNIT_VOLT 0x2728 /* Electric Potential Difference */ -#define BLE_GATT_CHR_UNIT_FARAD 0x2729 /* Capacitance */ -#define BLE_GATT_CHR_UNIT_OHM 0x272A /* Electric Resistance */ -#define BLE_GATT_CHR_UNIT_SIEMENS 0x272B /* Electric Conductance */ -#define BLE_GATT_CHR_UNIT_WEBER 0x272C /* Magnetic Flux */ -#define BLE_GATT_CHR_UNIT_TESLA 0x272D /* Magnetic Flux Density */ -#define BLE_GATT_CHR_UNIT_HENRY 0x272E /* Inductance */ -#define BLE_GATT_CHR_UNIT_DEGREE_CELSIUS 0x272F /* celsius Temperature */ -#define BLE_GATT_CHR_UNIT_LUMEN 0x2730 /* Luminous Flux */ -#define BLE_GATT_CHR_UNIT_LUX 0x2731 /* Illuminance */ -#define BLE_GATT_CHR_UNIT_BECQUEREL 0x2732 /* Activity Referred To A Radionuclide */ -#define BLE_GATT_CHR_UNIT_GRAY 0x2733 /* Absorbed Dose */ -#define BLE_GATT_CHR_UNIT_SIEVERT 0x2734 /* Dose Equivalent */ -#define BLE_GATT_CHR_UNIT_KATAL 0x2735 /* Catalytic Activity */ -#define BLE_GATT_CHR_UNIT_PASCAL_SECOND 0x2740 /* Dynamic Viscosity */ -#define BLE_GATT_CHR_UNIT_NEWTON_METRE 0x2741 /* Moment Of Force */ -#define BLE_GATT_CHR_UNIT_NEWTON_PER_METRE 0x2742 /* Surface Tension */ -#define BLE_GATT_CHR_UNIT_RADIAN_PER_SECOND 0x2743 /* Angular Velocity */ -#define BLE_GATT_CHR_UNIT_RADIAN_PER_SECOND_SQUARED 0x2744 /* Angular Acceleration */ -#define BLE_GATT_CHR_UNIT_WATT_PER_SQUARE_METRE_HEAT 0x2745 /* Heat Flux Density */ -#define BLE_GATT_CHR_UNIT_JOULE_PER_KELVIN 0x2746 /* Heat Capacity */ -#define BLE_GATT_CHR_UNIT_JOULE_PER_KILOGRAM_KELVIN 0x2747 /* Specific Heat Capacity */ -#define BLE_GATT_CHR_UNIT_JOULE_PER_KILOGRAM 0x2748 /* Specific Energy */ -#define BLE_GATT_CHR_UNIT_WATT_PER_METRE_KELVIN 0x2749 /* Thermal Conductivity */ -#define BLE_GATT_CHR_UNIT_JOULE_PER_CUBIC_METRE 0x274A /* Energy Density */ -#define BLE_GATT_CHR_UNIT_VOLT_PER_METRE 0x274B /* Electric Field Strength */ -#define BLE_GATT_CHR_UNIT_COULOMB_PER_CUBIC_METRE 0x274C /* Electric Charge Density */ -#define BLE_GATT_CHR_UNIT_COULOMB_PER_SQUARE_METRE_CHARGE 0x274D /* Surface Charge Density */ -#define BLE_GATT_CHR_UNIT_COULOMB_PER_SQUARE_METRE_FLUX 0x274E /* Electric Flux Density */ -#define BLE_GATT_CHR_UNIT_FARAD_PER_METRE 0x274F /* Permittivity */ -#define BLE_GATT_CHR_UNIT_HENRY_PER_METRE 0x2750 /* Permeability */ -#define BLE_GATT_CHR_UNIT_JOULE_PER_MOLE 0x2751 /* Molar Energy */ -#define BLE_GATT_CHR_UNIT_JOULE_PER_MOLE_KELVIN 0x2752 /* Molar Entropy */ -#define BLE_GATT_CHR_UNIT_COULOMB_PER_KILOGRAM 0x2753 /* Exposure */ -#define BLE_GATT_CHR_UNIT_GRAY_PER_SECOND 0x2754 /* Absorbed Dose Rate */ -#define BLE_GATT_CHR_UNIT_WATT_PER_STERADIAN 0x2755 /* Radiant Intensity */ -#define BLE_GATT_CHR_UNIT_WATT_PER_SQUARE_METRE_STERADIAN 0x2756 /* Radiance */ -#define BLE_GATT_CHR_UNIT_KATAL_PER_CUBIC_METRE 0x2757 /* Catalytic Activity Concentration */ -#define BLE_GATT_CHR_UNIT_MINUTE 0x2760 /* Time */ -#define BLE_GATT_CHR_UNIT_HOUR 0x2761 /* Time */ -#define BLE_GATT_CHR_UNIT_DAY 0x2762 /* Time */ -#define BLE_GATT_CHR_UNIT_DEGREE 0x2763 /* Plane Angle */ -#define BLE_GATT_CHR_UNIT_MINUTE_ANGLE 0x2764 /* Plane Angle */ -#define BLE_GATT_CHR_UNIT_SECOND_ANGLE 0x2765 /* Plane Angle */ -#define BLE_GATT_CHR_UNIT_HECTARE 0x2766 /* Area */ -#define BLE_GATT_CHR_UNIT_LITRE 0x2767 /* Volume */ -#define BLE_GATT_CHR_UNIT_TONNE 0x2768 /* Mass */ -#define BLE_GATT_CHR_UNIT_BAR 0x2780 /* Pressure */ -#define BLE_GATT_CHR_UNIT_MILLIMETRE_OF_MERCURY 0x2781 /* Pressure */ -#define BLE_GATT_CHR_UNIT_ANGSTROM 0x2782 /* Length */ -#define BLE_GATT_CHR_UNIT_NAUTICAL_MILE 0x2783 /* Length */ -#define BLE_GATT_CHR_UNIT_BARN 0x2784 /* Area */ -#define BLE_GATT_CHR_UNIT_KNOT 0x2785 /* Velocity */ -#define BLE_GATT_CHR_UNIT_NEPER 0x2786 /* Logarithmic Radio Quantity */ -#define BLE_GATT_CHR_UNIT_BEL 0x2787 /* Logarithmic Radio Quantity */ -#define BLE_GATT_CHR_UNIT_YARD 0x27A0 /* Length */ -#define BLE_GATT_CHR_UNIT_PARSEC 0x27A1 /* Length */ -#define BLE_GATT_CHR_UNIT_INCH 0x27A2 /* Length */ -#define BLE_GATT_CHR_UNIT_FOOT 0x27A3 /* Length */ -#define BLE_GATT_CHR_UNIT_MILE 0x27A4 /* Length */ -#define BLE_GATT_CHR_UNIT_POUND_FORCE_PER_SQUARE_INCH 0x27A5 /* Pressure */ -#define BLE_GATT_CHR_UNIT_KILOMETRE_PER_HOUR 0x27A6 /* Velocity */ -#define BLE_GATT_CHR_UNIT_MILE_PER_HOUR 0x27A7 /* Velocity */ -#define BLE_GATT_CHR_UNIT_REVOLUTION_PER_MINUTE 0x27A8 /* Angular Velocity */ -#define BLE_GATT_CHR_UNIT_GRAM_CALORIE 0x27A9 /* Energy */ -#define BLE_GATT_CHR_UNIT_KILOGRAM_CALORIE 0x27AA /* Energy */ -#define BLE_GATT_CHR_UNIT_KILOWATT_HOUR 0x27AB /* Energy */ -#define BLE_GATT_CHR_UNIT_DEGREE_FAHRENHEIT 0x27AC /* Thermodynamic Temperature */ -#define BLE_GATT_CHR_UNIT_PERCENTAGE 0x27AD /* Percentage */ -#define BLE_GATT_CHR_UNIT_PER_MILLE 0x27AE /* Per Mille */ -#define BLE_GATT_CHR_UNIT_BEATS_PER_MINUTE 0x27AF /* Period */ -#define BLE_GATT_CHR_UNIT_AMPERE_HOURS 0x27B0 /* Electric Charge */ -#define BLE_GATT_CHR_UNIT_MILLIGRAM_PER_DECILITRE 0x27B1 /* Mass Density */ -#define BLE_GATT_CHR_UNIT_MILLIMOLE_PER_LITRE 0x27B2 /* Mass Density */ -#define BLE_GATT_CHR_UNIT_YEAR 0x27B3 /* Time */ -#define BLE_GATT_CHR_UNIT_MONTH 0x27B4 /* Time */ -#define BLE_GATT_CHR_UNIT_COUNT_PER_CUBIC_METRE 0x27B5 /* Concentration */ -#define BLE_GATT_CHR_UNIT_WATT_PER_SQUARE_METRE_IRRADIANCE 0x27B6 /* Irradiance */ -#define BLE_GATT_CHR_UNIT_PER_KILOGRAM_PER_MINUTE 0x27B7 /* Milliliter */ -#define BLE_GATT_CHR_UNIT_POUND 0x27B8 /* Mass */ -#define BLE_GATT_CHR_UNIT_METABOLIC_EQUIVALENT 0x27B9 /* Metabolic Equivalent */ -#define BLE_GATT_CHR_UNIT_PER_MINUTE_STEP 0x27BA /* Step */ -#define BLE_GATT_CHR_UNIT_PER_MINUTE_STROKE 0x27BC /* Stroke */ -#define BLE_GATT_CHR_UNIT_KILOMETRE_PER_MINUTE 0x27BD /* Pace */ -#define BLE_GATT_CHR_UNIT_LUMEN_PER_WATT 0x27BE /* Luminous Efficacy */ -#define BLE_GATT_CHR_UNIT_LUMEN_HOUR 0x27BF /* Luminous Energy */ -#define BLE_GATT_CHR_UNIT_LUX_HOUR 0x27C0 /* Luminous Exposure */ -#define BLE_GATT_CHR_UNIT_GRAM_PER_SECOND 0x27C1 /* Mass Flow */ -#define BLE_GATT_CHR_UNIT_LITRE_PER_SECOND 0x27C2 /* Volume Flow */ -#define BLE_GATT_CHR_UNIT_DECIBEL 0x27C3 /* Sound Pressure */ -#define BLE_GATT_CHR_UNIT_PARTS_PER_MILLION 0x27C4 /* Concentration */ -#define BLE_GATT_CHR_UNIT_PARTS_PER_BILLION 0x27C5 /* Concentration */ -#define BLE_GATT_CHR_UNIT_MILLIGRAM_PER_DECILITRE_PER_MINUTE 0x27C6 /* Mass Density Rate */ -#define BLE_GATT_CHR_UNIT_KILOVOLT_AMPERE_HOUR 0x27C7 /* Electrical Apparent Energy */ -#define BLE_GATT_CHR_UNIT_VOLT_AMPERE 0x27C8 /* Electrical Apparent Power */ - -/** - * Client Presentation Format - * GATT Name Space - * Ref: Assigned Numbers Specification + * @defgroup ble_gatts_clt_cfg Client Characteristic Configuration Descriptor (CCCD) Flags Types + * @{ */ -#define BLE_GATT_CHR_NAMESPACE_BT_SIG 0x01 -/** - * Client Presentation Format - * GATT Description for Name Space BT_SIG - * Ref: Assigned Numbers Specification - */ -#define BLE_GATT_CHR_BT_SIG_DESC_UNKNOWN 0x0000 -/** 0x0001 - 0x00FF represent themselves. See Ref for more info */ -#define BLE_GATT_CHR_BT_SIG_DESC_FRONT 0x0100 -#define BLE_GATT_CHR_BT_SIG_DESC_BACK 0x0101 -#define BLE_GATT_CHR_BT_SIG_DESC_TOP 0x0102 -#define BLE_GATT_CHR_BT_SIG_DESC_BOTTOM 0x0103 -#define BLE_GATT_CHR_BT_SIG_DESC_UPPER 0x0104 -#define BLE_GATT_CHR_BT_SIG_DESC_LOWER 0x0105 -#define BLE_GATT_CHR_BT_SIG_DESC_MAIN 0x0106 -#define BLE_GATT_CHR_BT_SIG_DESC_BACKUP 0x0107 -#define BLE_GATT_CHR_BT_SIG_DESC_AUXILIARY 0x0108 -#define BLE_GATT_CHR_BT_SIG_DESC_SUPPLEMENTARY 0x0109 -#define BLE_GATT_CHR_BT_SIG_DESC_FLASH 0x010A -#define BLE_GATT_CHR_BT_SIG_DESC_INSIDE 0x010B -#define BLE_GATT_CHR_BT_SIG_DESC_OUTSIDE 0x010C -#define BLE_GATT_CHR_BT_SIG_DESC_LEFT 0x010D -#define BLE_GATT_CHR_BT_SIG_DESC_RIGHT 0x010E -#define BLE_GATT_CHR_BT_SIG_DESC_INTERNAL 0x010F -#define BLE_GATT_CHR_BT_SIG_DESC_EXTERNAL 0x0110 +/** GATT Client Charactaristic Configuration Flag: Notify. */ +#define BLE_GATT_CCCD_NOTIFY 0x01 -/*** @server. */ -/** Represents one notification tuple in a multi notification PDU */ -struct ble_gatt_notif { - /** The attribute handle on which to notify. */ - uint16_t handle; +/** GATT Client Charactaristic Configuration Flag: Indicate. */ +#define BLE_GATT_CCCD_INDICATE 0x02 - /** The notification value. */ - struct os_mbuf * value; -}; +/** @} */ /*** @client. */ /** Represents a GATT error. */ @@ -458,6 +262,21 @@ struct ble_gatt_dsc { ble_uuid_any_t uuid; }; +/** Represents a Characteristic Extended Properties descriptor */ +struct ble_gatt_cep_dsc { + /** Characteristic Extended properties **/ + uint16_t properties; +}; + +/** Represents a handle-value tuple for multiple handle notifications. */ +struct ble_gatt_notif { + /** The handle of the GATT characteristic */ + uint16_t handle; + + /** The buffer with GATT characteristic value */ + struct os_mbuf *value; +}; + /** Function prototype for the GATT MTU exchange callback. */ typedef int ble_gatt_mtu_fn(uint16_t conn_handle, const struct ble_gatt_error *error, @@ -536,6 +355,8 @@ int ble_gattc_exchange_mtu(uint16_t conn_handle, * updates; null for no callback. * @param cb_arg The optional argument to pass to the callback * function. + * + * @return 0 on success; nonzero on failure. */ int ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, void *cb_arg); @@ -712,10 +533,23 @@ int ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles, uint8_t num_handles, ble_gatt_attr_fn *cb, void *cb_arg); +/** + * Initiates GATT procedure: Read Multiple Variable Length Characteristic Values. + * + * @param conn_handle The connection over which to execute the + * procedure. + * @param handles An array of 16-bit attribute handles to read. + * @param num_handles The number of entries in the "handles" array. + * @param cb The function to call to report procedure status + * updates; null for no callback. + * @param cb_arg The optional argument to pass to the callback + * function. + * + * @return 0 on success; nonzero on failure. + */ int ble_gattc_read_mult_var(uint16_t conn_handle, const uint16_t *handles, uint8_t num_handles, ble_gatt_attr_mult_fn *cb, void *cb_arg); - /** * Initiates GATT procedure: Write Without Response. This function consumes * the supplied mbuf regardless of the outcome. @@ -747,21 +581,6 @@ int ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, int ble_gattc_write_no_rsp_flat(uint16_t conn_handle, uint16_t attr_handle, const void *data, uint16_t data_len); -/** - * Initiates GATT procedure: Signed Write. This function consumes the - * supplied mbuf regardless of the outcome. - * - * @param conn_handle The connection over which to execute the - * procedure. - * @param attr_handle The handle of the characteristic value to write - * to. - * @param txom The value to write to the characteristic. - * - * @return 0 on success; nonzero on failure. - */ -int ble_gattc_signed_write(uint16_t conn_handle, uint16_t attr_handle, - struct os_mbuf * txom); - /** * Initiates GATT procedure: Write Characteristic Value. This function * consumes the supplied mbuf regardless of the outcome. @@ -841,6 +660,8 @@ int ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, * updates; null for no callback. * @param cb_arg The optional argument to pass to the callback * function. + * + * @return 0 on success; nonzero on failure. */ int ble_gattc_write_reliable(uint16_t conn_handle, struct ble_gatt_attr *attrs, @@ -890,7 +711,15 @@ int ble_gatts_notify_multiple_custom(uint16_t conn_handle, struct ble_gatt_notif *tuples); /** - * Deprecated. Should not be used. Use ble_gatts_notify_custom instead. + * @deprecated Should not be used. Use ble_gatts_notify_custom instead. + * + * @param conn_handle The connection over which to execute the + * procedure. + * @param att_handle The attribute handle to indicate in the + * outgoing notification. + * @param om The value to write to the characteristic. + * + * @return 0 on success; nonzero on failure. */ int ble_gattc_notify_custom(uint16_t conn_handle, uint16_t att_handle, struct os_mbuf *om); @@ -910,10 +739,44 @@ int ble_gattc_notify_custom(uint16_t conn_handle, uint16_t att_handle, int ble_gatts_notify(uint16_t conn_handle, uint16_t chr_val_handle); /** - * Deprecated. Should not be used. Use ble_gatts_notify instead. + * @deprecated Should not be used. Use ble_gatts_notify instead. + * + * @param conn_handle The connection over which to execute the + * procedure. + * @param chr_val_handle The value attribute handle of the + * characteristic to include in the outgoing + * notification. + * + * @return 0 on success; nonzero on failure. */ int ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle); +/** + * Sends a multiple handle variable length characteristic notification. The + * content of the message is read from the specified characteristics. + * Notifications are sent in order of supplied handles. Function tries to + * send minimum amount of PDUs. If PDU can't contain all of the + * characteristic values, multiple notifications are sent. If only one + * handle-value pair fits into PDU, or only one characteristic remains in the + * list, regular characteristic notification is sent. + * + * If GATT client doesn't support receiving multiple handle notifications, + * this will use GATT notification for each characteristic, separately. + * + * @param conn_handle The connection over which to execute the + * procedure. + * @param num_handles The number of entries in the "chr_val_handles" + * array. + * @param chr_val_handles Array of attribute handles of the + * characteristics to include in the outgoing + * notification. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gatts_notify_multiple(uint16_t conn_handle, + size_t num_handles, + const uint16_t *chr_val_handles); + /** * Sends a "free-form" characteristic indication. The provided mbuf contains * the indication payload. This function consumes the supplied mbuf regardless @@ -930,8 +793,18 @@ int ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle); */ int ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, struct os_mbuf *txom); + /** - * Deprecated. Should not be used. Use ble_gatts_indicate_custom instead. + * @deprecated Should not be used. Use ble_gatts_indicate_custom instead. + * + * @param conn_handle The connection over which to execute the + * procedure. + * @param chr_val_handle The value attribute handle of the + * characteristic to include in the outgoing + * indication. + * @param txom The data to include in the indication. + * + * @return 0 on success; nonzero on failure. */ int ble_gattc_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, struct os_mbuf *txom); @@ -951,13 +824,16 @@ int ble_gattc_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, int ble_gatts_indicate(uint16_t conn_handle, uint16_t chr_val_handle); /** - * Deprecated. Should not be used. Use ble_gatts_indicate instead. + * @deprecated Should not be used. Use ble_gatts_indicate instead. + * @copydoc ble_gatts_indicate */ int ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle); -void ble_gattc_cache_conn_undisc_all(ble_addr_t peer_addr); - -/** Initialize the BLE GATT client. */ +/** + * Initialize the BLE GATT client + * + * @return 0 on success; nonzero on failure. + */ int ble_gattc_init(void); /*** @server. */ @@ -1006,9 +882,6 @@ struct ble_gatt_chr_def { * attribute handle. */ uint16_t *val_handle; - - /** Client Presentation Format Descriptors */ - struct ble_gatt_cpfd *cpfd; }; /** Represents the definition of a GATT service. */ @@ -1062,40 +935,6 @@ struct ble_gatt_dsc_def { void *arg; }; -/** - * Client Presentation Format Descriptor - * Defines the format of the Characteristic Value. - * - * +-------------+------------+ - * | Field Name | Value Size | - * +-------------+------------+ - * | Format | 1 octet | - * | Exponent | 1 octet | - * | Unit | 2 octets | - * | Name Space | 1 octet | - * | Description | 2 octets | - * +-------------+------------+ - */ -struct ble_gatt_cpfd { - /** - * Format of the value of this characteristic. e.g. UINT32 - * Cannot be 0x00. 0x00 represents CPFD array is ended. - */ - uint8_t format; - - /** Exponent field. Multiplies the value to 10^exponent. Type: sint8 */ - int8_t exponent; - - /** The unit of this characteristic. e.g. meters per second */ - uint16_t unit; - - /** The name space of the description. */ - uint8_t name_space; - - /** The description of this characteristic. Depends on name space. */ - uint16_t description; -}; - /** * Context for an access to a GATT characteristic or descriptor. When a client * reads or writes a locally registered characteristic or descriptor, an @@ -1231,18 +1070,6 @@ struct ble_gatt_register_ctxt { typedef void ble_gatt_register_fn(struct ble_gatt_register_ctxt *ctxt, void *arg); -#if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) -struct ble_gatts_clt_cfg { - STAILQ_ENTRY(ble_gatts_clt_cfg) next; - uint16_t chr_val_handle; - uint8_t flags; - uint8_t allowed; -}; - -/** A cached array of handles for the configurable characteristics. */ -STAILQ_HEAD(ble_gatts_clt_cfg_list, ble_gatts_clt_cfg); -#endif - /** * Queues a set of service definitions for registration. All services queued * in this manner get registered when ble_gatts_start() is called. @@ -1256,32 +1083,7 @@ STAILQ_HEAD(ble_gatts_clt_cfg_list, ble_gatts_clt_cfg); * BLE_HS_ENOMEM on heap exhaustion. */ int ble_gatts_add_svcs(const struct ble_gatt_svc_def *svcs); -void ble_gatts_free_svcs(void); -#if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) -/** - * Adds a set of services for registration. All services added - * in this manner get registered immidietely. - * - * @param svcs An array of service definitions to queue for - * registration. This array must be - * terminated with an entry whose 'type' - * equals 0. - * - * @return 0 on success; - * BLE_HS_ENOMEM on heap exhaustion. - */ -int ble_gatts_add_dynamic_svcs(const struct ble_gatt_svc_def *svcs); -/** - * Deletes a service with corresponding uuid. All services deleted - * in this manner will be deleted immidietely. - * - * @param uuid uuid of the service to be deleted. - * - * @return 0 on success; - * BLE_HS_ENOENT on invalid uuid. - */ -int ble_gatts_delete_svc(const ble_uuid_t *uuid); -#endif + /** * Set visibility of local GATT service. Invisible services are not removed * from database but are not discoverable by peer devices. Service Changed @@ -1385,14 +1187,6 @@ typedef void (*ble_gatt_svc_foreach_fn)(const struct ble_gatt_svc_def *svc, */ void ble_gatts_show_local(void); -#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) -/** - * Calculates and returns the maximum - * Security Mode 1 Level requirement. - */ -uint8_t ble_gatts_security_mode_1_level(void); -#endif - /** * Resets the GATT server to its initial state. On success, this function * removes all supported services, characteristics, and descriptors. This @@ -1422,52 +1216,42 @@ int ble_gatts_reset(void); int ble_gatts_start(void); /** - * Saves Client Supported Features for specified connection. + * Gets Client Supported Features for specified connection. * - * @param conn_handle Connection handle identifying connection for - * which Client Supported Features should be saved - * @param om The mbuf chain to set value from. + * @param conn_handle Connection handle identifying the connection for + * which Client Supported Features should be saved + * @param out_supported_feat Client supported features to be returned. + * @param len The size of the Client Supported Features + * characteristic in octets. * * @return 0 on success; * BLE_HS_ENOTCONN if no matching connection - * was found + * was found * BLE_HS_EINVAL if supplied buffer is empty or - * if any Client Supported Feature was - * attempted to be disabled. - * A BLE host core return code on unexpected - * error. + * if any Client Supported Feature was + * attempted to be disabled. + * A BLE host core return code on unexpected error. * */ -int ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, - struct os_mbuf *om); +int ble_gatts_peer_cl_sup_feat_get(uint16_t conn_handle, uint8_t *out_supported_feat, uint8_t len); /** - * Gets Client Supported Features for specified connection. + * Reads configuration values from Client Characteristic Configuration + * Descriptor for specified characteristic. * - * @param conn_handle Connection handle identifying connection for - * which Client Supported Features should be saved - * @param out_supported_feat Client supported features to be returned. + * @param conn_handle Connection handle identifying the connection + * to which CCC instance is related. + * @param chr_val_handle The value handle of characteristic. + * @param cccd_value Configuration value of CCC. * * @return 0 on success; * BLE_HS_ENOTCONN if no matching connection - * was found - * BLE_HS_EINVAL if supplied buffer is empty or - * if any Client Supported Feature was - * attempted to be disabled. - * A BLE host core return code on unexpected - * error. + * was found + * BLE_HS_ENOENT if descriptor could not be found. * */ -int ble_gatts_peer_cl_sup_feat_get(uint16_t conn_handle, uint8_t *out_supported_feat, uint8_t len); - -#if MYNEWT_VAL(BLE_GATT_CACHING) -int ble_gatts_calculate_hash(uint8_t *out_hash_key); -#endif - -/** - * Returns the current number of configured characteristics - */ -int ble_gatts_get_cfgable_chrs(void); +int ble_gatts_read_cccd(uint16_t conn_handle, uint16_t chr_val_handle, + uint8_t *cccd_value); #ifdef __cplusplus } @@ -1477,4 +1261,4 @@ int ble_gatts_get_cfgable_chrs(void); * @} */ -#endif +#endif /* H_BLE_GATT_ */ diff --git a/src/nimble/nimble/host/include/host/ble_hs.h b/src/nimble/nimble/host/include/host/ble_hs.h index 7ad279a99..6a6c2e7b4 100644 --- a/src/nimble/nimble/host/include/host/ble_hs.h +++ b/src/nimble/nimble/host/include/host/ble_hs.h @@ -43,8 +43,8 @@ #include "nimble/nimble/host/include/host/ble_sm.h" #include "nimble/nimble/host/include/host/ble_store.h" #include "nimble/nimble/host/include/host/ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_iso.h" #include "nimble/nimble/include/nimble/nimble_npl.h" -#include "nimble/nimble/host/include/host/ble_esp_hs.h" #ifdef __cplusplus extern "C" { @@ -56,8 +56,6 @@ extern "C" { /** Connection handle not present */ #define BLE_HS_CONN_HANDLE_NONE 0xffff -#define BLE_HS_CTRL_DATA_HDR_SZ 0x4 - /** * @brief Bluetooth Host Error Code * @defgroup bt_host_err Bluetooth Host Error Code @@ -315,29 +313,12 @@ struct ble_hs_cfg { */ unsigned sm_sc:1; - /** @brief Security Manager - Enable/Disable Secure Connections Only flag - * - * If set, this will enforce P-256 elliptic curve encryption algorithm - * during pairing. - * It will force the max key size to be used during pairing. - */ - unsigned sm_sc_only:1; - /** @brief Security Manager Key Press Notification flag * * Currently unsupported and should not be set. */ unsigned sm_keypress:1; - /** @brief Enable/Disable Enhanced ATT Support - * - * Primarily used to enable EATT behaviour; denotes the number of eatt - * channels. Set to 0 to disable eatt. - * - * Default value is CONFIG_BT_NIMBLE_EATT_CHAN_NUM. - */ - uint8_t eatt; - /** @brief Security Manager Local Key Distribution Mask */ uint8_t sm_our_key_dist; diff --git a/src/nimble/nimble/host/include/host/ble_hs_adv.h b/src/nimble/nimble/host/include/host/ble_hs_adv.h index af2a44548..e377144c2 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_adv.h +++ b/src/nimble/nimble/host/include/host/ble_hs_adv.h @@ -20,181 +20,268 @@ #ifndef H_BLE_HS_ADV_ #define H_BLE_HS_ADV_ +/** + * @brief Bluetooth Host Advertising API + * @defgroup bt_adv Bluetooth Host Advertising API + * @ingroup bt_host + * @{ + */ + #include #include "nimble/nimble/host/include/host/ble_uuid.h" -#include "syscfg/syscfg.h" #ifdef __cplusplus extern "C" { #endif +/** Max Advertising Data Size. */ #define BLE_HS_ADV_MAX_SZ BLE_HCI_MAX_ADV_DATA_LEN /** Max field payload size (account for 2-byte header). */ #define BLE_HS_ADV_MAX_FIELD_SZ (BLE_HS_ADV_MAX_SZ - 2) -#define BLE_HS_ADV_LE_SUPP_FEAT_LEN 6 - +/** Represents advertising data packet in BLE advertisement or scan response. */ struct ble_hs_adv_field { + /** Length of the advertising data (type and value). */ uint8_t length; + + /** Type of the advertising data field. */ uint8_t type; + + /** Value of the advertising data field. */ uint8_t value[0]; }; +/** Function pointer typedef for parsing an advertising data field. */ typedef int (* ble_hs_adv_parse_func_t) (const struct ble_hs_adv_field *, void *); +/** Advertising Data Fields. */ struct ble_hs_adv_fields { - /*** 0x01 - Flags. */ + /** 0x01 - Flags. */ uint8_t flags; - /*** 0x02,0x03 - 16-bit service class UUIDs. */ + /** 0x02,0x03 - 16-bit service class UUIDs. */ const ble_uuid16_t *uuids16; + + /** Number of 16-bit UUIDs. */ uint8_t num_uuids16; + + /** Indicates if the list of 16-bit UUIDs is complete. */ unsigned uuids16_is_complete:1; - /*** 0x04,0x05 - 32-bit service class UUIDs. */ + + /** 0x04,0x05 - 32-bit service class UUIDs. */ const ble_uuid32_t *uuids32; + + /** Number of 32-bit UUIDs. */ uint8_t num_uuids32; + + /** Indicates if the list of 32-bit UUIDs is complete. */ unsigned uuids32_is_complete:1; - /*** 0x06,0x07 - 128-bit service class UUIDs. */ + + /** 0x06,0x07 - 128-bit service class UUIDs. */ const ble_uuid128_t *uuids128; + + /** Number of 128-bit UUIDs. */ uint8_t num_uuids128; + + /** Indicates if the list of 128-bit UUIDs is complete. */ unsigned uuids128_is_complete:1; - /*** 0x08,0x09 - Local name. */ + + /** 0x08,0x09 - Local name. */ const uint8_t *name; + + /** Length of the local name. */ uint8_t name_len; - unsigned name_is_complete:1; - /*** 0x0a - Tx power level. */ - int8_t tx_pwr_lvl; - unsigned tx_pwr_lvl_is_present:1; + /** Indicates if the list of local names if complete. */ + unsigned name_is_complete:1; - /*** 0x0d - Slave connection interval range. */ - const uint8_t *slave_itvl_range; - /*** 0x10 - Security Manager TK value */ - const uint8_t *sm_tk_value; - unsigned sm_tk_value_is_present:1; + /** 0x0a - Tx power level. */ + int8_t tx_pwr_lvl; - /*** 0x11 - Security Manager OOB flag */ - uint8_t sm_oob_flag; - unsigned sm_oob_flag_is_present:1; + /** Indicates if Tx power level is present. */ + unsigned tx_pwr_lvl_is_present:1; - /*** 0x14 - 16-bit service soliciation list. */ - const ble_uuid16_t *sol_uuids16; - uint8_t sol_num_uuids16; - /*** 0x15 - 128-bit service solicitation UUIDs. */ - const ble_uuid128_t *sol_uuids128; - uint8_t sol_num_uuids128; + /** 0x12 - Slave connection interval range. */ + const uint8_t *slave_itvl_range; - /*** 0x16 - Service data - 16-bit UUID. */ + /** 0x16 - Service data - 16-bit UUID. */ const uint8_t *svc_data_uuid16; + + /** Length of the service data with 16-bit UUID. */ uint8_t svc_data_uuid16_len; - /*** 0x17 - Public target address. */ + + /** 0x17 - Public target address. */ const uint8_t *public_tgt_addr; - uint8_t num_public_tgt_addrs; - /*** 0x18 - Random target address. */ - const uint8_t *random_tgt_addr; - uint8_t num_random_tgt_addrs; + /** Number of public target addresses. */ + uint8_t num_public_tgt_addrs; - /*** 0x19 - Appearance. */ + /** 0x19 - Appearance. */ uint16_t appearance; + + /** Indicates if Appearance is present. */ unsigned appearance_is_present:1; - /*** 0x1a - Advertising interval. */ - uint16_t adv_itvl; - unsigned adv_itvl_is_present:1; - /*** 0x1b - LE Bluetooth device address */ - const uint8_t *device_addr; - unsigned device_addr_type; - unsigned device_addr_is_present:1; + /** 0x1a - Advertising interval. */ + uint16_t adv_itvl; - /*** 0x1f - 32-bit service solicitation UUIDs */ - const ble_uuid32_t *sol_uuids32; - uint8_t sol_num_uuids32; + /** Indicates if advertising interval is present. */ + unsigned adv_itvl_is_present:1; - /*** 0x1c - LE Role */ - uint8_t le_role; - unsigned le_role_is_present:1; - /*** 0x20 - Service data - 32-bit UUID. */ + /** 0x20 - Service data - 32-bit UUID. */ const uint8_t *svc_data_uuid32; + + /** Length of the service data with 32-bit UUID. */ uint8_t svc_data_uuid32_len; - /*** 0x21 - Service data - 128-bit UUID. */ + + /** 0x21 - Service data - 128-bit UUID. */ const uint8_t *svc_data_uuid128; + + /** Length of service data with 128-bit UUID. */ uint8_t svc_data_uuid128_len; - /*** 0x24 - URI. */ - const uint8_t *uri; - uint8_t uri_len; - /*** 0x27 - LE Supported Features. */ - /*** Core Spec v5.4 Vol. 6 Part B 4.6 */ - uint8_t le_supp_feat[BLE_HS_ADV_LE_SUPP_FEAT_LEN]; - unsigned le_supp_feat_is_present; + /** 0x24 - URI. */ + const uint8_t *uri; - /*** 0x2f - Advertising interval - long. */ - uint32_t adv_itvl_long; - unsigned adv_itvl_long_is_present:1; + /** Length of the URI. */ + uint8_t uri_len; -#if MYNEWT_VAL(ENC_ADV_DATA) - /*** 0x31 - Encrypted Advertising Data. */ - const uint8_t *enc_adv_data; - uint8_t enc_adv_data_len; -#endif - /*** 0xff - Manufacturer specific data. */ + /** 0xff - Manufacturer specific data. */ const uint8_t *mfg_data; + + /** Length of manufacturer specific data. */ uint8_t mfg_data_len; + + /** 0x30 - Broadcast name. */ + const uint8_t *broadcast_name; + + /** Length of the Broadcast name. */ + uint8_t broadcast_name_len; }; +/** + * @defgroup ble_hs_adv_types BLE Advertising Common Data Types + * @{ + */ + +/** Common Data Type: Flags. */ #define BLE_HS_ADV_TYPE_FLAGS 0x01 + +/** Common Data Type: Incomplete List of 16-bit Service Class UUIDs. */ #define BLE_HS_ADV_TYPE_INCOMP_UUIDS16 0x02 + +/** Common Data Type: Complete List of 16-bit Service Class UUIDs. */ #define BLE_HS_ADV_TYPE_COMP_UUIDS16 0x03 + +/** Common Data Type: Incomplete List of 32-bit Service Class UUIDs. */ #define BLE_HS_ADV_TYPE_INCOMP_UUIDS32 0x04 + +/** Common Data Type: Complete List of 32-bit Service Class UUIDs. */ #define BLE_HS_ADV_TYPE_COMP_UUIDS32 0x05 + +/** Common Data Type: Incomplete List of 128-bit Service Class UUIDs. */ #define BLE_HS_ADV_TYPE_INCOMP_UUIDS128 0x06 + +/** Common Data Type: Complete List of 128-bit Service Class UUIDs. */ #define BLE_HS_ADV_TYPE_COMP_UUIDS128 0x07 + +/** Common Data Type: Shortened Local Name. */ #define BLE_HS_ADV_TYPE_INCOMP_NAME 0x08 + +/** Common Data Type: Complete Local Name. */ #define BLE_HS_ADV_TYPE_COMP_NAME 0x09 + +/** Common Data Type: Tx Power Level. */ #define BLE_HS_ADV_TYPE_TX_PWR_LVL 0x0a -#define BLE_HS_ADV_TYPE_SEC_MGR_TK_VALUE 0x10 -#define BLE_HS_ADV_TYPE_SEC_MGR_OOB_FLAG 0x11 + +/** Common Data Type: Peripheral Connection Interval Range. */ #define BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE 0x12 + +/** Common Data Type: List of 16-bit Service Solicitation UUIDs. */ #define BLE_HS_ADV_TYPE_SOL_UUIDS16 0x14 + +/** Common Data Type: List of 128-bit Service Solicitation UUIDs. */ #define BLE_HS_ADV_TYPE_SOL_UUIDS128 0x15 + +/** Common Data Type: Service Data - 16-bit UUID. */ #define BLE_HS_ADV_TYPE_SVC_DATA_UUID16 0x16 + +/** Common Data Type: Public Target Address. */ #define BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR 0x17 + +/** Common Data Type: Random Target Address. */ #define BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR 0x18 + +/** Common Data Type: Appearance. */ #define BLE_HS_ADV_TYPE_APPEARANCE 0x19 + +/** Common Data Type: Advertising Interval. */ #define BLE_HS_ADV_TYPE_ADV_ITVL 0x1a -#define BLE_HS_ADV_TYPE_DEVICE_ADDR 0x1b -#define BLE_HS_ADV_TYPE_LE_ROLE 0x1c -#define BLE_HS_ADV_TYPE_SOL_UUIDS32 0x1f + +/** Common Data Type: Service Data - 32-bit UUID. */ #define BLE_HS_ADV_TYPE_SVC_DATA_UUID32 0x20 + +/** Common Data Type: Service Data - 128-bit UUID. */ #define BLE_HS_ADV_TYPE_SVC_DATA_UUID128 0x21 + +/** Common Data Type: URI. */ #define BLE_HS_ADV_TYPE_URI 0x24 -#define BLE_HS_ADV_TYPE_LE_SUPP_FEAT 0x27 + +/** Common Data Type: PB-ADV. */ #define BLE_HS_ADV_TYPE_MESH_PROV 0x29 + +/** Common Data Type: Mesh Message. */ #define BLE_HS_ADV_TYPE_MESH_MESSAGE 0x2a + +/** Common Data Type: Mesh Beacon. */ #define BLE_HS_ADV_TYPE_MESH_BEACON 0x2b -#define BLE_HS_ADV_TYPE_ADV_ITVL_LONG 0x2f -#define BLE_HS_ADV_TYPE_ENC_ADV_DATA 0x31 + +/** Common Data Type: Broadcast Name. */ +#define BLE_HS_ADV_TYPE_BROADCAST_NAME 0x30 + +/** Common Data Type: Manufacturer Specific Data. */ #define BLE_HS_ADV_TYPE_MFG_DATA 0xff +/** + * @} + */ + +/** + * @defgroup ble_hs_adv_flags BLE Advertising Flags + * @{ + */ +/** Length of BLE Advertising Flags field. */ #define BLE_HS_ADV_FLAGS_LEN 1 + +/** Limited Discoverable Mode Flag. */ #define BLE_HS_ADV_F_DISC_LTD 0x01 + +/** General Discoverable Mode Flag. */ #define BLE_HS_ADV_F_DISC_GEN 0x02 + +/** BR/EDR Not Supported Flag. */ #define BLE_HS_ADV_F_BREDR_UNSUP 0x04 +/** @} */ + +/** + * @defgroup ble_hs_adv_misc BLE Advertising Miscellaneous + * @{ + */ +/** Length of BLE advertising transmit power level field. */ #define BLE_HS_ADV_TX_PWR_LVL_LEN 1 /** @@ -203,33 +290,83 @@ struct ble_hs_adv_fields { */ #define BLE_HS_ADV_TX_PWR_LVL_AUTO (-128) +/** Length of the Peripheral Connection Interval Range field. */ #define BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN 4 +/** Minimum length of the Service Data - 16-bit UUID field. */ #define BLE_HS_ADV_SVC_DATA_UUID16_MIN_LEN 2 +/** Length of a Public Target Address entry. */ #define BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN 6 +/** Length of the Appearance field. */ #define BLE_HS_ADV_APPEARANCE_LEN 2 +/** Length of the Advertising Interval field. */ #define BLE_HS_ADV_ADV_ITVL_LEN 2 +/** Minimum length of the Service Data - 32-bit UUID field. */ #define BLE_HS_ADV_SVC_DATA_UUID32_MIN_LEN 4 +/** Minimum length of the Service Data - 128-bit UUID field. */ #define BLE_HS_ADV_SVC_DATA_UUID128_MIN_LEN 16 -#define BLE_HS_ADV_ADDR_TYPE_LEN 1 - -#define BLE_HS_ADV_ADV_ITVL_LONG_LEN 4 +/** + * @} + */ +/** + * Set the advertising data fields in an os_mbuf. + * + * @param adv_fields Pointer to the advertising data structure. + * @param om Pointer to the memory buffer that will be written with + * advertising data. + * + * @return 0 on success; non-zero on failure. + */ int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields, struct os_mbuf *om); +/** + * Set the advertising data fields in a destination buffer. + * + * @param adv_fields Pointer to the advertising data structure. + * @param dst Pointer to the destination buffer that will be written + * with advertising data. + * @param dst_len Pointer to the variable that will hold the length of + * the data written. + * @param max_len Maximum length of the destination buffer. + * + * @return 0 on success; nonzero on failure. + */ int ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, uint8_t *dst, uint8_t *dst_len, uint8_t max_len); +/** + * Parse the advertising data fields from a source buffer. + * + * @param adv_fields Pointer to the advertising data fields structure + * to populate. + * @param src Pointer to the source buffer containing the data + * to parse. + * @param src_len Length of the source buffer. + * + * @return 0 on success; nonzero on failure. + */ int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, const uint8_t *src, uint8_t src_len); +/** + * Parse the advertising data using the provided parsing function. + * + * @param data Pointer to the advertising data buffer to parse. + * @param length Length of the advertising data buffer. + * @param func Pointer to the parsing function to apply to each + * field. + * @param user_data User-defined data to pass to the parsing function. + * + * @return 0 on success; nonzero on failure. + */ int ble_hs_adv_parse(const uint8_t *data, uint8_t length, ble_hs_adv_parse_func_t func, void *user_data); @@ -237,4 +374,8 @@ int ble_hs_adv_parse(const uint8_t *data, uint8_t length, } #endif +/** + * @} + */ + #endif diff --git a/src/nimble/nimble/host/include/host/ble_hs_hci.h b/src/nimble/nimble/host/include/host/ble_hs_hci.h index 5b28d9991..237712080 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_hci.h +++ b/src/nimble/nimble/host/include/host/ble_hs_hci.h @@ -100,7 +100,7 @@ int ble_hs_hci_set_chan_class(const uint8_t *chan_map); * A BLE host core return code on unexpected * error. */ -int ble_hs_hci_util_rand(void *dst, int len); +int ble_hs_hci_rand(void *dst, int len); #if MYNEWT_VAL(BLE_HCI_VS) /** diff --git a/src/nimble/nimble/host/include/host/ble_hs_log.h b/src/nimble/nimble/host/include/host/ble_hs_log.h index e56217fd8..240f49003 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_log.h +++ b/src/nimble/nimble/host/include/host/ble_hs_log.h @@ -33,14 +33,13 @@ * @{ */ -#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) -#include "nimble/porting/nimble/include/logcfg/logcfg.h" +#ifndef BLE_NPL_LOG_MODULE +/** Defines the logging module for NimBLE Porting Layer (NPL). */ +#define BLE_NPL_LOG_MODULE BLE_HS_LOG #endif +#include "nimble/nimble/include/nimble/nimble_npl_log.h" + #ifdef __cplusplus extern "C" { #endif @@ -57,7 +56,7 @@ struct os_mbuf; * @param ... The format string and additional arguments for the log message. */ #define BLE_HS_LOG(lvl, ...) \ - BLE_HS_LOG_ ## lvl(__VA_ARGS__) + BLE_NPL_LOG(lvl, __VA_ARGS__) /** * @brief Macro for logging a Bluetooth address at a specified log level. @@ -69,9 +68,9 @@ struct os_mbuf; * @param addr The Bluetooth address to be logged. */ #define BLE_HS_LOG_ADDR(lvl, addr) \ - BLE_HS_LOG_ ## lvl("%02x:%02x:%02x:%02x:%02x:%02x", \ - (addr)[5], (addr)[4], (addr)[3], \ - (addr)[2], (addr)[1], (addr)[0]) + BLE_NPL_LOG(lvl, "%02x:%02x:%02x:%02x:%02x:%02x", \ + (addr)[5], (addr)[4], (addr)[3], \ + (addr)[2], (addr)[1], (addr)[0]) /** @@ -105,4 +104,4 @@ void ble_hs_log_flat_buf(const void *data, int len); * @} */ -#endif +#endif /* H_BLE_HS_LOG_*/ diff --git a/src/nimble/nimble/host/include/host/ble_iso.h b/src/nimble/nimble/host/include/host/ble_iso.h new file mode 100644 index 000000000..b2ab8514f --- /dev/null +++ b/src/nimble/nimble/host/include/host/ble_iso.h @@ -0,0 +1,509 @@ +/* + * 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_ISO_ +#define H_BLE_ISO_ + +/** + * @file ble_iso.h + * + * @brief Bluetooth ISO + * @defgroup bt_iso Bluetooth ISO + * @ingroup bt_host + * @{ + */ + +#include +#include "nimble/nimble/include/nimble/hci_common.h" +#include "syscfg/syscfg.h" + +/** + * @defgroup ble_iso_events ISO Events + * @{ + */ + +/** ISO event: BIG Create Completed */ +#define BLE_ISO_EVENT_BIG_CREATE_COMPLETE 0 + +/** ISO event: BIG Terminate Completed */ +#define BLE_ISO_EVENT_BIG_TERMINATE_COMPLETE 1 + +/** ISO event: BIG Sync Established */ +#define BLE_ISO_EVENT_BIG_SYNC_ESTABLISHED 2 + +/** ISO event: BIG Sync Terminated */ +#define BLE_ISO_EVENT_BIG_SYNC_TERMINATED 3 + +/** ISO event: ISO Data received */ +#define BLE_ISO_EVENT_ISO_RX 4 + +/** @} */ + +/** @brief Broadcast Isochronous Group (BIG) description */ +struct ble_iso_big_desc { + /** + * The identifier of the BIG. Assigned by the Host when a new BIG is + * created. + */ + uint8_t big_handle; + + /** + * The maximum time in microseconds for transmission of PDUs of all BISes in + * a BIG event. + */ + uint32_t big_sync_delay; + + /** + * The actual transport latency of transmitting payloads of all BISes in the + * BIG in microseconds. + */ + uint32_t transport_latency_big; + + /** The number of subevents per BIS in each BIG event. */ + uint8_t nse; + + /** + * The Burst Number (BN) specifies the number of new payloads in each BIS + * event. + */ + uint8_t bn; + + /** + * The Pre-Transmission Offset (PTO) specifies the offset of groups that + * carry data associated with the future BIS events. + */ + uint8_t pto; + + /** + * The Immediate Repetition Count (IRC) specifies the number of groups that + * carry the data associated with the current BIS event. + */ + uint8_t irc; + + /** + * The maximum number of data octets (excluding the MIC, if any) that can be + * carried in each BIS Data PDU in the BIG. + */ + uint16_t max_pdu; + + /** The time between two adjacent BIG anchor points in units of 1.25 ms. */ + uint16_t iso_interval; + + /** The total number of BISes in the BIG. */ + uint8_t num_bis; + + /** The connection handles of all the BIS in the BIG. */ + uint16_t conn_handle[MYNEWT_VAL(BLE_ISO_MAX_BISES)]; +}; + +/** @brief Received ISO Data status possible values */ +enum ble_iso_rx_data_status { + /** The complete SDU was received correctly. */ + BLE_ISO_DATA_STATUS_VALID = BLE_HCI_ISO_PKT_STATUS_VALID, + + /** May contain errors or part of the SDU may be missing. */ + BLE_ISO_DATA_STATUS_ERROR = BLE_HCI_ISO_PKT_STATUS_INVALID, + + /** Part(s) of the SDU were not received correctly */ + BLE_ISO_DATA_STATUS_LOST = BLE_HCI_ISO_PKT_STATUS_LOST, +}; + +/** @brief Received ISO data info structure */ +struct ble_iso_rx_data_info { + /** ISO Data timestamp. Valid if @ref ble_iso_rx_data_info.ts_valid is set */ + uint32_t ts; + + /** Packet sequence number */ + uint16_t seq_num; + + /** SDU length */ + uint16_t sdu_len : 12; + + /** ISO Data status. See @ref ble_iso_rx_data_status */ + uint16_t status : 2; + + /** Timestamp is valid */ + uint16_t ts_valid : 1; +}; + +/** + * Represents a ISO-related event. When such an event occurs, the host + * notifies the application by passing an instance of this structure to an + * application-specified callback. + */ +struct ble_iso_event { + /** + * Indicates the type of ISO event that occurred. This is one of the + * BLE_ISO_EVENT codes. + */ + uint8_t type; + + /** + * A discriminated union containing additional details concerning the ISO + * event. The 'type' field indicates which member of the union is valid. + */ + union { + /** + * Represents a completion of BIG creation. Valid for the following + * event types: + * o BLE_ISO_EVENT_BIG_CREATE_COMPLETE + */ + struct { + struct ble_iso_big_desc desc; + uint8_t status; + uint8_t phy; + } big_created; + + /** + * Represents a completion of BIG termination. Valid for the following + * event types: + * o BLE_ISO_EVENT_BIG_TERMINATE_COMPLETE + * o BLE_ISO_EVENT_BIG_SYNC_TERMINATED + */ + struct { + uint16_t big_handle; + uint8_t reason; + } big_terminated; + + /** + * Represents a completion of BIG synchronization. Valid for the following + * event types: + * o BLE_ISO_EVENT_BIG_SYNC_ESTABLISHED + */ + struct { + struct ble_iso_big_desc desc; + uint8_t status; + } big_sync_established; + + /** + * Represents a reception of ISO Data. Valid for the following + * event types: + * o BLE_ISO_EVENT_ISO_RX + */ + struct { + uint16_t conn_handle; + const struct ble_iso_rx_data_info *info; + struct os_mbuf *om; + } iso_rx; + }; +}; + +/** Function prototype for isochronous event callback. */ +typedef int ble_iso_event_fn(struct ble_iso_event *event, void *arg); + +/** Broadcast Isochronous Group (BIG) parameters */ +struct ble_iso_big_params { + /** + * The time interval of the periodic SDUs in microseconds. The value shall + * be between 0x0000FF and 0x0FFFFF. + */ + uint32_t sdu_interval; + + /** + * The maximum size of an SDU in octets. The value shall be between 0x0001 + * and 0x0FFF. + */ + uint16_t max_sdu; + + /** + * The maximum transport latency in milliseconds. The value shall be between + * 0x0005 and 0x0FA0. + */ + uint16_t max_transport_latency; + + /** + * The Retransmission Number (RTN) parameter contains the number of times + * every PDU should be retransmitted, irrespective of which BIG events the + * retransmissions occur in. The value shall be between 0x00 and 0x1E. + */ + uint8_t rtn; + + /** + * The PHY parameter is a bit field that indicates the PHY used for + * transmission of PDUs of BISes in the BIG. The value shall be one of the + * following: + * o BLE_HCI_LE_PHY_1M_PREF_MASK + * o BLE_HCI_LE_PHY_2M_PREF_MASK + * o BLE_HCI_LE_PHY_CODED_PREF_MASK + */ + uint8_t phy; + + /** + * Indicates the preferred method of arranging subevents of multiple BISes. + * The value shall be one of the following: + * o 0x00 - Sequential + * o 0x01 - Interleaved + */ + uint8_t packing; + + /** + * Indicates whether the BIG carries framed or unframed data. The value + * shall be one of the following: + * o 0x00 - Unframed + * o 0x01 - Framed + */ + uint8_t framing; + + /** + * Indicates whether the BIG is encrypted or not. The value shall be one of + * the following: + * o 0x00 - Unencrypted + * o 0x01 - Encrypted + */ + uint8_t encryption; + + /** + * The 128-bit code used to derive the session key that is used to encrypt + * and decrypt BIS payloads. + */ + const char *broadcast_code; +}; + +/** Create BIG parameters */ +struct ble_iso_create_big_params { + /** The associated periodic advertising train of the BIG. */ + uint8_t adv_handle; + + /** The total number of BISes in the BIG. */ + uint8_t bis_cnt; + + /** Callback function for reporting the status of the procedure. */ + ble_iso_event_fn *cb; + + /** + * An optional user-defined argument to be passed to the callback function. + */ + void *cb_arg; +}; + +/** + * Initiates the creation of Broadcast Isochronous Group (BIG). It configures + * the BIG parameters based on the provided input and triggers the corresponding + * HCI command. + * + * @param create_params A pointer to the structure holding the + * parameters specific to creating the BIG. + * These parameters define the general settings + * and include a callback function for handling + * creation events. + * @param big_params A pointer to the structure holding detailed + * parameters specific to the configuration of + * the BIG. These parameters include settings + * such as SDU interval, maximum SDU size, + * transport latency, etc. + * @param[out] big_handle BIG instance handle + * + * @return 0 on success; + * an error code on failure. + * + * @note The actual BIG creation result will be reported through the callback + * function specified in @p create_params. + */ +int ble_iso_create_big(const struct ble_iso_create_big_params *create_params, + const struct ble_iso_big_params *big_params, + uint8_t *big_handle); + +/** + * Terminates an existing Broadcast Isochronous Group (BIG). + * + * @param big_handle The identifier of the BIG to be terminated. + * + * @return 0 on success; + * an error code on failure. + */ +int ble_iso_terminate_big(uint8_t big_handle); + +/** @brief BIS parameters for @ref ble_iso_big_sync_create */ +struct ble_iso_bis_params { + /** BIS index */ + uint8_t bis_index; +}; + +/** @brief BIG Sync parameters for @ref ble_iso_big_sync_create */ +struct ble_iso_big_sync_create_params { + /** Periodic advertising train sync handle */ + uint16_t sync_handle; + + /** Null-terminated broadcast code for encrypted BIG or + * NULL if the BIG is unencrypted + */ + const char *broadcast_code; + + /** Maximum Subevents to be used to receive data payloads in each BIS event */ + uint8_t mse; + + /** The maximum permitted time between successful receptions of BIS PDUs */ + uint16_t sync_timeout; + + /** The callback to associate with this sync procedure. + * Sync establishment and termination are reported through this callback. + */ + ble_iso_event_fn *cb; + + /** The optional argument to pass to the callback function */ + void *cb_arg; + + /** Number of a BISes */ + uint8_t bis_cnt; + + /** BIS parameters */ + struct ble_iso_bis_params *bis_params; +}; + +/** + * @brief Synchronize to Broadcast Isochronous Group (BIG) + * + * This function is used to synchronize to a BIG described in the periodic + * advertising train specified by the @p param->pa_sync_handle parameter. + * + * @param[in] params BIG synchronization parameters + * @param[out] big_handle BIG instance handle + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_iso_big_sync_create(const struct ble_iso_big_sync_create_params *params, + uint8_t *big_handle); + +/** + * @brief Terminate Broadcast Isochronous Group (BIG) sync + * + * This function is used to stop synchronizing or cancel the process of + * synchronizing to the BIG identified by the @p big_handle parameter. + * The command also terminates the reception of BISes in the BIG. + * + * @param[in] big_handle BIG handle + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_iso_big_sync_terminate(uint8_t big_handle); + +/** @brief ISO Data direction */ +enum ble_iso_data_dir { + BLE_ISO_DATA_DIR_TX, + BLE_ISO_DATA_DIR_RX, +}; + +/** @brief ISO Codec ID */ +struct ble_iso_codec_id { + /** Coding Format */ + uint8_t format; + + /** Company ID */ + uint16_t company_id; + + /** Vendor Specific Codec ID */ + uint16_t vendor_specific; +}; + +/** @brief Setup ISO Data Path parameters */ +struct ble_iso_data_path_setup_params { + /** Connection handle of the CIS or BIS */ + uint16_t conn_handle; + + /** Data path direction */ + enum ble_iso_data_dir data_path_dir; + + /** Data path ID. 0x00 for HCI */ + uint8_t data_path_id; + + /** Controller delay */ + uint32_t ctrl_delay; + + /** Codec ID */ + struct ble_iso_codec_id codec_id; + + /** Codec Configuration Length */ + uint8_t codec_config_len; + + /** Codec Configuration */ + const uint8_t *codec_config; + + /** + * The ISO Data callback. Must be set if @p data_path_id is HCI. + * Received ISO data is reported through this callback. + */ + ble_iso_event_fn *cb; + + /** The optional argument to pass to the callback function */ + void *cb_arg; +}; + +/** + * @brief Setup ISO Data Path + * + * This function is used to identify and create the isochronous data path + * between the Host and the Controller for a CIS, CIS configuration, or BIS + * identified by the @p param->conn_handle parameter. + * + * @param[in] param BIG synchronization parameters + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_iso_data_path_setup(const struct ble_iso_data_path_setup_params *param); + +/** @brief @brief Remove ISO Data Path parameters */ +struct ble_iso_data_path_remove_params { + /** Connection handle of the CIS or BIS */ + uint16_t conn_handle; + + /** Data path direction */ + enum ble_iso_data_dir data_path_dir; +}; + +/** + * @brief Remove ISO Data Path + * + * This function is used to remove the input and/or output data path(s) + * associated with a CIS, CIS configuration, or BIS identified by the + * @p param->conn_handle parameter. + * + * @param[in] param BIG synchronization parameters + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_iso_data_path_remove(const struct ble_iso_data_path_remove_params *param); + +/** + * Initiates the transmission of isochronous data. + * + * @param conn_handle The connection over which to execute the procedure. + * @param data A pointer to the data to be transmitted. + * @param data_len Number of the data octets to be transmitted. + * + * @return 0 on success; + * an error code on failure. + */ +int ble_iso_tx(uint16_t conn_handle, void *data, uint16_t data_len); + +/** + * Initializes memory for ISO. + * + * @return 0 on success + */ +int ble_iso_init(void); + +/** + * @} + */ + +#endif /* H_BLE_ISO_ */ diff --git a/src/nimble/nimble/host/include/host/ble_l2cap.h b/src/nimble/nimble/host/include/host/ble_l2cap.h index 982584084..a72dace2d 100644 --- a/src/nimble/nimble/host/include/host/ble_l2cap.h +++ b/src/nimble/nimble/host/include/host/ble_l2cap.h @@ -66,6 +66,12 @@ struct ble_hs_conn; /** Security Manager (SM) CID. */ #define BLE_L2CAP_CID_SM 6 +/** Start range for connection oriented channel CID. */ +#define BLE_L2CAP_COC_CID_START 0x0040 + +/** End range for connection oriented channel CID. */ +#define BLE_L2CAP_COC_CID_END 0x007F + /** @} */ /** @@ -540,6 +546,19 @@ uint16_t ble_l2cap_get_conn_handle(struct ble_l2cap_chan *chan); int ble_l2cap_create_server(uint16_t psm, uint16_t mtu, ble_l2cap_event_fn *cb, void *cb_arg); +/** + * @brief Removes an L2CAP server. + * + * This function removes an L2CAP server with the specified Protocol/Service + * Multiplexer (PSM). Existing connections for this PSM are not removed. + * + * @param psm The Protocol/Service Multiplexer (PSM) for the server. + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_l2cap_remove_server(uint16_t psm); + /** * @brief Initiate an L2CAP connection. * @@ -565,7 +584,7 @@ int ble_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, /** * @brief Disconnect an L2CAP channel. * - * This function disconnects the specified L2CAP channel by sending a disconnect signal. + * This function disconnects the specified L2CAP connection oriented channel by sending a disconnect signal. * * @param chan Pointer to the L2CAP channel structure representing the channel to disconnect. * diff --git a/src/nimble/nimble/host/include/host/ble_sm.h b/src/nimble/nimble/host/include/host/ble_sm.h index ff381cf25..b6586021b 100644 --- a/src/nimble/nimble/host/include/host/ble_sm.h +++ b/src/nimble/nimble/host/include/host/ble_sm.h @@ -20,75 +20,229 @@ #ifndef H_BLE_SM_ #define H_BLE_SM_ +/** + * @brief Bluetooth Security Manager (SM) + * @defgroup bt_sm Bluetooth Security Manager (SM) + * @ingroup bt_host + * @{ + */ + #include #include "syscfg/syscfg.h" +#include +#include "nimble/nimble/include/nimble/ble.h" #ifdef __cplusplus extern "C" { #endif +/** + * @defgroup ble_sm_err Security Manager (SM) Error Codes + * @{ + */ + +/** SM Error Code: Success */ #define BLE_SM_ERR_SUCCESS 0x00 + +/** SM Error Code: Passkey entry failed */ #define BLE_SM_ERR_PASSKEY 0x01 + +/** SM Error Code: Out Of Band (OOB) not available */ #define BLE_SM_ERR_OOB 0x02 + +/** SM Error Code: Authentication Requirements */ #define BLE_SM_ERR_AUTHREQ 0x03 + +/** SM Error Code: Confirm Value failed */ #define BLE_SM_ERR_CONFIRM_MISMATCH 0x04 + +/** SM Error Code: Pairing Not Supported */ #define BLE_SM_ERR_PAIR_NOT_SUPP 0x05 + +/** SM Error Code: Encryption Key Size */ #define BLE_SM_ERR_ENC_KEY_SZ 0x06 + +/** SM Error Code: Command Not Supported */ #define BLE_SM_ERR_CMD_NOT_SUPP 0x07 + +/** SM Error Code: Unspecified Reason */ #define BLE_SM_ERR_UNSPECIFIED 0x08 + +/** SM Error Code: Repeated Attempts */ #define BLE_SM_ERR_REPEATED 0x09 + +/** SM Error Code: Invalid Parameters */ #define BLE_SM_ERR_INVAL 0x0a + +/** SM Error Code: DHKey Check failed */ #define BLE_SM_ERR_DHKEY 0x0b + +/** SM Error Code: Numeric Comparison failed */ #define BLE_SM_ERR_NUMCMP 0x0c + +/** SM Error Code: Pairing in progress */ #define BLE_SM_ERR_ALREADY 0x0d + +/** SM Error Code: Cross-transport Key Derivation/Generation not allowed */ #define BLE_SM_ERR_CROSS_TRANS 0x0e + +/** SM Error Code: Key Rejected */ #define BLE_SM_ERR_KEY_REJ 0x0f + +/** SM Error Code: Out Of Boundary Code Value */ #define BLE_SM_ERR_MAX_PLUS_1 0x10 +/** @} */ + +/** + * @defgroup ble_sm_pair_alg Security Manager (SM) Pairing Algorithms + * @{ + */ + +/** SM Pairing Algorithm: Just Works */ #define BLE_SM_PAIR_ALG_JW 0 + +/** SM Pairing Algorithm: Passkey Entry */ #define BLE_SM_PAIR_ALG_PASSKEY 1 + +/** SM Pairing Algorithm: Out Of Band */ #define BLE_SM_PAIR_ALG_OOB 2 + +/** SM Pairing Algorithm: Numeric Comparison */ #define BLE_SM_PAIR_ALG_NUMCMP 3 +/** @} */ + +/** + * @defgroup ble_sm_pair_key_dist Security Manager (SM) Key Distribution Flags + * @{ + */ + +/** SM Key Distribution: Distribute Long Term Key (LTK) */ #define BLE_SM_PAIR_KEY_DIST_ENC 0x01 + +/** SM Key Distribution: Distribute Identity Resolving Key (IRK) */ #define BLE_SM_PAIR_KEY_DIST_ID 0x02 + +/** SM Key Distribution: Distribute Connection Signature Resolving Key (CSRK) */ #define BLE_SM_PAIR_KEY_DIST_SIGN 0x04 + +/** SM Key Distribution: Derive the Link Key from the LTK */ #define BLE_SM_PAIR_KEY_DIST_LINK 0x08 + +/** SM Key Distribution: Reserved For Future Use */ #define BLE_SM_PAIR_KEY_DIST_RESERVED 0xf0 +/** @} */ + +/** + * @defgroup ble_sm_io_cap Security Manager (SM) Input/Output Capabilities + * @{ + */ + +/** SM IO Capabilities: Display Only */ #define BLE_SM_IO_CAP_DISP_ONLY 0x00 + +/** SM IO Capabilities: Display Yes No */ #define BLE_SM_IO_CAP_DISP_YES_NO 0x01 + +/** SM IO Capabilities: Keyboard Only */ #define BLE_SM_IO_CAP_KEYBOARD_ONLY 0x02 + +/** SM IO Capabilities: No Input No Output */ #define BLE_SM_IO_CAP_NO_IO 0x03 + +/** SM IO Capabilities: Keyboard Display */ #define BLE_SM_IO_CAP_KEYBOARD_DISP 0x04 + +/** SM IO Capabilities: Reserved For Future Use */ #define BLE_SM_IO_CAP_RESERVED 0x05 +/** @} */ + +/** + * @defgroup ble_sm_pair_oob Security Manager (SM) Out Of Band Data (OOB) Flags + * @{ + */ + +/** SM OOB: Out Of Band Data Not Available */ #define BLE_SM_PAIR_OOB_NO 0x00 + +/** SM OOB: Out Of Band Data Available */ #define BLE_SM_PAIR_OOB_YES 0x01 + +/** SM OOB: Reserved For Future Use */ #define BLE_SM_PAIR_OOB_RESERVED 0x02 +/** @} */ + +/** + * @defgroup ble_sm_authreq Security Manager (SM) Authentication Requirements Flags + * @{ + */ + +/** SM Authentication Requirement: Bonding */ #define BLE_SM_PAIR_AUTHREQ_BOND 0x01 + +/** SM Authentication Requirement: MITM protection */ #define BLE_SM_PAIR_AUTHREQ_MITM 0x04 + +/** SM Authentication Requirement: Secure Connections */ #define BLE_SM_PAIR_AUTHREQ_SC 0x08 + +/** SM Authentication Requirement: Keypress notifications */ #define BLE_SM_PAIR_AUTHREQ_KEYPRESS 0x10 + +/** SM Authentication Requirement: Reserved For Future Use */ #define BLE_SM_PAIR_AUTHREQ_RESERVED 0xe2 +/** @} */ + +/** + * @defgroup ble_sm_pair_key_sz Security Manager (SM) Key Sizes + * @{ + */ + +/** SM Key Size: Minimum supported encryption key size in octets */ #define BLE_SM_PAIR_KEY_SZ_MIN 7 + +/** SM Key Size: Maximum supported encryption key size in octets */ #define BLE_SM_PAIR_KEY_SZ_MAX 16 -/* +/** @} */ + +/** + * @defgroup ble_sm_ioact Security Manager (SM) Key Generation Action + * @{ * The security manager asks the application to perform a key generation * action. The application passes the passkey back to SM via * ble_sm_inject_io(). */ + +/** SM IO Action: None (Just Works pairing) */ #define BLE_SM_IOACT_NONE 0 + +/** SM IO Action: Out Of Band (OOB) */ #define BLE_SM_IOACT_OOB 1 + +/** SM IO Action: Input (Passkey Entry) */ #define BLE_SM_IOACT_INPUT 2 + +/** SM IO Action: Passkey Display */ #define BLE_SM_IOACT_DISP 3 + +/** SM IO Action: Numeric Comparison */ #define BLE_SM_IOACT_NUMCMP 4 + +/** SM IO Action: Out Of Band (OOB) Secure Connections */ #define BLE_SM_IOACT_OOB_SC 5 + +/** SM IO Action: Out Of Boundary Code Value */ #define BLE_SM_IOACT_MAX_PLUS_ONE 6 +/** @} */ + +/** Represents Out Of Band (OOB) data used in Secure Connections pairing */ struct ble_sm_sc_oob_data { /** Random Number. */ uint8_t r[16]; @@ -97,24 +251,100 @@ struct ble_sm_sc_oob_data { uint8_t c[16]; }; +/** Represents Input/Output data for Security Manager used during pairing process */ struct ble_sm_io { + /** Pairing action, indicating the type of pairing method. Can be one of the + * following: + * o BLE_SM_IOACT_NONE + * o BLE_SM_IOACT_OOB + * o BLE_SM_IOACT_INPUT + * o BLE_SM_IOACT_DISP + * o BLE_SM_IOACT_NUMCMP + * o BLE_SM_IOACT_OOB_SC + */ uint8_t action; + + /** Union holding different types of pairing data. The valid field is inferred + * from the action field. */ union { + /** Passkey value between 000000 and 999999. + * Valid for the following actions: + * o BLE_SM_IOACT_INPUT + * o BLE_SM_IOACT_DISP + */ uint32_t passkey; + + /** Temporary Key random value used in Legacy Pairing. + * Valid for the following actions: + * o BLE_SM_IOACT_OOB + */ uint8_t oob[16]; + + /** Numeric Comparison acceptance indicator. + * Valid for the following actions: + * o BLE_SM_IOACT_NUMCMP + */ uint8_t numcmp_accept; + + /** Out Of Band (OOB) data used in Secure Connections. + * Valid for the following actions: + * o BLE_SM_IOACT_OOB_SC + */ struct { - struct ble_sm_sc_oob_data *local; + /** Remote Secure Connections Out Of Band (OOB) data */ struct ble_sm_sc_oob_data *remote; + /** Local Secure Connections Out Of Band (OOB) data */ + struct ble_sm_sc_oob_data *local; } oob_sc_data; }; }; +/** + * Generates Out of Band (OOB) data used during the authentication process. + * The data consists of 128-bit Random Number and 128-bit Confirm Value. + * + * @param oob_data A pointer to the structure where the generated + * OOB data will be stored. + * + * @return 0 on success; + * Non-zero on failure. + */ int ble_sm_sc_oob_generate_data(struct ble_sm_sc_oob_data *oob_data); +#if MYNEWT_VAL(BLE_SM_CSIS_SIRK) +/** + * Resolves CSIS RSI to check if advertising device is part of the same Coordinated Set, + * as the device with specified SIRK + * + * @param rsi RSI value from Advertising Data + * @param sirk SIRK + * @param ltk_peer_addr If SIRK is in plaintext form this should be set to NULL, + * otherwise peer address should be passed here to get + * LTK and decrypt SIRK + * + * @return 0 if RSI was resolved succesfully; nonzero on failure. + */ +int ble_sm_csis_resolve_rsi(const uint8_t *rsi, const uint8_t *sirk, + const ble_addr_t *ltk_peer_addr); +#endif + #if NIMBLE_BLE_SM +/** + * @brief Passes the IO data from an application to the Security Manager during the pairing + * process. + * + * It should be used after a pairing method has been established for given connection + * and once the appropriate key generation information (e.g. passkey) has been obtained. + * + * @param conn_handle The connection handle of the relevant connection. + * @param pkey A pointer to the structure where IO data is stored. + * + * @return 0 on success; + * Non-zero on failure. + */ int ble_sm_inject_io(uint16_t conn_handle, struct ble_sm_io *pkey); #else +/** This macro replaces the function to return BLE_HS_ENOTSUP when SM is disabled. */ #define ble_sm_inject_io(conn_handle, pkey) \ ((void)(conn_handle), BLE_HS_ENOTSUP) #endif @@ -123,4 +353,8 @@ int ble_sm_inject_io(uint16_t conn_handle, struct ble_sm_io *pkey); } #endif -#endif +/** + * @} + */ + +#endif /* H_BLE_SM_ */ diff --git a/src/nimble/nimble/host/include/host/ble_store.h b/src/nimble/nimble/host/include/host/ble_store.h index 8fcfb4871..c2a0c1c0f 100644 --- a/src/nimble/nimble/host/include/host/ble_store.h +++ b/src/nimble/nimble/host/include/host/ble_store.h @@ -20,6 +20,13 @@ #ifndef H_BLE_STORE_ #define H_BLE_STORE_ +/** + * @brief Bluetooth Store API + * @defgroup bt_store Bluetooth Store + * @ingroup bt_host + * @{ + */ + #include #include "nimble/nimble/include/nimble/ble.h" @@ -27,9 +34,20 @@ extern "C" { #endif -#define BLE_STORE_OBJ_TYPE_OUR_SEC 1 -#define BLE_STORE_OBJ_TYPE_PEER_SEC 2 -#define BLE_STORE_OBJ_TYPE_CCCD 3 +/** + * @defgroup bt_store_obj_types Bluetooth Store Object Types + * @ingroup bt_host + * @{ + */ +/** Object type: Our security material. */ +#define BLE_STORE_OBJ_TYPE_OUR_SEC 1 + +/** Object type: Peer security material. */ +#define BLE_STORE_OBJ_TYPE_PEER_SEC 2 + +/** Object type: Client Characteristic Configuration Descriptor. */ +#define BLE_STORE_OBJ_TYPE_CCCD 3 + #define BLE_STORE_OBJ_TYPE_PEER_DEV_REC 4 #if MYNEWT_VAL(ENC_ADV_DATA) @@ -37,14 +55,24 @@ extern "C" { #endif #define BLE_STORE_OBJ_TYPE_PEER_ADDR 6 -#define BLE_STORE_OBJ_TYPE_LOCAL_IRK 7 +#define BLE_STORE_OBJ_TYPE_LOCAL_IRK 7 #define BLE_STORE_OBJ_TYPE_CSFC 8 + +/** @} */ + +/** + * @defgroup bt_store_event_types Bluetooth Store Event Types + * @ingroup bt_host + * @{ + */ /** Failed to persist record; insufficient storage capacity. */ #define BLE_STORE_EVENT_OVERFLOW 1 /** About to execute a procedure that may fail due to overflow. */ #define BLE_STORE_EVENT_FULL 2 +/** @} */ + /** * Used as a key for lookups of security material. This struct corresponds to * the following store object types: @@ -69,23 +97,39 @@ struct ble_store_key_sec { * o BLE_STORE_OBJ_TYPE_PEER_SEC */ struct ble_store_value_sec { + /** Peer address for which the security material is stored. */ ble_addr_t peer_addr; + + /* Espressif added for bond age tracking persistence */ uint16_t bond_count; + /** Encryption key size. */ uint8_t key_size; + /** Encrypted Diversifier used for encryption key generation. */ uint16_t ediv; + /** Random number used for encryption key generation. */ uint64_t rand_num; + /** Long Term Key. */ uint8_t ltk[16]; + /** Flag indicating whether Long Term Key is present. */ uint8_t ltk_present:1; + /** Identity Resolving Key. */ uint8_t irk[16]; + /** Flag indicating whether Identity Resolving Key is present. */ uint8_t irk_present:1; + /** Connection Signature Resolving Key. */ uint8_t csrk[16]; + /** Flag indicating if Connection Signature Resolving Key is present. */ uint8_t csrk_present:1; + + /* Espressif added for signed write support */ uint32_t sign_counter; + /** Flag indicating whether the connection is authenticated. */ unsigned authenticated:1; + /** Flag indicating Secure Connections support. */ uint8_t sc:1; }; @@ -116,9 +160,13 @@ struct ble_store_key_cccd { * This struct corresponds to the BLE_STORE_OBJ_TYPE_CCCD store object type. */ struct ble_store_value_cccd { + /** The peer address associated with the stored CCCD. */ ble_addr_t peer_addr; + /** The handle of the characteristic value. */ uint16_t chr_val_handle; + /** Flags associated with the CCCD. */ uint16_t flags; + /** Flag indicating whether the value has changed. */ unsigned value_changed:1; }; @@ -188,6 +236,7 @@ struct ble_store_key_rpa_rec{ ble_addr_t peer_rpa_addr; uint8_t idx; }; + struct ble_store_value_rpa_rec{ ble_addr_t peer_rpa_addr; ble_addr_t peer_addr; @@ -198,7 +247,9 @@ struct ble_store_value_rpa_rec{ * object type code to indicate which field is valid. */ union ble_store_key { + /** Key for security material store lookups. */ struct ble_store_key_sec sec; + /** Key for Client Characteristic Configuration Descriptor store lookups. */ struct ble_store_key_cccd cccd; #if MYNEWT_VAL(ENC_ADV_DATA) struct ble_store_key_ead ead; @@ -213,16 +264,19 @@ union ble_store_key { * code to indicate which field is valid. */ union ble_store_value { + /** Stored security material. */ struct ble_store_value_sec sec; + /** Stored Client Characteristic Configuration Descriptor. */ struct ble_store_value_cccd cccd; #if MYNEWT_VAL(ENC_ADV_DATA) struct ble_store_value_ead ead; #endif - struct ble_store_value_rpa_rec rpa_rec; - struct ble_store_value_local_irk local_irk; - struct ble_store_value_csfc csfc; + struct ble_store_value_rpa_rec rpa_rec; + struct ble_store_value_local_irk local_irk; + struct ble_store_value_csfc csfc; }; +/** Represents an event associated with the BLE Store. */ struct ble_store_status_event { /** * The type of event being reported; one of the BLE_STORE_EVENT_TYPE_[...] @@ -263,20 +317,26 @@ struct ble_store_status_event { }; }; -/* Generate LTK, EDIT and Rand */ +/** Generate LTK, EDIT and Rand. */ #define BLE_STORE_GEN_KEY_LTK 0x01 -/* Generate IRK */ +/** Generate IRK. */ #define BLE_STORE_GEN_KEY_IRK 0x02 -/* Generate CSRK */ +/** Generate CSRK. */ #define BLE_STORE_GEN_KEY_CSRK 0x03 +/** Represents a storage for generated key. */ struct ble_store_gen_key { union { + /** Long Term Key (LTK) for peripheral role. */ uint8_t ltk_periph[16]; + /** Identity Resolving Key (IRK). */ uint8_t irk[16]; + /** Connection Signature Resolving Key (CSRK). */ uint8_t csrk[16]; }; + /** Encrypted Diversifier (EDIV). */ uint16_t ediv; + /** Random Number for key generation. */ uint64_t rand; }; @@ -366,25 +426,234 @@ typedef int ble_store_delete_fn(int obj_type, const union ble_store_key *key); typedef int ble_store_status_fn(struct ble_store_status_event *event, void *arg); +/** + * Reads data from a storage. + * + * @param obj_type The type of the object to read. + * @param key Pointer to the key used for the lookup. + * @param val Pointer to store the retrieved data. + * + * @return 0 if the read operation is successful; + * Non-zero on error. + */ int ble_store_read(int obj_type, const union ble_store_key *key, union ble_store_value *val); + +/** + * Writes data to a storage. + * + * @param obj_type The type of the object to write. + * @param val Pointer to the data to be written. + * + * @return 0 if the write operation is successful; + * Non-zero on error. + */ int ble_store_write(int obj_type, const union ble_store_value *val); + +/** + * Deletes data from a storage. + * + * @param obj_type The type of the object to delete. + * @param key Pointer to the key used for the lookup. + * + * @return 0 if the deletion operation is successful; + * Non-zero on error. + */ int ble_store_delete(int obj_type, const union ble_store_key *key); + +/** + * @brief Handles a storage overflow event. + * + * This function is called when a storage overflow event occurs. It constructs + * an event structure and passes it to the general storage status handler using + * the `ble_store_status` function. + * + * @param obj_type The type of the object for which the overflow + * occurred. + * @param value Pointer to the value associated with the + * overflow. + * + * @return 0 if the event is successfully handled; + * Non-zero on error. + */ int ble_store_overflow_event(int obj_type, const union ble_store_value *value); + +/** + * @brief Handles a storage full event. + * + * This function is called when a storage full event occurs, typically during + * a write operation. It constructs an event structure and passes it to the + * general storage status handler using the `ble_store_status` function. + * + * @param obj_type The type of the object that may fail to be + * written. + * @param conn_handle The connection handle associated with the write + * operation. + * + * @return 0 if the event is successfully handled; + * Non-zero on error. + */ int ble_store_full_event(int obj_type, uint16_t conn_handle); +/** + * @brief Reads our security material from a storage. + * + * This function reads our security material from a storage, using the provided + * key and populates the `ble_store_value_sec` structure with the retrieved data. + * + * @param key_sec The key identifying the security material to + * read. + * @param value_sec A pointer to a `ble_store_value_sec` structure + * where the retrieved security material will + * be stored. + * + * @return 0 if the security material was successfully read + * from a storage; + * Non-zero on error. + */ int ble_store_read_our_sec(const struct ble_store_key_sec *key_sec, struct ble_store_value_sec *value_sec); + +/** + * @brief Writes our security material to a storage. + * + * This function writes our security material to a storage, using the provided + * `ble_store_value_sec` structure. + * + * @param value_sec A pointer to a `ble_store_value_sec` structure + * containing the security material to be + * stored. + * + * @return 0 if the security material was successfully + * written to a storage; + * Non-zero on error. + */ int ble_store_write_our_sec(const struct ble_store_value_sec *value_sec); + +/** + * @brief Deletes our security material from a storage. + * + * This function deletes our security material from a storage, identified by the + * provided `ble_store_key_sec`. + * + * @param key_sec A pointer to a `ble_store_key_sec` structure + * that specifies the security material to be + * deleted. + * + * @return 0 if the security material was successfully + * deleted from a storage; + * Non-zero on error. + */ int ble_store_delete_our_sec(const struct ble_store_key_sec *key_sec); + +/** + * @brief Reads peer security material from a storage. + * + * This function reads peer security material from a storage, identified by the + * provided `ble_store_key_sec`. The retrieved security material is stored in + * the `ble_store_value_sec` structure. + * + * @param key_sec A pointer to a `ble_store_key_sec` structure + * that specifies the peer's security material + * to be retrieved. + * @param value_sec A pointer to a `ble_store_value_sec` structure + * where the retrieved security material will + * be stored. + * + * @return 0 if the security material was successfully + * retrieved; + * Non-zero on error. + */ int ble_store_read_peer_sec(const struct ble_store_key_sec *key_sec, struct ble_store_value_sec *value_sec); + +/** + * @brief Writes peer security material to a storage. + * + * This function writes the provided peer security material, specified by a + * `ble_store_value_sec` structure, to a storage. Additionally, if the provided + * peer IRK is present and the peer address is not `BLE_ADDR_ANY`, it is also + * written to the controller's key cache. + * + * @param value_sec A pointer to a `ble_store_value_sec` structure + * containing the peer's security material + * to be written. + * + * @return 0 if the peer's security material was + * successfully written to a storage and + * the peer IRK was added to the controller key + * cache if present; + * Non-zero on error. + */ int ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec); + +/** + * @brief Deletes peer security material from a storage. + * + * This function deletes the peer security material associated with the provided + * key from a storage. + * + * @param key_sec A pointer to a `ble_store_key_sec` structure + * identifying the security material to be + * deleted. + * + * @return 0 if the peer's security material was + * successfully deleted from a storage; + * Non-zero on error. + */ int ble_store_delete_peer_sec(const struct ble_store_key_sec *key_sec); + +/** + * @brief Reads a Client Characteristic Configuration Descriptor (CCCD) from + * a storage. + * + * This function reads a CCCD from a storage based on the provided key and + * stores the retrieved value in the specified output structure. + * + * @param key A pointer to a `ble_store_key_cccd` structure + * representing the key to identify the CCCD to + * be read. + * @param out_value A pointer to a `ble_store_value_cccd` structure + * to store the CCCD value read from a storage. + * + * @return 0 if the CCCD was successfully read and stored + * in the `out_value` structure; + * Non-zero on error. + */ int ble_store_read_cccd(const struct ble_store_key_cccd *key, struct ble_store_value_cccd *out_value); + +/** + * @brief Writes a Client Characteristic Configuration Descriptor (CCCD) to + * a storage. + * + * This function writes a CCCD to a storage based on the provided value. + * + * @param value A pointer to a `ble_store_value_cccd` structure + * representing the CCCD value to be written to + * a storage. + * + * @return 0 if the CCCD was successfully written to + * a storage; + * Non-zero on error. + */ int ble_store_write_cccd(const struct ble_store_value_cccd *value); + +/** + * @brief Deletes a Client Characteristic Configuration Descriptor (CCCD) from + * a storage. + * + * This function deletes a CCCD from a storage based on the provided key. + * + * @param key A pointer to a `ble_store_key_cccd` structure + * identifying the CCCD to be deleted from + * a storage. + * + * @return 0 if the CCCD was successfully deleted from + * a storage; + * Non-zero on error. + */ int ble_store_delete_cccd(const struct ble_store_key_cccd *key); int ble_store_read_csfc(const struct ble_store_key_csfc *key, @@ -392,10 +661,36 @@ int ble_store_read_csfc(const struct ble_store_key_csfc *key, int ble_store_write_csfc(const struct ble_store_value_csfc *value); int ble_store_delete_csfc(const struct ble_store_key_csfc *key); +/** + * @brief Generates a storage key for a security material entry from its value. + * + * This function generates a storage key for a security material entry based on + * the provided security material value. + * + * @param out_key A pointer to a `ble_store_key_sec` structure + * where the generated key will be stored. + * @param value A pointer to a `ble_store_value_sec` structure + * containing the security material value from + * which the key will be generated. + */ void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, const struct ble_store_value_sec *value); + +/** + * @brief Generates a storage key for a CCCD entry from its value. + * + * This function generates a storage key for a Client Characteristic + * Configuration Descriptor (CCCD) entry based on the provided CCCD value. + * + * @param out_key A pointer to a `ble_store_key_cccd` structure + * where the generated key will be stored. + * @param value A pointer to a `ble_store_value_cccd` structure + * containing the CCCD value from which the key + * will be generated. + */ void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, const struct ble_store_value_cccd *value); + void ble_store_key_from_value_csfc(struct ble_store_key_csfc *out_key, const struct ble_store_value_csfc *value); @@ -409,48 +704,185 @@ void ble_store_key_from_value_ead(struct ble_store_key_ead *out_key, #endif /* irk store*/ int ble_store_read_local_irk(const struct ble_store_key_local_irk *key, - struct ble_store_value_local_irk *out_value); + struct ble_store_value_local_irk *out_value); int ble_store_write_local_irk(const struct ble_store_value_local_irk *value); int ble_store_delete_local_irk(const struct ble_store_key_local_irk *key); void ble_store_key_from_value_local_irk(struct ble_store_key_local_irk *out_key, - const struct ble_store_value_local_irk *value); - + const struct ble_store_value_local_irk *value); /*irk store */ /* rpa mapping*/ int ble_store_read_rpa_rec(const struct ble_store_key_rpa_rec *key, - struct ble_store_value_rpa_rec *out_value); + struct ble_store_value_rpa_rec *out_value); int ble_store_write_rpa_rec(const struct ble_store_value_rpa_rec *value); int ble_store_delete_rpa_rec(const struct ble_store_key_rpa_rec *key); void ble_store_key_from_value_rpa_rec(struct ble_store_key_rpa_rec *out_key, - const struct ble_store_value_rpa_rec *value); + const struct ble_store_value_rpa_rec *value); /* rpa mapping*/ + +/** + * @brief Generates a storage key from a value based on the object type. + * + * This function generates a storage key from a value based on the provided + * object type. + * + * @param obj_type The type of object for which the key is + * generated. + * @param out_key A pointer to a `ble_store_key` union where + * the generated key will be stored. + * @param value A pointer to a `ble_store_value` union + * containing the value from which the key will + * be generated. + */ void ble_store_key_from_value(int obj_type, union ble_store_key *out_key, const union ble_store_value *value); + +/** + * @brief Function signature for the storage iterator callback. + * + * This function signature represents a callback function used for iterating + * over stored objects in a store. + * + * @param obj_type The type of object being iterated. + * @param val A pointer to the stored value of the object. + * @param cookie A user-defined pointer for additional data. + * + * @return 0 to continue iterating; + * Non-zero value to stop the iteration. + */ typedef int ble_store_iterator_fn(int obj_type, union ble_store_value *val, void *cookie); + +/** + * @brief Iterates over stored objects of a specific type in a store. + * + * This function allows you to iterate over stored objects of a specific type in + * the store and invoke a user-defined callback function for each object. + * + * @param obj_type The type of objects to iterate over. + * @param callback A pointer to the user-defined callback function + * that will be invoked for each stored object. + * @param cookie A user-defined pointer for additional data to + * pass to the callback function. + * + * @return 0 on success; + * Non-zero on error. + */ int ble_store_iterate(int obj_type, ble_store_iterator_fn *callback, void *cookie); + +/** + * @brief Clears all stored objects from a store. + * + * This function removes all stored objects from a store, effectively clearing + * the storage. + * + * @return 0 on success; + * Non-zero on error. + */ int ble_store_clear(void); -/*** Utility functions. */ +/** + * @defgroup ble_store_util Bluetooth Store Utility Functions + * @{ + */ +/** + * Retrieves the set of peer addresses for which a bond has been established. + * + * @param out_peer_id_addrs The set of bonded peer addresses. + * @param out_num_peers The number of bonds that have been established. + * @param max_peers The capacity of the destination buffer. + * + * @return 0 on success; + * BLE_HS_ENOMEM if the destination buffer is too + * small; + * Other non-zero on error. + */ int ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers, int max_peers); + +/** + * Deletes all entries from a store that match the specified key. + * + * @param type The type of store entry to delete. + * @param key Entries matching this key get deleted. + * + * @return 0 on success; + * Non-zero on error. + */ int ble_store_util_delete_all(int type, const union ble_store_key *key); + +/** + * Deletes all entries from a store that are attached to the specified peer + * address. This function deletes security entries and CCCD records. + * + * @param peer_id_addr Entries with this peer address get deleted. + * + * @return 0 on success; + * Non-zero on error. + */ int ble_store_util_delete_peer(const ble_addr_t *peer_id_addr); + +/** + * @brief Deletes the oldest peer from a store. + * + * This function deletes the oldest bonded peer from the storage. If there are + * no bonded peers in the storage, the function returns success. + * + * @return 0 on success; + * Non-zero on error. + */ int ble_store_util_delete_oldest_peer(void); + +/** + * @brief Counts the number of stored objects of a given type. + * + * This function counts the number of stored objects of a specific type in + * a store and returns the count in the `out_count` parameter. + * + * @param type The type of the objects to count. + * @param out_count The count of stored objects. + * + * @return 0 on success; + * Non-zero on error. + */ int ble_store_util_count(int type, int *out_count); + +/** + * @brief Round-robin status callback for handling store status events. + * + * This function handles store status events, particularly in cases where there + * is insufficient storage capacity for new records. + * It attempts to resolve overflow issues by deleting the oldest bond and + * proceeds with the persist operation. + * + * @note This behavior may not be suitable for production use as it may lead to + * removal of important bonds by less relevant peers. It is more useful for + * demonstration purposes and sample applications. + * + * @param event A pointer to the store status event. + * @param arg A pointer to additional user-defined arguments. + * + * @return 0 on success; + * Non-zero on error. + */ int ble_store_util_status_rr(struct ble_store_status_event *event, void *arg); +/** @} */ + #ifdef __cplusplus } #endif +/** + * @} + */ + #endif diff --git a/src/nimble/nimble/host/include/host/ble_uuid.h b/src/nimble/nimble/host/include/host/ble_uuid.h index 54d2b5e2f..16ba4157f 100644 --- a/src/nimble/nimble/host/include/host/ble_uuid.h +++ b/src/nimble/nimble/host/include/host/ble_uuid.h @@ -130,6 +130,16 @@ typedef union { .value = (uuid32), \ } +/** + * @brief Macro for initializing a 128-bit UUID. + * + * This macro initializes a 128-bit UUID with the provided value. + * + * @param ... A sequence of values in little-endian order representing + * the 128-bit UUID. + * + * @return The initialized 128-bit UUID structure. + */ #define BLE_UUID128_INIT(uuid128 ...) \ { \ .u = { \ @@ -139,7 +149,8 @@ typedef union { } /** - * @brief Macro for declaring a pointer to a 16-bit UUID structure initialized with a specific 16-bit UUID value. + * @brief Macro for declaring a pointer to a 16-bit UUID structure initialized + * with a specific 16-bit UUID value. * * @param uuid16 The 16-bit UUID value to initialize the structure with. * @@ -149,7 +160,8 @@ typedef union { ((ble_uuid_t *) (&(ble_uuid16_t) BLE_UUID16_INIT(uuid16))) /** - * @brief Macro for declaring a pointer to a 32-bit UUID structure initialized with a specific 32-bit UUID value. + * @brief Macro for declaring a pointer to a 32-bit UUID structure initialized + * with a specific 32-bit UUID value. * * @param uuid32 The 32-bit UUID value to initialize the structure with. * @@ -159,7 +171,8 @@ typedef union { ((ble_uuid_t *) (&(ble_uuid32_t) BLE_UUID32_INIT(uuid32))) /** - * @brief Macro for declaring a pointer to a 128-bit UUID structure initialized with specific 128-bit UUID values. + * @brief Macro for declaring a pointer to a 128-bit UUID structure initialized + * with specific 128-bit UUID values. * * @param uuid128 The 128-bit UUID value to initialize the structure with. * @@ -169,7 +182,8 @@ typedef union { ((ble_uuid_t *) (&(ble_uuid128_t) BLE_UUID128_INIT(uuid128))) /** - * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer to 16-bit UUID structure. + * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer + * to 16-bit UUID structure. * * @param u Pointer to a `ble_uuid_t` structure. * @@ -179,7 +193,8 @@ typedef union { ((ble_uuid16_t *) (u)) /** - * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer to 32-bit UUID structure. + * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer + * to 32-bit UUID structure. * * @param u Pointer to a `ble_uuid_t` structure. * @@ -189,7 +204,8 @@ typedef union { ((ble_uuid32_t *) (u)) /** - * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer to 128-bit UUID structure. + * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer + * to 128-bit UUID structure. * * @param u Pointer to a `ble_uuid_t` structure. * @@ -209,8 +225,8 @@ typedef union { * @param buf The source buffer to parse. * @param len The size of the buffer, in bytes. * - * @return 0 on success, BLE_HS_EINVAL if the source buffer does not contain - * a valid UUID. + * @return 0 on success; + * BLE_HS_EINVAL if the source buffer does not contain a valid UUID. */ int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len); @@ -219,7 +235,8 @@ int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len); * @param uuid1 The first UUID to compare. * @param uuid2 The second UUID to compare. * - * @return 0 if the two UUIDs are equal, nonzero if the UUIDs differ. + * @return 0 if the two UUIDs are equal; + * nonzero if the UUIDs differ. */ int ble_uuid_cmp(const ble_uuid_t *uuid1, const ble_uuid_t *uuid2); @@ -280,4 +297,4 @@ uint16_t ble_uuid_u16(const ble_uuid_t *uuid); * @} */ -#endif /* _BLE_HOST_UUID_H */ +#endif /* H_BLE_UUID_ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/access.h b/src/nimble/nimble/host/mesh/include/mesh/access.h deleted file mode 100644 index f552b584c..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/access.h +++ /dev/null @@ -1,628 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Access Layer APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_ACCESS_H -#define __BT_MESH_ACCESS_H - -#include "msg.h" -#include - -/** - * @brief Bluetooth Mesh Access Layer - * @defgroup bt_mesh_access Bluetooth Mesh Access Layer - * @ingroup bt_mesh - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#define BT_MESH_ADDR_UNASSIGNED 0x0000 -#define BT_MESH_ADDR_ALL_NODES 0xffff -#define BT_MESH_ADDR_PROXIES 0xfffc -#define BT_MESH_ADDR_FRIENDS 0xfffd -#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 - * macro BT_MESH_MODEL_NONE can be given instead. - * - * @param _loc Location Descriptor. - * @param _mods Array of models. - * @param _vnd_mods Array of vendor models. - */ -#define BT_MESH_ELEM(_loc, _mods, _vnd_mods) \ -{ \ - .loc = (_loc), \ - .model_count = ARRAY_SIZE(_mods), \ - .models = (_mods), \ - .vnd_model_count = ARRAY_SIZE(_vnd_mods), \ - .vnd_models = (_vnd_mods), \ -} - -/** Abstraction that describes a Mesh Element */ -struct bt_mesh_elem { - /* Unicast Address. Set at runtime during provisioning. */ - uint16_t addr; - - /* Location Descriptor (GATT Bluetooth Namespace Descriptors) */ - const uint16_t loc; - - const uint8_t model_count; - const uint8_t vnd_model_count; - - struct bt_mesh_model * const models; - struct bt_mesh_model * const vnd_models; -}; - -/* Foundation Models */ -#define BT_MESH_MODEL_ID_CFG_SRV 0x0000 -#define BT_MESH_MODEL_ID_CFG_CLI 0x0001 -#define BT_MESH_MODEL_ID_HEALTH_SRV 0x0002 -#define BT_MESH_MODEL_ID_HEALTH_CLI 0x0003 - -/* Models from the Mesh Model Specification */ -#define BT_MESH_MODEL_ID_GEN_ONOFF_SRV 0x1000 -#define BT_MESH_MODEL_ID_GEN_ONOFF_CLI 0x1001 -#define BT_MESH_MODEL_ID_GEN_LEVEL_SRV 0x1002 -#define BT_MESH_MODEL_ID_GEN_LEVEL_CLI 0x1003 -#define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV 0x1004 -#define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI 0x1005 -#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV 0x1006 -#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV 0x1007 -#define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI 0x1008 -#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV 0x1009 -#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV 0x100a -#define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI 0x100b -#define BT_MESH_MODEL_ID_GEN_BATTERY_SRV 0x100c -#define BT_MESH_MODEL_ID_GEN_BATTERY_CLI 0x100d -#define BT_MESH_MODEL_ID_GEN_LOCATION_SRV 0x100e -#define BT_MESH_MODEL_ID_GEN_LOCATION_SETUPSRV 0x100f -#define BT_MESH_MODEL_ID_GEN_LOCATION_CLI 0x1010 -#define BT_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV 0x1011 -#define BT_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV 0x1012 -#define BT_MESH_MODEL_ID_GEN_USER_PROP_SRV 0x1013 -#define BT_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV 0x1014 -#define BT_MESH_MODEL_ID_GEN_PROP_CLI 0x1015 -#define BT_MESH_MODEL_ID_SENSOR_SRV 0x1100 -#define BT_MESH_MODEL_ID_SENSOR_SETUP_SRV 0x1101 -#define BT_MESH_MODEL_ID_SENSOR_CLI 0x1102 -#define BT_MESH_MODEL_ID_TIME_SRV 0x1200 -#define BT_MESH_MODEL_ID_TIME_SETUP_SRV 0x1201 -#define BT_MESH_MODEL_ID_TIME_CLI 0x1202 -#define BT_MESH_MODEL_ID_SCENE_SRV 0x1203 -#define BT_MESH_MODEL_ID_SCENE_SETUP_SRV 0x1204 -#define BT_MESH_MODEL_ID_SCENE_CLI 0x1205 -#define BT_MESH_MODEL_ID_SCHEDULER_SRV 0x1206 -#define BT_MESH_MODEL_ID_SCHEDULER_SETUP_SRV 0x1207 -#define BT_MESH_MODEL_ID_SCHEDULER_CLI 0x1208 -#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV 0x1300 -#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV 0x1301 -#define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI 0x1302 -#define BT_MESH_MODEL_ID_LIGHT_CTL_SRV 0x1303 -#define BT_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV 0x1304 -#define BT_MESH_MODEL_ID_LIGHT_CTL_CLI 0x1305 -#define BT_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV 0x1306 -#define BT_MESH_MODEL_ID_LIGHT_HSL_SRV 0x1307 -#define BT_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV 0x1308 -#define BT_MESH_MODEL_ID_LIGHT_HSL_CLI 0x1309 -#define BT_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV 0x130a -#define BT_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV 0x130b -#define BT_MESH_MODEL_ID_LIGHT_XYL_SRV 0x130c -#define BT_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV 0x130d -#define BT_MESH_MODEL_ID_LIGHT_XYL_CLI 0x130e -#define BT_MESH_MODEL_ID_LIGHT_LC_SRV 0x130f -#define BT_MESH_MODEL_ID_LIGHT_LC_SETUPSRV 0x1310 -#define BT_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311 - -struct bt_mesh_model_op { - /* OpCode encoded using the BT_MESH_MODEL_OP_* macros */ - const uint32_t opcode; - - /** Message length. If the message has variable length then this value - * indicates minimum message length and should be positive. Handler - * function should verify precise length based on the contents of the - * message. If the message has fixed length then this value should - * be negative. Use BT_MESH_LEN_* macros when defining this value. - */ - const ssize_t len; - - /* Message handler for the opcode */ - int (*const func)(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf); -}; - -#define BT_MESH_MODEL_OP_1(b0) (b0) -#define BT_MESH_MODEL_OP_2(b0, b1) (((b0) << 8) | (b1)) -#define BT_MESH_MODEL_OP_3(b0, cid) ((((b0) << 16) | 0xc00000) | (cid)) - -/** Macro for encoding exact message length for fixed-length messages. */ -#define BT_MESH_LEN_EXACT(len) (-len) -/** Macro for encoding minimum message length for variable-length messages. */ -#define BT_MESH_LEN_MIN(len) (len) - -#define BT_MESH_MODEL_OP_END { 0, 0, NULL } -#define BT_MESH_MODEL_NO_OPS ((struct bt_mesh_model_op []) \ - { BT_MESH_MODEL_OP_END }) - -/** Helper to define an empty model array */ -#define BT_MESH_MODEL_NONE ((struct bt_mesh_model []){}) - -/** @def BT_MESH_MODEL_CB - * - * @brief Composition data SIG model entry with callback functions. - * - * @param _id Model ID. - * @param _op Array of model opcode handlers. - * @param _pub Model publish parameters. - * @param _user_data User data for the model. - * @param _cb Callback structure, or NULL to keep no callbacks. - */ -#define BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, _cb) \ -{ \ - .id = (_id), \ - .op = _op, \ - .keys = { [0 ... (CONFIG_BT_MESH_MODEL_KEY_COUNT - 1)] = \ - BT_MESH_KEY_UNUSED }, \ - .pub = _pub, \ - .groups = { [0 ... (CONFIG_BT_MESH_MODEL_GROUP_COUNT - 1)] = \ - BT_MESH_ADDR_UNASSIGNED }, \ - .user_data = _user_data, \ - .cb = _cb, \ -} - -/** @def BT_MESH_MODEL_VND_CB - * - * @brief Composition data vendor model entry with callback functions. - * - * @param _company Company ID. - * @param _id Model ID. - * @param _op Array of model opcode handlers. - * @param _pub Model publish parameters. - * @param _user_data User data for the model. - * @param _cb Callback structure, or NULL to keep no callbacks. - */ -#define BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, _cb) \ -{ \ - .vnd.company = (_company), \ - .vnd.id = (_id), \ - .op = _op, \ - .pub = _pub, \ - .keys = { [0 ... (CONFIG_BT_MESH_MODEL_KEY_COUNT - 1)] = \ - BT_MESH_KEY_UNUSED }, \ - .groups = { [0 ... (CONFIG_BT_MESH_MODEL_GROUP_COUNT - 1)] = \ - BT_MESH_ADDR_UNASSIGNED }, \ - .user_data = _user_data, \ - .cb = _cb, \ -} - - -/** @def BT_MESH_MODEL - * - * @brief Composition data SIG model entry. - * - * @param _id Model ID. - * @param _op Array of model opcode handlers. - * @param _pub Model publish parameters. - * @param _user_data User data for the model. - */ -#define BT_MESH_MODEL(_id, _op, _pub, _user_data) \ - BT_MESH_MODEL_CB(_id, _op, _pub, _user_data, NULL) - -/** @def BT_MESH_MODEL_VND - * - * @brief Composition data vendor model entry. - * - * @param _company Company ID. - * @param _id Model ID. - * @param _op Array of model opcode handlers. - * @param _pub Model publish parameters. - * @param _user_data User data for the model. - */ -#define BT_MESH_MODEL_VND(_company, _id, _op, _pub, _user_data) \ - BT_MESH_MODEL_VND_CB(_company, _id, _op, _pub, _user_data, NULL) - -/** @def BT_MESH_TRANSMIT - * - * @brief Encode transmission count & interval steps. - * - * @param count Number of retransmissions (first transmission is excluded). - * @param int_ms Interval steps in milliseconds. Must be greater than 0, - * less than or equal to 320, and a multiple of 10. - * - * @return Mesh transmit value that can be used e.g. for the default - * values of the configuration model data. - */ -#define BT_MESH_TRANSMIT(count, int_ms) ((count) | (((int_ms / 10) - 1) << 3)) - -/** @def BT_MESH_TRANSMIT_COUNT - * - * @brief Decode transmit count from a transmit value. - * - * @param transmit Encoded transmit count & interval value. - * - * @return Transmission count (actual transmissions is N + 1). - */ -#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (uint8_t)BIT_MASK(3))) - -/** @def BT_MESH_TRANSMIT_INT - * - * @brief Decode transmit interval from a transmit value. - * - * @param transmit Encoded transmit count & interval value. - * - * @return Transmission interval in milliseconds. - */ -#define BT_MESH_TRANSMIT_INT(transmit) ((((transmit) >> 3) + 1) * 10) - -/** @def BT_MESH_PUB_TRANSMIT - * - * @brief Encode Publish Retransmit count & interval steps. - * - * @param count Number of retransmissions (first transmission is excluded). - * @param int_ms Interval steps in milliseconds. Must be greater than 0 - * and a multiple of 50. - * - * @return Mesh transmit value that can be used e.g. for the default - * values of the configuration model data. - */ -#define BT_MESH_PUB_TRANSMIT(count, int_ms) BT_MESH_TRANSMIT(count, \ - (int_ms) / 5) - -/** @def BT_MESH_PUB_TRANSMIT_COUNT - * - * @brief Decode Pubhlish Retransmit count from a given value. - * - * @param transmit Encoded Publish Retransmit count & interval value. - * - * @return Retransmission count (actual transmissions is N + 1). - */ -#define BT_MESH_PUB_TRANSMIT_COUNT(transmit) BT_MESH_TRANSMIT_COUNT(transmit) - -/** @def BT_MESH_PUB_TRANSMIT_INT - * - * @brief Decode Publish Retransmit interval from a given value. - * - * @param transmit Encoded Publish Retransmit count & interval value. - * - * @return Transmission interval in milliseconds. - */ -#define BT_MESH_PUB_TRANSMIT_INT(transmit) ((((transmit) >> 3) + 1) * 50) - -/** Model publication context. */ -struct bt_mesh_model_pub { - /** The model the context belongs to. Initialized by the stack. */ - struct bt_mesh_model *mod; - - uint16_t addr; /**< Publish Address. */ - uint16_t key:12, /**< Publish AppKey Index. */ - cred:1, /**< Friendship Credentials Flag. */ - send_rel:1, /**< Force reliable sending (segment acks) */ - fast_period:1; /**< Use FastPeriodDivisor */ - - uint8_t ttl; /**< Publish Time to Live. */ - uint8_t retransmit; /**< Retransmit Count & Interval Steps. */ - uint8_t period; /**< Publish Period. */ - uint8_t period_div:4, /**< Divisor for the Period. */ - count:4; - - 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 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 - * @ref bt_mesh_model_pub.update callback has been called - * and returned success. The buffer must be created outside - * of function context, i.e. it must not be on the stack. - * This is most conveniently acheived by creating it inline - * when declaring the publication context: - * - * static struct bt_mesh_model_pub my_pub = { - * .msg = NET_BUF_SIMPLE(size), - * }; - */ - struct os_mbuf *msg; - - /** @brief Callback for updating the publication buffer. - * - * When set to NULL, the model is assumed not to support - * periodic publishing. When set to non-NULL the callback - * 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. - * - * @return Zero on success or (negative) error code otherwise. - */ - int (*update)(struct bt_mesh_model *mod); - - /** Publish Period Timer. Only for stack-internal use. */ - struct k_work_delayable timer; -}; - -/** Model callback functions. */ -struct bt_mesh_model_cb { - /** @brief Set value handler of user data tied to the model. - * - * @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, - const char *name, char *val); - - /** @brief Callback called when the mesh is started. - * - * 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 - * - * @param model Model this callback belongs to. - * - * @return 0 on success, error otherwise. - */ - 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. - */ - int (*const init)(struct bt_mesh_model *model); - - /** @brief Model reset callback. - * - * 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); -}; - -/** Vendor model ID */ -struct bt_mesh_mod_id_vnd { - /** Vendor's company ID */ - uint16_t company; - /** Model ID */ - uint16_t id; -}; - -/** Abstraction that describes a Mesh Model instance */ -struct bt_mesh_model { - union { - const uint16_t id; - const struct bt_mesh_mod_id_vnd vnd; - }; - - /* Internal information, mainly for persistent storage */ - 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 */ - uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT]; - - /* Subscription List (group or virtual addresses) */ - uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT]; - - const struct bt_mesh_model_op * const op; - - /* Model callback structure. */ - const struct bt_mesh_model_cb * const cb; - -#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS) - /* Pointer to the next model in a model extension list. */ - struct bt_mesh_model *next; -#endif - - /* Model-specific user data */ - void *user_data; -}; - -struct bt_mesh_send_cb { - void (*start)(uint16_t duration, int err, void *cb_data); - void (*end)(int err, void *cb_data); -}; - -/** Special TTL value to request using configured default TTL */ -#define BT_MESH_TTL_DEFAULT 0xff - -/** Maximum allowed TTL value */ -#define BT_MESH_TTL_MAX 0x7f - -/** - * @brief Send an Access Layer message. - * - * @param model Mesh (client) Model that the message belongs to. - * @param ctx Message context, includes keys, TTL, etc. - * @param msg Access Layer payload (the actual message to be sent). - * @param cb Optional "message sent" callback. - * @param cb_data User data to be passed to the callback. - * - * @return 0 on success, or (negative) error code on failure. - */ -int bt_mesh_model_send(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *msg, - const struct bt_mesh_send_cb *cb, - void *cb_data); - -/** - * @brief Send a model publication message. - * - * Before calling this function, the user needs to ensure that the model - * publication message (@ref bt_mesh_model_pub.msg) contains a valid - * message to be sent. Note that this API is only to be used for - * non-period publishing. For periodic publishing the app only needs - * to make sure that @ref bt_mesh_model_pub.msg contains a valid message - * whenever the @ref bt_mesh_model_pub.update callback is called. - * - * @param model Mesh (client) Model that's publishing the message. - * - * @return 0 on success, or (negative) error code on failure. - */ -int bt_mesh_model_publish(struct bt_mesh_model *model); - -/** - * @brief Get the element that a model belongs to. - * - * @param mod Mesh model. - * - * @return Pointer to the element that the given model belongs to. - */ -struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod); - -/** @brief Find a SIG model. - * - * @param elem Element to search for the model in. - * @param id Model ID of the model. - * - * @return A pointer to the Mesh model matching the given parameters, or NULL - * 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, - uint16_t id); - -/** @brief Find a vendor model. - * - * @param elem Element to search for the model in. - * @param company Company ID of the model. - * @param id Model ID of the model. - * - * @return A pointer to the Mesh model matching the given parameters, or NULL - * 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, - uint16_t company, uint16_t id); - -/** @brief Get whether the model is in the primary element of the device. - * - * @param mod Mesh model. - * - * @return true if the model is on the primary element, false otherwise. - */ -static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod) -{ - return (mod->elem_idx == 0); -} - -/** @brief Immediately store the model's user data in persistent storage. - * - * @param mod Mesh model. - * @param vnd This is a vendor model. - * @param name Name/key of the settings item. Only - * @ref SETTINGS_MAX_DIR_DEPTH bytes will be used at most. - * @param data Model data to store, or NULL to delete any model data. - * @param data_len Length of the model data. - * - * @return 0 on success, or (negative) error code on failure. - */ -int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, - const char *name, const void *data, - size_t data_len); - -/** @brief Let a model extend another. - * - * Mesh models may be extended to reuse their functionality, forming a more - * complex model. A Mesh model may extend any number of models, in any element. - * The extensions may also be nested, ie a model that extends another may itself - * be extended. - * - * A set of models that extend each other form a model extension list. - * - * All models in an extension list share one subscription list per element. The - * access layer will utilize the combined subscription list of all models in an - * extension list and element, giving the models extended subscription list - * capacity. - * - * @param extending_mod Mesh model that is extending the base model. - * @param base_mod The model being extended. - * - * @retval 0 Successfully extended the base_mod model. - */ -int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, - struct bt_mesh_model *base_mod); - -/** @brief Check if model is extended by another model. - * - * @param model The model to check. - * - * @retval true If model is extended by another model, otherwise false - */ -bool bt_mesh_model_is_extended(struct bt_mesh_model *model); - -/** Node Composition */ -struct bt_mesh_comp { - uint16_t cid; - uint16_t pid; - uint16_t vid; - - size_t elem_count; - struct bt_mesh_elem *elem; -}; - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __BT_MESH_ACCESS_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/atomic.h b/src/nimble/nimble/host/mesh/include/mesh/atomic.h deleted file mode 100644 index 2c7317948..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/atomic.h +++ /dev/null @@ -1,409 +0,0 @@ -/* 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/src/nimble/nimble/host/mesh/include/mesh/cdb.h b/src/nimble/nimble/host/mesh/include/mesh/cdb.h deleted file mode 100644 index fa691eb64..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/cdb.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2019 Tobias Svehagen - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef _BLUETOOTH_MESH_CDB_H_ -#define _BLUETOOTH_MESH_CDB_H_ - -#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_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; - - 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_ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/cfg.h b/src/nimble/nimble/host/mesh/include/mesh/cfg.h deleted file mode 100644 index 422ef3e66..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/cfg.h +++ /dev/null @@ -1,491 +0,0 @@ -/** @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, -}; - -/* Key Refresh Phase */ -#define BT_MESH_KR_NORMAL 0x00 -#define BT_MESH_KR_PHASE_1 0x01 -#define BT_MESH_KR_PHASE_2 0x02 -#define BT_MESH_KR_PHASE_3 0x03 - -/* Legacy feature defines */ -#define BT_MESH_RELAY_DISABLED BT_MESH_FEATURE_DISABLED -#define BT_MESH_RELAY_ENABLED BT_MESH_FEATURE_ENABLED -#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_ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h b/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h deleted file mode 100644 index 86716f316..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/cfg_cli.h +++ /dev/null @@ -1,345 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Configuration Client Model APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_CFG_CLI_H -#define __BT_MESH_CFG_CLI_H - -/** - * @brief Bluetooth Mesh - * @defgroup bt_mesh_cfg_cli Bluetooth Mesh Configuration Client Model - * @ingroup bt_mesh - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** Mesh Configuration Client Model Context */ -struct bt_mesh_cfg_cli { - struct bt_mesh_model *model; - struct bt_mesh_msg_ack_ctx ack_ctx; -}; - -extern const struct bt_mesh_model_op bt_mesh_cfg_cli_op[]; -extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb; - -#define BT_MESH_MODEL_CFG_CLI(cli_data) \ - 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_node_reset(uint16_t net_idx, uint16_t addr, bool *status); - -int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, - uint8_t *rsp, struct os_mbuf *comp); - -int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status); - -int bt_mesh_cfg_krp_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, - uint8_t *status, uint8_t *phase); - -int bt_mesh_cfg_krp_set(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, - uint8_t transition, uint8_t *status, uint8_t *phase); - -int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status); - -int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl); - -int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl); - -int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_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_get(uint16_t net_idx, uint16_t addr, uint8_t *status); - -int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val, - uint8_t *status); - -int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr, - uint8_t *transmit); - -int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr, - uint8_t val, uint8_t *transmit); - -int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status, - uint8_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); - -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 - * - * @brief Helper macro to encode model publication period in units of 100ms - * - * @param steps Number of 100ms steps. - * - * @return Encoded value that can be assigned to bt_mesh_cfg_mod_pub.period - */ -#define BT_MESH_PUB_PERIOD_100MS(steps) ((steps) & BIT_MASK(6)) - -/** @def BT_MESH_PUB_PERIOD_SEC - * - * @brief Helper macro to encode model publication period in units of 1 second - * - * @param steps Number of 1 second steps. - * - * @return Encoded value that can be assigned to bt_mesh_cfg_mod_pub.period - */ -#define BT_MESH_PUB_PERIOD_SEC(steps) (((steps) & BIT_MASK(6)) | (1 << 6)) - -/** @def BT_MESH_PUB_PERIOD_10SEC - * - * @brief Helper macro to encode model publication period in units of 10 - * seconds - * - * @param steps Number of 10 second steps. - * - * @return Encoded value that can be assigned to bt_mesh_cfg_mod_pub.period - */ -#define BT_MESH_PUB_PERIOD_10SEC(steps) (((steps) & BIT_MASK(6)) | (2 << 6)) - -/** @def BT_MESH_PUB_PERIOD_10MIN - * - * @brief Helper macro to encode model publication period in units of 10 - * minutes - * - * @param steps Number of 10 minute steps. - * - * @return Encoded value that can be assigned to bt_mesh_cfg_mod_pub.period - */ -#define BT_MESH_PUB_PERIOD_10MIN(steps) (((steps) & BIT_MASK(6)) | (3 << 6)) - -struct bt_mesh_cfg_mod_pub { - uint16_t addr; - const uint8_t *uuid; - uint16_t app_idx; - bool cred_flag; - uint8_t ttl; - uint8_t period; - uint8_t transmit; -}; - -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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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 { - 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(uint16_t net_idx, uint16_t addr, - struct bt_mesh_cfg_hb_sub *sub, uint8_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 { - 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(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(uint16_t net_idx, uint16_t addr, - struct bt_mesh_cfg_hb_pub *pub, uint8_t *status); - -int bt_mesh_cfg_mod_sub_del_all(uint16_t net_idx, uint16_t addr, - uint16_t elem_addr, uint16_t mod_id, - uint8_t *status); - -int bt_mesh_cfg_mod_sub_del_all_vnd(uint16_t net_idx, uint16_t addr, - uint16_t elem_addr, uint16_t mod_id, - uint16_t cid, uint8_t *status); - -int bt_mesh_cfg_net_key_update(uint16_t net_idx, uint16_t addr, - uint16_t key_net_idx, const uint8_t net_key[16], - uint8_t *status); - -int bt_mesh_cfg_app_key_update(uint16_t net_idx, uint16_t addr, - uint16_t key_net_idx, uint16_t key_app_idx, - const uint8_t app_key[16], uint8_t *status); - -int bt_mesh_cfg_node_identity_set(uint16_t net_idx, uint16_t addr, - uint16_t key_net_idx, uint8_t new_identity, - uint8_t *status, uint8_t *identity); - -int bt_mesh_cfg_node_identity_get(uint16_t net_idx, uint16_t addr, - uint16_t key_net_idx, uint8_t *status, - uint8_t *identity); - -int bt_mesh_cfg_lpn_timeout_get(uint16_t net_idx, uint16_t addr, - uint16_t unicast_addr, int32_t *polltimeout); - -int32_t bt_mesh_cfg_cli_timeout_get(void); -void bt_mesh_cfg_cli_timeout_set(int32_t timeout); - -struct bt_mesh_comp_p0 { - /** Company ID */ - uint16_t cid; - /** Product ID */ - uint16_t pid; - /** Version ID */ - uint16_t vid; - /** Replay protection list size */ - uint16_t crpl; - /** Supported features, see @ref BT_MESH_FEAT_SUPPORTED. */ - uint16_t feat; - - struct os_mbuf *_buf; -}; - -struct bt_mesh_comp_p0_elem { - /** Element location */ - uint16_t loc; - /** The number of SIG models in this element */ - size_t nsig; - /** The number of vendor models in this element */ - size_t nvnd; - - uint8_t *_buf; -}; - -int bt_mesh_comp_p0_get(struct bt_mesh_comp_p0 *comp, - struct os_mbuf *buf); - -struct bt_mesh_comp_p0_elem *bt_mesh_comp_p0_elem_pull(const struct bt_mesh_comp_p0 *comp, - struct bt_mesh_comp_p0_elem *elem); - -uint16_t bt_mesh_comp_p0_elem_mod(struct bt_mesh_comp_p0_elem *elem, int idx); - -struct bt_mesh_mod_id_vnd bt_mesh_comp_p0_elem_mod_vnd(struct bt_mesh_comp_p0_elem *elem, int idx); - -#ifdef __cplusplus -} -#endif -/** - * @} - */ - -#endif /* __BT_MESH_CFG_CLI_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h b/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h deleted file mode 100644 index 5bf3f4399..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/cfg_srv.h +++ /dev/null @@ -1,40 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Configuration Server Model APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_CFG_SRV_H -#define __BT_MESH_CFG_SRV_H - -/** - * @brief Bluetooth Mesh - * @defgroup bt_mesh_cfg_srv Bluetooth Mesh Configuration Server Model - * @ingroup bt_mesh - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - - -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 \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \ - NULL, &bt_mesh_cfg_srv_cb) - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __BT_MESH_CFG_SRV_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/glue.h b/src/nimble/nimble/host/mesh/include/mesh/glue.h deleted file mode 100644 index 3badd24e6..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/glue.h +++ /dev/null @@ -1,699 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef _MESH_GLUE_ -#define _MESH_GLUE_ - -#include -#include - -#include "syscfg/syscfg.h" -#include "nimble/porting/nimble/include/logcfg/logcfg.h" -#include "nimble/porting/nimble/include/modlog/modlog.h" -#include "nimble/nimble/include/nimble/nimble_npl.h" - -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/porting/nimble/include/os/queue.h" - -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" -#include "nimble/nimble/host/src/ble_sm_priv.h" -#include "nimble/nimble/host/src/ble_hs_hci_priv.h" - -#if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#include "mbedtls/cipher.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/cmac.h" -#include "mbedtls/ecdh.h" -#include "mbedtls/ecp.h" - -#else -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h" -#endif - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -#include "config/config.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define SETTINGS_MAX_DIR_DEPTH 8 /* max depth of settings tree */ - -/** Key size used in Bluetooth's ECC domain. */ -#define BT_ECC_KEY_SIZE 32 - /** Length of a Bluetooth ECC public key coordinate. */ -#define BT_PUB_KEY_COORD_LEN (BT_ECC_KEY_SIZE) - /** Length of a Bluetooth ECC public key. */ -#define BT_PUB_KEY_LEN (2 * (BT_PUB_KEY_COORD_LEN)) - /** Length of a Bluetooth ECC private key. */ -#define BT_PRIV_KEY_LEN (BT_ECC_KEY_SIZE) - /** Length of a Bluetooth Diffie-Hellman key. */ -#define BT_DH_KEY_LEN (BT_ECC_KEY_SIZE) - -/** @brief Helper to declare elements of bt_data arrays - * - * This macro is mainly for creating an array of struct bt_data - * elements which is then passed to bt_le_adv_start(). - * - * @param _type Type of advertising data field - * @param _data Pointer to the data field payload - * @param _data_len Number of bytes behind the _data pointer - */ -#define BT_DATA(_type, _data, _data_len) \ - { \ - .type = (_type), \ - .data_len = (_data_len), \ - .data = (const uint8_t *)(_data), \ - } - -/** @brief Helper to declare elements of bt_data arrays - * - * This macro is mainly for creating an array of struct bt_data - * elements which is then passed to bt_le_adv_start(). - * - * @param _type Type of advertising data field - * @param _bytes Variable number of single-byte parameters - */ -#define BT_DATA_BYTES(_type, _bytes...) \ - BT_DATA(_type, ((uint8_t []) { _bytes }), \ - sizeof((uint8_t []) { _bytes })) - -/* EIR/AD data type definitions */ -#define BT_DATA_FLAGS 0x01 /* AD flags */ -#define BT_DATA_UUID16_SOME 0x02 /* 16-bit UUID, more available */ -#define BT_DATA_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ -#define BT_DATA_UUID32_SOME 0x04 /* 32-bit UUID, more available */ -#define BT_DATA_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ -#define BT_DATA_UUID128_SOME 0x06 /* 128-bit UUID, more available */ -#define BT_DATA_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ -#define BT_DATA_NAME_SHORTENED 0x08 /* Shortened name */ -#define BT_DATA_NAME_COMPLETE 0x09 /* Complete name */ -#define BT_DATA_TX_POWER 0x0a /* Tx Power */ -#define BT_DATA_SOLICIT16 0x14 /* Solicit UUIDs, 16-bit */ -#define BT_DATA_SOLICIT128 0x15 /* Solicit UUIDs, 128-bit */ -#define BT_DATA_SVC_DATA16 0x16 /* Service data, 16-bit UUID */ -#define BT_DATA_GAP_APPEARANCE 0x19 /* GAP appearance */ -#define BT_DATA_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */ -#define BT_DATA_SVC_DATA32 0x20 /* Service data, 32-bit UUID */ -#define BT_DATA_SVC_DATA128 0x21 /* Service data, 128-bit UUID */ -#define BT_DATA_URI 0x24 /* URI */ -#define BT_DATA_MESH_PROV 0x29 /* Mesh Provisioning PDU */ -#define BT_DATA_MESH_MESSAGE 0x2a /* Mesh Networking PDU */ -#define BT_DATA_MESH_BEACON 0x2b /* Mesh Beacon */ - -#define BT_DATA_MANUFACTURER_DATA 0xff /* Manufacturer Specific Data */ - -#define BT_LE_AD_LIMITED 0x01 /* Limited Discoverable */ -#define BT_LE_AD_GENERAL 0x02 /* General Discoverable */ -#define BT_LE_AD_NO_BREDR 0x04 /* BR/EDR not supported */ - -#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) -#define sys_be32_to_cpu(a) be32toh(a) -#define sys_be16_to_cpu(a) be16toh(a) -#define sys_le16_to_cpu(a) le16toh(a) - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif - -#define CODE_UNREACHABLE __builtin_unreachable() -#define __ASSERT(code, str) \ - do { \ - if (!(code)) BT_ERR(str); \ - assert(code); \ - } while (0); - -#define __ASSERT_NO_MSG(test) __ASSERT(test, "") - -/* Mesh is designed to not use mbuf chains */ -#if BT_DBG_ENABLED -#define ASSERT_NOT_CHAIN(om) assert(SLIST_NEXT(om, om_next) == NULL) -#else -#define ASSERT_NOT_CHAIN(om) (void)(om) -#endif - -#define CHECKIF(expr) \ - __ASSERT_NO_MSG(!(expr)); \ - if (0) - -#define __packed __attribute__((__packed__)) - -#define MSEC_PER_SEC (1000) -#define K_MSEC(ms) (ms) -#define K_SECONDS(s) K_MSEC((s) * MSEC_PER_SEC) -#define K_MINUTES(m) K_SECONDS((m) * 60) -#define K_HOURS(h) K_MINUTES((h) * 60) - -#ifndef BIT -#define BIT(n) (1UL << (n)) -#endif - -#define BIT_MASK(n) (BIT(n) - 1) - -#define BT_GAP_ADV_FAST_INT_MIN_1 0x0030 /* 30 ms */ -#define BT_GAP_ADV_FAST_INT_MAX_1 0x0060 /* 60 ms */ -#define BT_GAP_ADV_FAST_INT_MIN_2 0x00a0 /* 100 ms */ -#define BT_GAP_ADV_FAST_INT_MAX_2 0x00f0 /* 150 ms */ -#define BT_GAP_ADV_SLOW_INT_MIN 0x0640 /* 1 s */ -#define BT_GAP_ADV_SLOW_INT_MAX 0x0780 /* 1.2 s */ - -#ifndef MESH_LOG_MODULE -#define MESH_LOG_MODULE BLE_MESH_LOG -#endif - -#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) -#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ - -#define BLE_MESH_LOG(lvl, ...) CAT(MESH_LOG_MODULE, CAT(_, lvl))(__VA_ARGS__) - -#define BT_DBG(fmt, ...) BLE_MESH_LOG(DEBUG, "%s: " fmt "\n", __func__, ## __VA_ARGS__); -#define BT_INFO(fmt, ...) BLE_MESH_LOG(INFO, "%s: " fmt "\n", __func__, ## __VA_ARGS__); -#define BT_WARN(fmt, ...) BLE_MESH_LOG(WARN, "%s: " fmt "\n", __func__, ## __VA_ARGS__); -#define BT_ERR(fmt, ...) BLE_MESH_LOG(ERROR, "%s: " fmt "\n", __func__, ## __VA_ARGS__); -#define BT_GATT_ERR(_att_err) (-(_att_err)) - -typedef ble_addr_t bt_addr_le_t; - -#define k_fifo_init(queue) ble_npl_eventq_init(queue) -#define net_buf_simple_tailroom(buf) OS_MBUF_TRAILINGSPACE(buf) -#define net_buf_tailroom(buf) net_buf_simple_tailroom(buf) -#define net_buf_headroom(buf) ((buf)->om_data - &(buf)->om_databuf[buf->om_pkthdr_len]) -#define net_buf_simple_headroom(buf) net_buf_headroom(buf) -#define net_buf_simple_tail(buf) ((buf)->om_data + (buf)->om_len) - -struct net_buf_simple_state { - /** Offset of the data pointer from the beginning of the storage */ - uint16_t offset; - /** Length of data */ - uint16_t len; -}; - -static inline struct os_mbuf * NET_BUF_SIMPLE(uint16_t size) -{ - struct os_mbuf *buf; - - buf = os_msys_get(size, 0); - assert(buf); - - return buf; -} - -#define K_NO_WAIT (0) -#define K_FOREVER (-1) - -#if MYNEWT_VAL(BLE_EXT_ADV) -#define BT_MESH_ADV_INST (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES)) - -#if MYNEWT_VAL(BLE_MESH_PROXY) -/* Note that BLE_MULTI_ADV_INSTANCES contains number of additional instances. - * Instance 0 is always there - */ -#if MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) < 1 -#error "Mesh needs at least BLE_MULTI_ADV_INSTANCES set to 1" -#endif -#define BT_MESH_ADV_GATT_INST (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) - 1) -#endif /* BLE_MESH_PROXY */ -#endif /* BLE_EXT_ADV */ - -/* This is by purpose */ -static inline void net_buf_simple_init(struct os_mbuf *buf, - size_t reserve_head) -{ - /* This is called in Zephyr after init. - * Note in Mynewt case we don't care abour reserved head*/ - buf->om_data = &buf->om_databuf[buf->om_pkthdr_len] + reserve_head; - 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); -} - -struct bt_le_ext_adv_start_param { - uint16_t timeout; - - uint8_t num_events; -}; - -void net_buf_put(struct ble_npl_eventq *fifo, struct os_mbuf *buf); -void * net_buf_ref(struct os_mbuf *om); -void net_buf_unref(struct os_mbuf *om); -uint16_t net_buf_simple_pull_le16(struct os_mbuf *om); -uint16_t net_buf_simple_pull_be16(struct os_mbuf *om); -uint32_t net_buf_simple_pull_le24(struct os_mbuf *om); -uint32_t net_buf_simple_pull_be32(struct os_mbuf *om); -uint32_t net_buf_simple_pull_le32(struct os_mbuf *om); -uint8_t net_buf_simple_pull_u8(struct os_mbuf *om); -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,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); - -#define net_buf_add_mem(a,b,c) os_mbuf_append(a,b,c) -#define net_buf_simple_add_mem(a,b,c) os_mbuf_append(a,b,c) -#define net_buf_add_u8(a,b) net_buf_simple_add_u8(a,b) -#define net_buf_add(a,b) net_buf_simple_add(a,b) - -#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_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) -#define net_buf_skip(a, b) net_buf_simple_pull_mem(a, b) - -#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 { - uint8_t type; - uint8_t data_len; - const uint8_t *data; -}; - -struct bt_pub_key_cb { - /** @brief Callback type for Public Key generation. - * - * Used to notify of the local public key or that the local key is not - * available (either because of a failure to read it or because it is - * being regenerated). - * - * @param key The local public key, or NULL in case of no key. - */ - void (*func)(const uint8_t key[BT_PUB_KEY_LEN]); - - struct bt_pub_key_cb *_next; -}; - -/** LE Advertising Parameters. */ -struct bt_le_adv_param { - /** - * @brief Local identity. - * - * @note When extended advertising @kconfig{CONFIG_BT_EXT_ADV} is not - * enabled or not supported by the controller it is not possible - * to scan and advertise simultaneously using two different - * random addresses. - */ - uint8_t id; - - /** - * @brief Advertising Set Identifier, valid range 0x00 - 0x0f. - * - * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV - **/ - uint8_t sid; - - /** - * @brief Secondary channel maximum skip count. - * - * Maximum advertising events the advertiser can skip before it must - * send advertising data on the secondary advertising channel. - * - * @note Requires @ref BT_LE_ADV_OPT_EXT_ADV - */ - uint8_t secondary_max_skip; - - /** Bit-field of advertising options */ - uint32_t options; - - /** Minimum Advertising Interval (N * 0.625 milliseconds) - * Minimum Advertising Interval shall be less than or equal to the - * Maximum Advertising Interval. The Minimum Advertising Interval and - * Maximum Advertising Interval should not be the same value (as stated - * in Bluetooth Core Spec 5.2, section 7.8.5) - * Range: 0x0020 to 0x4000 - */ - uint32_t interval_min; - - /** Maximum Advertising Interval (N * 0.625 milliseconds) - * Minimum Advertising Interval shall be less than or equal to the - * Maximum Advertising Interval. The Minimum Advertising Interval and - * Maximum Advertising Interval should not be the same value (as stated - * in Bluetooth Core Spec 5.2, section 7.8.5) - * Range: 0x0020 to 0x4000 - */ - uint32_t interval_max; - - /** - * @brief Directed advertising to peer - * - * When this parameter is set the advertiser will send directed - * advertising to the remote device. - * - * The advertising type will either be high duty cycle, or low duty - * cycle if the BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY option is enabled. - * When using @ref BT_LE_ADV_OPT_EXT_ADV then only low duty cycle is - * allowed. - * - * In case of connectable high duty cycle if the connection could not - * be established within the timeout the connected() callback will be - * called with the status set to @ref BT_HCI_ERR_ADV_TIMEOUT. - */ - const bt_addr_le_t *peer; -}; - -typedef void (*bt_dh_key_cb_t)(const uint8_t key[BT_DH_KEY_LEN]); -int bt_dh_key_gen(const uint8_t remote_pk[BT_PUB_KEY_LEN], bt_dh_key_cb_t cb); -int bt_pub_key_gen(struct bt_pub_key_cb *new_cb); -uint8_t *bt_pub_key_get(void); -void bt_conn_get_info(struct ble_hs_conn *conn, struct ble_gap_conn_desc *desc); -int bt_rand(void *buf, size_t len); -const char * bt_hex(const void *buf, size_t len); -int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data); -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, - const struct bt_data *sd, size_t sd_len); - -int bt_le_adv_stop(void); - -struct k_work_delayable { - struct ble_npl_callout work; -}; - -void k_work_init(struct ble_npl_callout *work, ble_npl_event_fn handler); -void k_work_init_delayable(struct k_work_delayable *w, ble_npl_event_fn *f); -void k_work_cancel_delayable(struct k_work_delayable *w); -bool k_work_delayable_is_pending(struct k_work_delayable *w); -void k_work_reschedule(struct k_work_delayable *w, uint32_t ms); -int64_t k_uptime_get(void); -uint32_t k_uptime_get_32(void); -int64_t k_uptime_delta(int64_t *reftime); -void k_sleep(int32_t duration); -void k_work_submit(struct ble_npl_callout *w); -void k_work_add_arg(struct ble_npl_callout *w, void *arg); -void k_work_add_arg_delayable(struct k_work_delayable *w, void *arg); -ble_npl_time_t k_work_delayable_remaining_get(struct k_work_delayable *w); -void k_work_schedule(struct k_work_delayable *w, uint32_t ms); -uint32_t k_ticks_to_ms_floor32(ble_npl_time_t ticks); - -static inline void net_buf_simple_save(struct os_mbuf *buf, - struct net_buf_simple_state *state) -{ - state->offset = net_buf_simple_headroom(buf); - state->len = buf->om_len; -} - -void net_buf_simple_clone(const struct os_mbuf *original, struct os_mbuf *clone); - -static inline void net_buf_simple_restore(struct os_mbuf *buf, - struct net_buf_simple_state *state) -{ - buf->om_data = &buf->om_databuf[buf->om_pkthdr_len] + state->offset; - buf->om_len = state->len; -} - -static inline void sys_memcpy_swap(void *dst, const void *src, size_t length) -{ - __ASSERT(((src < dst && (src + length) <= dst) || - (src > dst && (dst + length) <= src)), - "Source and destination buffers must not overlap"); - - src += length - 1; - - for (; length > 0; length--) { - *((uint8_t *)dst++) = *((uint8_t *)src--); - } -} - -#define popcount(x) __builtin_popcount(x) - -static inline unsigned int find_lsb_set(uint32_t op) -{ - return __builtin_ffs(op); -} - -static inline unsigned int find_msb_set(uint32_t op) -{ - if (!op) - return 0; - - 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_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 -#define CONFIG_BT_MESH_DEBUG_CFG BLE_MESH_DEBUG_CFG -#define CONFIG_BT_MESH_DEBUG_ADV BLE_MESH_DEBUG_ADV - -/* Above flags are used with IS_ENABLED macro */ -#define IS_ENABLED(config) MYNEWT_VAL(config) - -#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_IV_UPDATE_SEQ_LIMIT MYNEWT_VAL(BLE_MESH_IV_UPDATE_SEQ_LIMIT) -#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER) -#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME) -#define CONFIG_BT_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX) -#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_MODEL_VND_MSG_CID_FORCE MYNEWT_VAL(BLE_MESH_MODEL_VND_MSG_CID_FORCE) -#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT) -#define CONFIG_BT_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED) -#define CONFIG_BT_MESH_DEFAULT_TTL MYNEWT_VAL(BLE_MESH_DEFAULT_TTL) -#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 CONFIG_BT_MESH_PROXY_MSG_LEN MYNEWT_VAL(BLE_MESH_PROXY_MSG_LEN) - -#define printk console_printf - -#define CONTAINER_OF(ptr, type, field) \ - ((type *)(((char *)(ptr)) - offsetof(type, field))) - - -#define k_sem ble_npl_sem - -static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count, - unsigned int limit) -{ - ble_npl_sem_init(sem, initial_count); -} - -static inline int k_sem_take(struct k_sem *sem, int32_t timeout) -{ - uint32_t ticks; - - ble_npl_time_ms_to_ticks(timeout, &ticks); - return - ble_npl_sem_pend(sem, ticks); -} - -static inline void k_sem_give(struct k_sem *sem) -{ - ble_npl_sem_release(sem); -} - -static inline void k_sem_reset(struct k_sem *sem) -{ - ble_npl_sem_init(sem, 0); -} -/* Helpers to access the storage array, since we don't have access to its - * type at this point anymore. - */ - -#define BUF_SIZE(pool) (pool->omp_pool->mp_block_size) - -static inline int net_buf_id(struct os_mbuf *buf) -{ - struct os_mbuf_pool *pool = buf->om_omp; - 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); -} - -/* XXX: We should not use os_mbuf_pkthdr chains to represent a list of - * packets, this is a hack. For now this is not an issue, because mesh - * does not use os_mbuf chains. We should change this in the future. - */ -STAILQ_HEAD(net_buf_slist_t, os_mbuf_pkthdr); - -void net_buf_slist_init(struct net_buf_slist_t *list); -bool net_buf_slist_is_empty(struct net_buf_slist_t *list); -struct os_mbuf *net_buf_slist_peek_head(struct net_buf_slist_t *list); -struct os_mbuf *net_buf_slist_peek_next(struct os_mbuf *buf); -struct os_mbuf *net_buf_slist_get(struct net_buf_slist_t *list); -void net_buf_slist_put(struct net_buf_slist_t *list, struct os_mbuf *buf); -void net_buf_slist_remove(struct net_buf_slist_t *list, struct os_mbuf *prev, - struct os_mbuf *cur); -void net_buf_slist_merge_slist(struct net_buf_slist_t *list, - struct net_buf_slist_t *list_to_append); -#define NET_BUF_SLIST_FOR_EACH_NODE(head, var) STAILQ_FOREACH(var, head, omp_next) - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - -#define settings_load conf_load -int settings_bytes_from_str(char *val_str, void *vp, int *len); -char *settings_str_from_bytes(const void *vp, int vp_len, - char *buf, int buf_len); - -#define snprintk snprintf -#define BT_SETTINGS_SIZE(in_size) ((((((in_size) - 1) / 3) * 4) + 4) + 1) -#define settings_save_one conf_save_one - -#else - -static inline int -settings_load(void) -{ - return 0; -} - -#endif /* MYNEWT_VAL(MYNEWT_VAL_BLE_MESH_SETTINGS) */ - -#define BUILD_ASSERT(cond, msg) _Static_assert(cond, msg) - - -/* 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 - -#endif /* _MESH_GLUE_ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/health_cli.h b/src/nimble/nimble/host/mesh/include/mesh/health_cli.h deleted file mode 100644 index cb14ee6bc..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/health_cli.h +++ /dev/null @@ -1,77 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Health Client Model APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_HEALTH_CLI_H -#define __BT_MESH_HEALTH_CLI_H - -/** - * @brief Bluetooth Mesh - * @defgroup bt_mesh_health_cli Bluetooth Mesh Health Client Model - * @ingroup bt_mesh - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** Mesh Health Client Model Context */ -struct bt_mesh_health_cli { - struct bt_mesh_model *model; - - 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 bt_mesh_msg_ack_ctx ack_ctx; -}; - -extern const struct bt_mesh_model_op bt_mesh_health_cli_op[]; -extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb; - -#define BT_MESH_MODEL_HEALTH_CLI(cli_data) \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_CLI, bt_mesh_health_cli_op, \ - NULL, cli_data, &bt_mesh_health_cli_cb) - -int bt_mesh_health_cli_set(struct bt_mesh_model *model); - -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(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(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(uint16_t addr, uint16_t app_idx, uint8_t *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(uint16_t addr, uint16_t app_idx, uint8_t *attention); - -int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention, - uint8_t *updated_attention); - -int32_t bt_mesh_health_cli_timeout_get(void); -void bt_mesh_health_cli_timeout_set(int32_t timeout); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __BT_MESH_HEALTH_CLI_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/health_srv.h b/src/nimble/nimble/host/mesh/include/mesh/health_srv.h deleted file mode 100644 index 980e75748..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/health_srv.h +++ /dev/null @@ -1,100 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Health Server Model APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_HEALTH_SRV_H -#define __BT_MESH_HEALTH_SRV_H - -/** - * @brief Mesh Bluetooth Mesh Health Server Model - * @defgroup bt_mesh_health_srv - * @ingroup bt_mesh - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_mesh_health_srv_cb { - /* Fetch current faults */ - 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, 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, uint16_t company_id); - - /* Run a specific test */ - 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); - - /* Attention off */ - void (*attn_off)(struct bt_mesh_model *model); -}; - -/** @def BT_MESH_HEALTH_FAULT_MSG - * - * A helper to define a health fault message. - * - * @param max_faults Maximum number of faults the element can have. - * - * @return a New os_mbuf of the needed size. - */ -#define BT_MESH_HEALTH_FAULT_MSG(max_faults) \ - NET_BUF_SIMPLE(1 + 3 + (max_faults)) - -/** Mesh Health Server Model Context */ -struct bt_mesh_health_srv { - struct bt_mesh_model *model; - - /* Optional callback struct */ - const struct bt_mesh_health_srv_cb *cb; - - /* Attention Timer state */ - struct k_work_delayable attn_timer; -}; - -int bt_mesh_fault_update(struct bt_mesh_elem *elem); - -extern const struct bt_mesh_model_op bt_mesh_health_srv_op[]; -extern const struct bt_mesh_model_cb bt_mesh_health_srv_cb; - -/** @def BT_MESH_MODEL_HEALTH_SRV - * - * Define a new health server model. Note that this API needs to be - * repeated for each element that the application wants to have a - * health server model on. Each instance also needs a unique - * bt_mesh_health_srv and bt_mesh_model_pub context. - * - * @param srv Pointer to a unique struct bt_mesh_health_srv. - * @param pub Pointer to a unique struct bt_mesh_model_pub. - * - * @return New mesh model instance. - */ -#define BT_MESH_MODEL_HEALTH_SRV(srv, pub) \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_HEALTH_SRV, bt_mesh_health_srv_op, \ - pub, srv, &bt_mesh_health_srv_cb) - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __BT_MESH_HEALTH_SRV_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/heartbeat.h b/src/nimble/nimble/host/mesh/include/mesh/heartbeat.h deleted file mode 100644 index 2e4986094..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/heartbeat.h +++ /dev/null @@ -1,123 +0,0 @@ -/** @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_ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/main.h b/src/nimble/nimble/host/mesh/include/mesh/main.h deleted file mode 100644 index 6e9d2e629..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/main.h +++ /dev/null @@ -1,589 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Profile APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_MAIN_H -#define __BT_MESH_MAIN_H - -/** - * @brief Bluetooth Mesh Provisioning - * @defgroup bt_mesh_prov Bluetooth Mesh Provisioning - * @ingroup bt_mesh - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - BT_MESH_NO_OUTPUT = 0, - BT_MESH_BLINK = BIT(0), - BT_MESH_BEEP = BIT(1), - BT_MESH_VIBRATE = BIT(2), - BT_MESH_DISPLAY_NUMBER = BIT(3), - BT_MESH_DISPLAY_STRING = BIT(4), -} bt_mesh_output_action_t; - -typedef enum { - BT_MESH_NO_INPUT = 0, - BT_MESH_PUSH = BIT(0), - BT_MESH_TWIST = BIT(1), - BT_MESH_ENTER_NUMBER = BIT(2), - BT_MESH_ENTER_STRING = BIT(3), -} bt_mesh_input_action_t; - -typedef enum { - BT_MESH_PROV_ADV = BIT(0), - BT_MESH_PROV_GATT = BIT(1), -} bt_mesh_prov_bearer_t; - -typedef enum { - BT_MESH_PROV_OOB_OTHER = BIT(0), - BT_MESH_PROV_OOB_URI = BIT(1), - BT_MESH_PROV_OOB_2D_CODE = BIT(2), - BT_MESH_PROV_OOB_BAR_CODE = BIT(3), - BT_MESH_PROV_OOB_NFC = BIT(4), - BT_MESH_PROV_OOB_NUMBER = BIT(5), - BT_MESH_PROV_OOB_STRING = BIT(6), - /* 7 - 10 are reserved */ - BT_MESH_PROV_OOB_ON_BOX = BIT(11), - BT_MESH_PROV_OOB_IN_BOX = BIT(12), - BT_MESH_PROV_OOB_ON_PAPER = BIT(13), - BT_MESH_PROV_OOB_IN_MANUAL = BIT(14), - 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 uint8_t *uuid; - - /** Optional URI. This will be advertised separately from the - * unprovisioned beacon, however the unprovisioned beacon will - * contain a hash of it so the two can be associated by the - * provisioner. - */ - const char *uri; - - /** Out of Band information field. */ - bt_mesh_prov_oob_info_t oob_info; - - /** Pointer to Public Key in big-endian for OOB public key type support. - * - * Remember to enable @option{CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY} - * when initializing this parameter. - * - * Must be used together with @ref bt_mesh_prov::private_key_be. - */ - const uint8_t *public_key_be; - /** Pointer to Private Key in big-endian for OOB public key type support. - * - * Remember to enable @option{CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY} - * when initializing this parameter. - * - * Must be used together with @ref bt_mesh_prov::public_key_be. - */ - const uint8_t *private_key_be; - - /** Static OOB value */ - const uint8_t *static_val; - /** Static OOB value length */ - uint8_t static_val_len; - - /** Maximum size of Output OOB supported */ - uint8_t output_size; - /** Supported Output OOB Actions */ - uint16_t output_actions; - - /* Maximum size of Input OOB supported */ - uint8_t input_size; - /** Supported Input OOB 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. - * - * This callback notifies the application that it should - * output the given number using the given action. - * - * @param act Action for outputting the number. - * @param num Number to be outputted. - * - * @return Zero on success or negative error code otherwise - */ - int (*output_number)(bt_mesh_output_action_t act, uint32_t num); - - /** @brief Output of a string is requested. - * - * This callback notifies the application that it should - * display the given string to the user. - * - * @param str String to be displayed. - * - * @return Zero on success or negative error code otherwise - */ - int (*output_string)(const char *str); - - /** @brief Input is requested. - * - * This callback notifies the application that it should - * request input from the user using the given action. The - * requested input will either be a string or a number, and - * the application needs to consequently call the - * bt_mesh_input_string() or bt_mesh_input_number() functions - * once the data has been acquired from the user. - * - * @param act Action for inputting data. - * @param num Maximum size of the inputted data. - * - * @return Zero on success or negative error code otherwise - */ - int (*input)(bt_mesh_input_action_t act, uint8_t size); - - /** @brief The other device finished their OOB input. - * - * This callback notifies the application that it should stop - * displaying its output OOB value, as the other party finished their - * OOB input. - */ - void (*input_complete)(void); - - /** @brief Unprovisioned beacon has been received. - * - * This callback notifies the application that an unprovisioned - * beacon has been received. - * - * @param uuid UUID - * @param oob_info OOB Information - * @param uri_hash Pointer to URI Hash value. NULL if no hash was - * present in the beacon. - */ - void (*unprovisioned_beacon)(uint8_t uuid[16], - bt_mesh_prov_oob_info_t oob_info, - uint32_t *uri_hash); - - /** @brief Provisioning link has been opened. - * - * This callback notifies the application that a provisioning - * link has been opened on the given provisioning bearer. - * - * @param bearer Provisioning bearer. - */ - void (*link_open)(bt_mesh_prov_bearer_t bearer); - - /** @brief Provisioning link has been closed. - * - * This callback notifies the application that a provisioning - * link has been closed on the given provisioning bearer. - * - * @param bearer Provisioning bearer. - */ - void (*link_close)(bt_mesh_prov_bearer_t bearer); - - /** @brief Provisioning is complete. - * - * This callback notifies the application that provisioning has - * been successfully completed, and that the local node has been - * assigned the specified NetKeyIndex and primary element address. - * - * @param net_idx NetKeyIndex given during provisioning. - * @param addr Primary element address. - */ - void (*complete)(uint16_t net_idx, uint16_t addr); - - /** @brief A new node has been added to the provisioning database. - * - * This callback notifies the application that provisioning has - * been successfully completed, and that a node has been assigned - * 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)(uint16_t net_idx, uint8_t uuid[16], uint16_t addr, - uint8_t num_elem); - - /** @brief Node has been reset. - * - * This callback notifies the application that the local node - * has been reset and needs to be reprovisioned. The node will - * not automatically advertise as unprovisioned, rather the - * bt_mesh_prov_enable() API needs to be called to enable - * unprovisioned advertising on one or more provisioning bearers. - */ - void (*reset)(void); -}; - -/** @brief Provide provisioning input OOB string. - * - * This is intended to be called after the bt_mesh_prov input callback - * has been called with BT_MESH_ENTER_STRING as the action. - * - * @param str String. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_mesh_input_string(const char *str); - -/** @brief Provide provisioning input OOB number. - * - * This is intended to be called after the bt_mesh_prov input callback - * has been called with BT_MESH_ENTER_NUMBER as the action. - * - * @param num Number. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_mesh_input_number(uint32_t num); - -/** @brief Provide Device public key. - * - * @param public_key Device public key in big-endian. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[BT_PUB_KEY_LEN]); - -/** @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 - * - * Enable one or more provisioning bearers. - * - * @param bearers Bit-wise or of provisioning bearers. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers); - -/** @brief Disable specific provisioning bearers - * - * Disable one or more provisioning bearers. - * - * @param bearers Bit-wise or of provisioning bearers. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers); - -/** - * @} - */ - -/** - * @brief Bluetooth Mesh - * @defgroup bt_mesh Bluetooth Mesh - * @ingroup bluetooth - * @{ - */ - -/* Primary Network Key index */ -#define BT_MESH_NET_PRIMARY 0x000 - -/* Features */ -#define BT_MESH_FEAT_RELAY BIT(0) -#define BT_MESH_FEAT_PROXY BIT(1) -#define BT_MESH_FEAT_FRIEND BIT(2) -#define BT_MESH_FEAT_LOW_POWER BIT(3) -#define BT_MESH_FEAT_SUPPORTED (BT_MESH_FEAT_RELAY | \ - BT_MESH_FEAT_PROXY | \ - BT_MESH_FEAT_FRIEND | \ - BT_MESH_FEAT_LOW_POWER) - -/** @brief Initialize Mesh support - * - * After calling this API, the node will not automatically advertise as - * unprovisioned, rather the bt_mesh_prov_enable() API needs to be called - * to enable unprovisioned advertising on one or more provisioning bearers. - * - * @param own_addr_type Node address type - * @param prov Node provisioning information. - * @param comp Node Composition. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_mesh_init(uint8_t own_addr_type, - const struct bt_mesh_prov *prov, - const struct bt_mesh_comp *comp); - -/** @brief Reset the state of the local Mesh node. - * - * Resets the state of the node, which means that it needs to be - * reprovisioned to become an active node in a Mesh network again. - * - * After calling this API, the node will not automatically advertise as - * unprovisioned, rather the bt_mesh_prov_enable() API needs to be called - * to enable unprovisioned advertising on one or more provisioning bearers. - * - */ -void bt_mesh_reset(void); - -/** @brief Suspend the Mesh network temporarily. - * - * This API can be used for power saving purposes, but the user should be - * aware that leaving the local node suspended for a long period of time - * may cause it to become permanently disconnected from the Mesh network. - * If at all possible, the Friendship feature should be used instead, to - * make the node into a Low Power Node. - * - * @return 0 on success, or (negative) error code on failure. - */ -int bt_mesh_suspend(void); - -/** @brief Resume a suspended Mesh network. - * - * This API resumes the local node, after it has been suspended using the - * bt_mesh_suspend() API. - * - * @return 0 on success, or (negative) error code on failure. - */ -int bt_mesh_resume(void); - -/** @brief Provision the local Mesh Node. - * - * This API should normally not be used directly by the application. The - * only exception is for testing purposes where manual provisioning is - * desired without an actual external provisioner. - * - * @param net_key Network Key - * @param net_idx Network Key Index - * @param flags Provisioning Flags - * @param iv_index IV Index - * @param addr Primary element address - * @param dev_key Device Key - * - * @return Zero on success or (negative) error code otherwise. - */ -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 - * - * @param uuid UUID - * @param net_idx Network Key Index - * @param addr Address to assign to remote device. If addr is 0, the lowest - * available address will be chosen. - * @param attention_duration The attention duration to be send to remote device - * - * @return Zero on success or (negative) error code otherwise. - */ -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. - * - * This API can be used to check if the local node has been provisioned - * or not. It can e.g. be helpful to determine if there was a stored - * network in flash, i.e. if the network was restored after calling - * settings_load(). - * - * @return True if the node is provisioned. False otherwise. - */ -bool bt_mesh_is_provisioned(void); - -/** @brief Toggle the IV Update test mode - * - * This API is only available if the IV Update test mode has been enabled - * in Kconfig. It is needed for passing most of the IV Update qualification - * test cases. - * - * @param enable true to enable IV Update test mode, false to disable it. - */ -void bt_mesh_iv_update_test(bool enable); - -/** @brief Toggle the IV Update state - * - * This API is only available if the IV Update test mode has been enabled - * in Kconfig. It is needed for passing most of the IV Update qualification - * test cases. - * - * @return true if IV Update In Progress state was entered, false otherwise. - */ -bool bt_mesh_iv_update(void); - -/** @brief Toggle the Low Power feature of the local device - * - * Enables or disables the Low Power feature of the local device. This is - * exposed as a run-time feature, since the device might want to change - * this e.g. based on being plugged into a stable power source or running - * from a battery power source. - * - * @param enable true to enable LPN functionality, false to disable it. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_mesh_lpn_set(bool enable); - -/** @brief Send out a Friend Poll message. - * - * Send a Friend Poll message to the Friend of this node. If there is no - * established Friendship the function will return an error. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_mesh_lpn_poll(void); - -/** @brief Register a callback for Friendship changes. - * - * Registers a callback that will be called whenever Friendship gets - * established or is lost. - * - * @param cb Function to call when the Friendship status changes. - */ -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); - -/** @brief Store pending RPL entry(ies) in the persistent storage. - * - * This API allows the user to store pending RPL entry(ies) in the persistent - * storage without waiting for the timeout. - * - * @note When flash is used as the persistent storage, calling this API too - * frequently may wear it out. - * - * @param addr Address of the node which RPL entry needs to be stored or - * @ref BT_MESH_ADDR_ALL_NODES to store all pending RPL entries. - */ -void bt_mesh_rpl_pending_store(uint16_t addr); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __BT_MESH_MAIN_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/mesh.h b/src/nimble/nimble/host/mesh/include/mesh/mesh.h deleted file mode 100644 index 2629b1a59..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/mesh.h +++ /dev/null @@ -1,33 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Profile APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_H -#define __BT_MESH_H - -#include -#include "syscfg/syscfg.h" -#include "nimble/porting/nimble/include/os/os_mbuf.h" - -#include "glue.h" -#include "msg.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 "nimble/nimble/host/mesh/src/app_keys.h" -#include "nimble/nimble/host/mesh/src/net.h" - -#endif /* __BT_MESH_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/model_cli.h b/src/nimble/nimble/host/mesh/include/mesh/model_cli.h deleted file mode 100644 index 87e2dd2be..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/model_cli.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __MODEL_CLI_H__ -#define __MODEL_CLI_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_mesh_gen_model_cli { - struct bt_mesh_model *model; - - struct k_sem op_sync; - uint32_t op_pending; - void *op_param; -}; - -extern const struct bt_mesh_model_op gen_onoff_cli_op[]; -extern const struct bt_mesh_model_cb bt_mesh_gen_onoff_cli_cb; - -#define BT_MESH_MODEL_GEN_ONOFF_CLI(cli_data, pub) \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, pub,\ - cli_data, &bt_mesh_gen_onoff_cli_cb) - -extern const struct bt_mesh_model_op gen_level_cli_op[]; -extern const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb; - -#define BT_MESH_MODEL_GEN_LEVEL_CLI(cli_data, pub) \ - 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(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 -} -#endif - -#endif /* __MODEL_CLI_H__ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/model_srv.h b/src/nimble/nimble/host/mesh/include/mesh/model_srv.h deleted file mode 100644 index a23296b83..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/model_srv.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __MODEL_SRV_H__ -#define __MODEL_SRV_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct bt_mesh_gen_onoff_srv { - struct bt_mesh_model *model; - - 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[]; -extern const struct bt_mesh_model_cb gen_onoff_srv_cb; - -#define BT_MESH_MODEL_GEN_ONOFF_SRV(srv, pub) \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, \ - gen_onoff_srv_op, pub, srv, &gen_onoff_srv_cb) - -struct bt_mesh_gen_level_srv { - struct bt_mesh_model *model; - - 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[]; -extern const struct bt_mesh_model_cb gen_level_srv_cb; - -#define BT_MESH_MODEL_GEN_LEVEL_SRV(srv, pub) \ - BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, \ - gen_level_srv_op, pub, srv, &gen_level_srv_cb) - -struct bt_mesh_light_lightness_srv { - struct bt_mesh_model *model; - - 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[]; -extern const struct bt_mesh_model_cb light_lightness_srv_cb; - -#define BT_MESH_MODEL_LIGHT_LIGHTNESS_SRV(srv, pub) \ - 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, 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 -} -#endif - -#endif /* __MODEL_SRV_H__ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/msg.h b/src/nimble/nimble/host/mesh/include/mesh/msg.h deleted file mode 100644 index e327545b1..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/msg.h +++ /dev/null @@ -1,225 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Message APIs. - */ - -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ -#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ - -/** - * @brief Bluetooth Mesh Message API - * @defgroup bt_mesh_msg Bluetooth Mesh Message API - * @ingroup bt_mesh - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** Length of a short Mesh MIC. */ -#define BT_MESH_MIC_SHORT 4 -/** Length of a long Mesh MIC. */ -#define BT_MESH_MIC_LONG 8 - -/** @def BT_MESH_MODEL_OP_LEN - * - * @brief Helper to determine the length of an opcode. - * - * @param _op Opcode. - */ -#define BT_MESH_MODEL_OP_LEN(_op) ((_op) <= 0xff ? 1 : (_op) <= 0xffff ? 2 : 3) - - -/** @def BT_MESH_MODEL_BUF_LEN - * - * @brief Helper for model message buffer length. - * - * Returns the length of a Mesh model message buffer, including the opcode - * length and a short MIC. - * - * @param _op Opcode of the message. - * @param _payload_len Length of the model payload. - */ -#define BT_MESH_MODEL_BUF_LEN(_op, _payload_len) \ - (BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_SHORT) - - -/** @def BT_MESH_MODEL_BUF_LEN_LONG_MIC - * - * @brief Helper for model message buffer length. - * - * Returns the length of a Mesh model message buffer, including the opcode - * length and a long MIC. - * - * @param _op Opcode of the message. - * @param _payload_len Length of the model payload. - */ -#define BT_MESH_MODEL_BUF_LEN_LONG_MIC(_op, _payload_len) \ - (BT_MESH_MODEL_OP_LEN(_op) + (_payload_len) + BT_MESH_MIC_LONG) - - -/** @def BT_MESH_MODEL_BUF_DEFINE - * - * @brief Define a Mesh model message buffer using @ref NET_BUF_SIMPLE_DEFINE. - * - * @param _buf Buffer name. - * @param _op Opcode of the message. - * @param _payload_len Length of the model message payload. - */ -#define BT_MESH_MODEL_BUF(_op, _payload_len) \ - NET_BUF_SIMPLE(BT_MESH_MODEL_BUF_LEN(_op, (_payload_len))) - - -/** Message sending context. */ -struct bt_mesh_msg_ctx { - /** NetKey Index of the subnet to send the message on. */ - uint16_t net_idx; - - /** AppKey Index to encrypt the message with. */ - uint16_t app_idx; - - /** Remote address. */ - uint16_t addr; - - /** Destination address of a received message. Not used for sending. */ - uint16_t recv_dst; - - /** RSSI of received packet. Not used for sending. */ - int8_t recv_rssi; - - /** Received TTL value. Not used for sending. */ - uint8_t recv_ttl; - - /** Force sending reliably by using segment acknowledgment */ - bool send_rel; - - /** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */ - uint8_t send_ttl; -}; - -/** @brief Initialize a model message. - * - * Clears the message buffer contents, and encodes the given opcode. - * The message buffer will be ready for filling in payload data. - * - * @param msg Message buffer. - * @param opcode Opcode to encode. - */ -void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode); - -/** - * Acknowledged message context for tracking the status of model messages pending a response. - */ -struct bt_mesh_msg_ack_ctx { - struct k_sem sem; /**< Sync semaphore. */ - uint32_t op; /**< Opcode we're waiting for. */ - uint16_t dst; /**< Address of the node that should respond. */ - void *user_data; /**< User specific parameter. */ -}; - -/** @brief Initialize an acknowledged message context. - * - * Initializes semaphore used for synchronization between @ref bt_mesh_msg_ack_ctx_wait and - * @ref bt_mesh_msg_ack_ctx_rx calls. Call this function before using @ref bt_mesh_msg_ack_ctx. - * - * @param ack Acknowledged message context to initialize. - */ -static inline void bt_mesh_msg_ack_ctx_init(struct bt_mesh_msg_ack_ctx *ack) -{ - k_sem_init(&ack->sem, 0, 1); -} - -/** @brief Reset the synchronization semaphore in an acknowledged message context. - * - * This function aborts call to @ref bt_mesh_msg_ack_ctx_wait. - * - * @param ack Acknowledged message context to be reset. - */ -static inline void bt_mesh_msg_ack_ctx_reset(struct bt_mesh_msg_ack_ctx *ack) -{ - k_sem_reset(&ack->sem); -} - -/** @brief Clear parameters of an acknowledged message context. - * - * This function clears the opcode, remote address and user data set - * by @ref bt_mesh_msg_ack_ctx_prepare. - * - * @param ack Acknowledged message context to be cleared. - */ -void bt_mesh_msg_ack_ctx_clear(struct bt_mesh_msg_ack_ctx *ack); - -/** @brief Prepare an acknowledged message context for the incoming message to wait. - * - * This function sets the opcode, remote address of the incoming message and stores the user data. - * Use this function before calling @ref bt_mesh_msg_ack_ctx_wait. - * - * @param ack Acknowledged message context to prepare. - * @param op The message OpCode. - * @param dst Destination address of the message. - * @param user_data User data for the acknowledged message context. - * - * @return 0 on success, or (negative) error code on failure. - */ -int bt_mesh_msg_ack_ctx_prepare(struct bt_mesh_msg_ack_ctx *ack, - uint32_t op, uint16_t dst, void *user_data); -/** @brief Check if the acknowledged message context is initialized with an opcode. - * - * @param ack Acknowledged message context. - * - * @return true if the acknowledged message context is initialized with an opcode, - * false otherwise. - */ -static inline bool bt_mesh_msg_ack_ctx_busy(struct bt_mesh_msg_ack_ctx *ack) -{ - return (ack->op != 0); -} - -/** @brief Wait for a message acknowledge. - * - * This function blocks execution until @ref bt_mesh_msg_ack_ctx_rx is called or by timeout. - * - * @param ack Acknowledged message context of the message to wait for. - * @param timeout Wait timeout. - * - * @return 0 on success, or (negative) error code on failure. - */ -int bt_mesh_msg_ack_ctx_wait(struct bt_mesh_msg_ack_ctx *ack, int32_t timeout); - -/** @brief Mark a message as acknowledged. - * - * This function unblocks call to @ref bt_mesh_msg_ack_ctx_wait. - * - * @param ack Context of a message to be acknowledged. - */ -static inline void bt_mesh_msg_ack_ctx_rx(struct bt_mesh_msg_ack_ctx *ack) -{ - k_sem_give(&ack->sem); -} - -/** @brief Check if an opcode and address of a message matches the expected one. - * - * @param ack Acknowledged message context to be checked. - * @param op OpCode of the incoming message. - * @param addr Source address of the incoming message. - * @param user_data If not NULL, returns a user data stored in the acknowledged message context - * by @ref bt_mesh_msg_ack_ctx_prepare. - * - * @return true if the incoming message matches the expected one, false otherwise. - */ -bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, - uint32_t op, uint16_t addr, void **user_data); - -#ifdef __cplusplus -} -#endif -/** - * @} - */ -#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_MSG_H_ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/porting.h b/src/nimble/nimble/host/mesh/include/mesh/porting.h deleted file mode 100644 index 1667a8a04..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/porting.h +++ /dev/null @@ -1,27 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Porting APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_PORTING_H -#define __BT_MESH_PORTING_H - -#ifdef __cplusplus -extern "C" { -#endif - -void mesh_adv_thread(void *args); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __BT_MESH_PORTING_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/proxy.h b/src/nimble/nimble/host/mesh/include/mesh/proxy.h deleted file mode 100644 index 63bbfa3e5..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/proxy.h +++ /dev/null @@ -1,43 +0,0 @@ -/** @file - * @brief Bluetooth Mesh Proxy APIs. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_PROXY_H -#define __BT_MESH_PROXY_H - -/** - * @brief Bluetooth Mesh Proxy - * @defgroup bt_mesh_proxy Bluetooth Mesh Proxy - * @ingroup bt_mesh - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Enable advertising with Node Identity. - * - * This API requires that GATT Proxy support has been enabled. Once called - * each subnet will start advertising using Node Identity for the next - * 60 seconds. - * - * @return 0 on success, or (negative) error code on failure. - */ -int bt_mesh_proxy_identity_enable(void); - -#ifdef __cplusplus -} -#endif - -/** - * @} - */ - -#endif /* __BT_MESH_PROXY_H */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/slist.h b/src/nimble/nimble/host/mesh/include/mesh/slist.h deleted file mode 100644 index 8a858f83b..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/slist.h +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * - * @brief Single-linked list implementation - * - * Single-linked list implementation using inline macros/functions. - * This API is not thread safe, and thus if a list is used across threads, - * calls to functions must be protected with synchronization primitives. - */ - -#ifndef __SLIST_H__ -#define __SLIST_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -struct _snode { - struct _snode *next; -}; - -typedef struct _snode sys_snode_t; - -struct _slist { - sys_snode_t *head; - sys_snode_t *tail; -}; - -typedef struct _slist sys_slist_t; - -/** - * @brief Provide the primitive to iterate on a list - * Note: the loop is unsafe and thus __sn should not be removed - * - * User _MUST_ add the loop statement curly braces enclosing its own code: - * - * SYS_SLIST_FOR_EACH_NODE(l, n) { - * - * } - * - * This and other SYS_SLIST_*() macros are not thread safe. - * - * @param __sl A pointer on a sys_slist_t to iterate on - * @param __sn A sys_snode_t pointer to peek each node of the list - */ -#define SYS_SLIST_FOR_EACH_NODE(__sl, __sn) \ - for (__sn = sys_slist_peek_head(__sl); __sn; \ - __sn = sys_slist_peek_next(__sn)) - -/** - * @brief Provide the primitive to iterate on a list, from a node in the list - * Note: the loop is unsafe and thus __sn should not be removed - * - * User _MUST_ add the loop statement curly braces enclosing its own code: - * - * SYS_SLIST_ITERATE_FROM_NODE(l, n) { - * - * } - * - * Like SYS_SLIST_FOR_EACH_NODE(), but __dn already contains a node in the list - * where to start searching for the next entry from. If NULL, it starts from - * the head. - * - * This and other SYS_SLIST_*() macros are not thread safe. - * - * @param __sl A pointer on a sys_slist_t to iterate on - * @param __sn A sys_snode_t pointer to peek each node of the list - * it contains the starting node, or NULL to start from the head - */ -#define SYS_SLIST_ITERATE_FROM_NODE(__sl, __sn) \ - for (__sn = __sn ? sys_slist_peek_next_no_check(__sn) \ - : sys_slist_peek_head(__sl); \ - __sn; \ - __sn = sys_slist_peek_next(__sn)) - -/** - * @brief Provide the primitive to safely iterate on a list - * Note: __sn can be removed, it will not break the loop. - * - * User _MUST_ add the loop statement curly braces enclosing its own code: - * - * SYS_SLIST_FOR_EACH_NODE_SAFE(l, n, s) { - * - * } - * - * This and other SYS_SLIST_*() macros are not thread safe. - * - * @param __sl A pointer on a sys_slist_t to iterate on - * @param __sn A sys_snode_t pointer to peek each node of the list - * @param __sns A sys_snode_t pointer for the loop to run safely - */ -#define SYS_SLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns) \ - for (__sn = sys_slist_peek_head(__sl), \ - __sns = sys_slist_peek_next(__sn); \ - __sn; __sn = __sns, \ - __sns = sys_slist_peek_next(__sn)) - -/* - * @brief Provide the primitive to resolve the container of a list node - * Note: it is safe to use with NULL pointer nodes - * - * @param __ln A pointer on a sys_node_t to get its container - * @param __cn Container struct type pointer - * @param __n The field name of sys_node_t within the container struct - */ -#define SYS_SLIST_CONTAINER(__ln, __cn, __n) \ - ((__ln) ? CONTAINER_OF((__ln), __typeof__(*(__cn)), __n) : NULL) -/* - * @brief Provide the primitive to peek container of the list head - * - * @param __sl A pointer on a sys_slist_t to peek - * @param __cn Container struct type pointer - * @param __n The field name of sys_node_t within the container struct - */ -#define SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n) \ - SYS_SLIST_CONTAINER(sys_slist_peek_head(__sl), __cn, __n) - -/* - * @brief Provide the primitive to peek container of the list tail - * - * @param __sl A pointer on a sys_slist_t to peek - * @param __cn Container struct type pointer - * @param __n The field name of sys_node_t within the container struct - */ -#define SYS_SLIST_PEEK_TAIL_CONTAINER(__sl, __cn, __n) \ - SYS_SLIST_CONTAINER(sys_slist_peek_tail(__sl), __cn, __n) - -/* - * @brief Provide the primitive to peek the next container - * - * @param __cn Container struct type pointer - * @param __n The field name of sys_node_t within the container struct - */ - -#define SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n) \ - ((__cn) ? SYS_SLIST_CONTAINER(sys_slist_peek_next(&((__cn)->__n)), \ - __cn, __n) : NULL) - -/** - * @brief Provide the primitive to iterate on a list under a container - * Note: the loop is unsafe and thus __cn should not be detached - * - * User _MUST_ add the loop statement curly braces enclosing its own code: - * - * SYS_SLIST_FOR_EACH_CONTAINER(l, c, n) { - * - * } - * - * @param __sl A pointer on a sys_slist_t to iterate on - * @param __cn A pointer to peek each entry of the list - * @param __n The field name of sys_node_t within the container struct - */ -#define SYS_SLIST_FOR_EACH_CONTAINER(__sl, __cn, __n) \ - for (__cn = SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n); __cn; \ - __cn = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n)) - -/** - * @brief Provide the primitive to safely iterate on a list under a container - * Note: __cn can be detached, it will not break the loop. - * - * User _MUST_ add the loop statement curly braces enclosing its own code: - * - * SYS_SLIST_FOR_EACH_NODE_SAFE(l, c, cn, n) { - * - * } - * - * @param __sl A pointer on a sys_slist_t to iterate on - * @param __cn A pointer to peek each entry of the list - * @param __cns A pointer for the loop to run safely - * @param __n The field name of sys_node_t within the container struct - */ -#define SYS_SLIST_FOR_EACH_CONTAINER_SAFE(__sl, __cn, __cns, __n) \ - for (__cn = SYS_SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n), \ - __cns = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n); __cn; \ - __cn = __cns, __cns = SYS_SLIST_PEEK_NEXT_CONTAINER(__cn, __n)) - -/** - * @brief Initialize a list - * - * @param list A pointer on the list to initialize - */ -static inline void sys_slist_init(sys_slist_t *list) -{ - list->head = NULL; - list->tail = NULL; -} - -#define SYS_SLIST_STATIC_INIT(ptr_to_list) {NULL, NULL} - -/** - * @brief Test if the given list is empty - * - * @param list A pointer on the list to test - * - * @return a boolean, true if it's empty, false otherwise - */ -static inline bool sys_slist_is_empty(sys_slist_t *list) -{ - return (!list->head); -} - -/** - * @brief Peek the first node from the list - * - * @param list A point on the list to peek the first node from - * - * @return A pointer on the first node of the list (or NULL if none) - */ -static inline sys_snode_t *sys_slist_peek_head(sys_slist_t *list) -{ - return list->head; -} - -/** - * @brief Peek the last node from the list - * - * @param list A point on the list to peek the last node from - * - * @return A pointer on the last node of the list (or NULL if none) - */ -static inline sys_snode_t *sys_slist_peek_tail(sys_slist_t *list) -{ - return list->tail; -} - -/** - * @brief Peek the next node from current node, node is not NULL - * - * Faster then sys_slist_peek_next() if node is known not to be NULL. - * - * @param node A pointer on the node where to peek the next node - * - * @return a pointer on the next node (or NULL if none) - */ -static inline sys_snode_t *sys_slist_peek_next_no_check(sys_snode_t *node) -{ - return node->next; -} - -/** - * @brief Peek the next node from current node - * - * @param node A pointer on the node where to peek the next node - * - * @return a pointer on the next node (or NULL if none) - */ -static inline sys_snode_t *sys_slist_peek_next(sys_snode_t *node) -{ - return node ? sys_slist_peek_next_no_check(node) : NULL; -} - -/** - * @brief Prepend a node to the given list - * - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * @param node A pointer on the node to prepend - */ -static inline void sys_slist_prepend(sys_slist_t *list, - sys_snode_t *node) -{ - node->next = list->head; - list->head = node; - - if (!list->tail) { - list->tail = list->head; - } -} - -/** - * @brief Append a node to the given list - * - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * @param node A pointer on the node to append - */ -static inline void sys_slist_append(sys_slist_t *list, - sys_snode_t *node) -{ - node->next = NULL; - - if (!list->tail) { - list->tail = node; - list->head = node; - } else { - list->tail->next = node; - list->tail = node; - } -} - -/** - * @brief Append a list to the given list - * - * Append a singly-linked, NULL-terminated list consisting of nodes containing - * the pointer to the next node as the first element of a node, to @a list. - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * @param head A pointer to the first element of the list to append - * @param tail A pointer to the last element of the list to append - */ -static inline void sys_slist_append_list(sys_slist_t *list, - void *head, void *tail) -{ - if (!list->tail) { - list->head = (sys_snode_t *)head; - list->tail = (sys_snode_t *)tail; - } else { - list->tail->next = (sys_snode_t *)head; - list->tail = (sys_snode_t *)tail; - } -} - -/** - * @brief merge two slists, appending the second one to the first - * - * When the operation is completed, the appending list is empty. - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * @param list_to_append A pointer to the list to append. - */ -static inline void sys_slist_merge_slist(sys_slist_t *list, - sys_slist_t *list_to_append) -{ - sys_slist_append_list(list, list_to_append->head, - list_to_append->tail); - sys_slist_init(list_to_append); -} - -/** - * @brief Insert a node to the given list - * - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * @param prev A pointer on the previous node - * @param node A pointer on the node to insert - */ -static inline void sys_slist_insert(sys_slist_t *list, - sys_snode_t *prev, - sys_snode_t *node) -{ - if (!prev) { - sys_slist_prepend(list, node); - } else if (!prev->next) { - sys_slist_append(list, node); - } else { - node->next = prev->next; - prev->next = node; - } -} - -/** - * @brief Fetch and remove the first node of the given list - * - * List must be known to be non-empty. - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * - * @return A pointer to the first node of the list - */ -static inline sys_snode_t *sys_slist_get_not_empty(sys_slist_t *list) -{ - sys_snode_t *node = list->head; - - list->head = node->next; - if (list->tail == node) { - list->tail = list->head; - } - - return node; -} - -/** - * @brief Fetch and remove the first node of the given list - * - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * - * @return A pointer to the first node of the list (or NULL if empty) - */ -static inline sys_snode_t *sys_slist_get(sys_slist_t *list) -{ - return sys_slist_is_empty(list) ? NULL : sys_slist_get_not_empty(list); -} - -/** - * @brief Remove a node - * - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * @param prev_node A pointer on the previous node - * (can be NULL, which means the node is the list's head) - * @param node A pointer on the node to remove - */ -static inline void sys_slist_remove(sys_slist_t *list, - sys_snode_t *prev_node, - sys_snode_t *node) -{ - if (!prev_node) { - list->head = node->next; - - /* Was node also the tail? */ - if (list->tail == node) { - list->tail = list->head; - } - } else { - prev_node->next = node->next; - - /* Was node the tail? */ - if (list->tail == node) { - list->tail = prev_node; - } - } - - node->next = NULL; -} - -/** - * @brief Find and remove a node from a list - * - * This and other sys_slist_*() functions are not thread safe. - * - * @param list A pointer on the list to affect - * @param node A pointer on the node to remove from the list - * - * @return true if node was removed - */ -static inline bool sys_slist_find_and_remove(sys_slist_t *list, - sys_snode_t *node) -{ - sys_snode_t *prev = NULL; - sys_snode_t *test; - - SYS_SLIST_FOR_EACH_NODE(list, test) { - if (test == node) { - sys_slist_remove(list, prev, node); - return true; - } - - prev = test; - } - - return false; -} - - -#ifdef __cplusplus -} -#endif - -#endif /* __SLIST_H__ */ diff --git a/src/nimble/nimble/host/mesh/include/mesh/testing.h b/src/nimble/nimble/host/mesh/include/mesh/testing.h deleted file mode 100644 index 580aafe41..000000000 --- a/src/nimble/nimble/host/mesh/include/mesh/testing.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file testing.h - * @brief Internal API for Bluetooth testing. - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __BT_TESTING_H -#define __BT_TESTING_H - -#include "slist.h" -#include "glue.h" -#include "access.h" - -/** - * @brief Bluetooth testing - * @defgroup bt_test_cb Bluetooth testing callbacks - * @ingroup bluetooth - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief Bluetooth Testing callbacks structure. - * - * Callback structure to be used for Bluetooth testing purposes. - * Allows access to Bluetooth stack internals, not exposed by public API. - */ -struct bt_test_cb { - 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)(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; -}; - -/** Register callbacks for Bluetooth testing purposes - * - * @param cb bt_test_cb callback structure - */ -void bt_test_cb_register(struct bt_test_cb *cb); - -/** Unregister callbacks for Bluetooth testing purposes - * - * @param cb bt_test_cb callback structure - */ -void bt_test_cb_unregister(struct bt_test_cb *cb); - -/** Send Friend Subscription List Add message. - * - * Used by Low Power node to send the group address for which messages are to - * be stored by Friend node. - * - * @param group Group address - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_test_mesh_lpn_group_add(uint16_t group); - -/** Send Friend Subscription List Remove message. - * - * Used by Low Power node to remove the group addresses from Friend node - * subscription list. Messages sent to those addresses will not be stored - * by Friend node. - * - * @param groups Group addresses - * @param groups_count Group addresses count - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count); - -/** Clear replay protection list cache. - * - * @return Zero on success or (negative) error code otherwise. - */ -int bt_test_mesh_rpl_clear(void); - -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, uint16_t key_idx, uint16_t id); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __BT_TESTING_H */ diff --git a/src/nimble/nimble/host/mesh/src/access.c b/src/nimble/nimble/host/mesh/src/access.c deleted file mode 100644 index a7df6fc52..000000000 --- a/src/nimble/nimble/host/mesh/src/access.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_ACCESS_LOG - -#include -#include -#include - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -#include "mesh_priv.h" -#include "adv.h" -#include "net.h" -#include "lpn.h" -#include "transport.h" -#include "access.h" -#include "foundation.h" -#include "settings.h" -#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS) -#include "nimble/nimble/host/mesh/include/mesh/model_cli.h" -#endif - -/* bt_mesh_model.flags */ -enum { - BT_MESH_MOD_BIND_PENDING = BIT(0), - BT_MESH_MOD_SUB_PENDING = BIT(1), - BT_MESH_MOD_PUB_PENDING = BIT(2), - BT_MESH_MOD_EXTENDED = BIT(3), -}; - -/* Model publication information for persistent storage. */ -struct mod_pub_val { - uint16_t addr; - uint16_t key; - uint8_t ttl; - uint8_t retransmit; - uint8_t period; - uint8_t period_div:4, - cred:1; -}; - -static const struct bt_mesh_comp *dev_comp; -static uint16_t dev_primary_addr; -static void (*msg_cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf); - -void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, - bool vnd, bool primary, - void *user_data), - void *user_data) -{ - int i, j; - - for (i = 0; i < dev_comp->elem_count; i++) { - struct bt_mesh_elem *elem = &dev_comp->elem[i]; - - for (j = 0; j < elem->model_count; j++) { - struct bt_mesh_model *model = &elem->models[j]; - - func(model, elem, false, i == 0, user_data); - } - - for (j = 0; j < elem->vnd_model_count; j++) { - struct bt_mesh_model *model = &elem->vnd_models[j]; - - func(model, elem, true, i == 0, user_data); - } - } -} - -int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) -{ - int period; - - if (!mod->pub) { - return 0; - } - - switch (mod->pub->period >> 6) { - case 0x00: - /* 1 step is 100 ms */ - period = K_MSEC((mod->pub->period & BIT_MASK(6)) * 100); - break; - case 0x01: - /* 1 step is 1 second */ - period = K_SECONDS(mod->pub->period & BIT_MASK(6)); - break; - case 0x02: - /* 1 step is 10 seconds */ - period = K_SECONDS((mod->pub->period & BIT_MASK(6)) * 10); - break; - case 0x03: - /* 1 step is 10 minutes */ - period = K_MINUTES((mod->pub->period & BIT_MASK(6)) * 10); - break; - default: - CODE_UNREACHABLE; - } - - if (mod->pub->fast_period) { - return period >> mod->pub->period_div; - } else { - return period; - } -} - -static int32_t next_period(struct bt_mesh_model *mod) -{ - struct bt_mesh_model_pub *pub = mod->pub; - uint32_t elapsed, period; - - period = bt_mesh_model_pub_period_get(mod); - if (!period) { - return 0; - } - - elapsed = k_uptime_get_32() - pub->period_start; - - BT_DBG("Publishing took %ums", (unsigned) elapsed); - - if (elapsed > period) { - BT_WARN("Publication sending took longer than the period"); - /* Return smallest positive number since 0 means disabled */ - return K_MSEC(1); - } - - return period - elapsed; -} - -static void publish_sent(int err, void *user_data) -{ - struct bt_mesh_model *mod = user_data; - int32_t delay; - - BT_DBG("err %d", err); - - if (mod->pub->count) { - delay = BT_MESH_PUB_TRANSMIT_INT(mod->pub->retransmit); - } else { - delay = next_period(mod); - } - - if (delay) { - BT_DBG("Publishing next time in %dms", (int) delay); - k_work_schedule(&mod->pub->timer, delay); - } -} - -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; - - if (err) { - BT_ERR("Failed to publish: err %d", err); - publish_sent(err, user_data); - return; - } - - /* Initialize the timestamp for the beginning of a new period */ - if (pub->count == BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit)) { - pub->period_start = k_uptime_get_32(); - } -} - -static const struct bt_mesh_send_cb pub_sent_cb = { - .start = publish_start, - .end = publish_sent, -}; - -static int publish_transmit(struct bt_mesh_model *mod) -{ - struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - struct bt_mesh_model_pub *pub = mod->pub; - 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, - .friend_cred = pub->cred, - }; - int err; - - net_buf_simple_init(sdu, 0); - net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len); - - err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod); - - os_mbuf_free_chain(sdu); - return err; -} - -static int pub_period_start(struct bt_mesh_model_pub *pub) -{ - int err; - - pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit); - - if (!pub->update) { - return 0; - } - - err = pub->update(pub->mod); - if (err) { - /* Skip this publish attempt. */ - BT_DBG("Update failed, skipping publish (err: %d)", err); - pub->count = 0; - pub->period_start = k_uptime_get_32(); - publish_sent(err, pub->mod); - return err; - } - - return 0; -} - -static void mod_publish(struct ble_npl_event *work) -{ - struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work); - int err; - - if (pub->addr == BT_MESH_ADDR_UNASSIGNED || - atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) { - /* Publication is no longer active, but the cancellation of the - * delayed work failed. Abandon recurring timer. - */ - return; - } - - BT_DBG(""); - - if (pub->count) { - pub->count--; - } else { - /* First publication in this period */ - err = pub_period_start(pub); - if (err) { - return; - } - } - - err = publish_transmit(pub->mod); - if (err) { - BT_ERR("Failed to publish (err %d)", err); - if (pub->count == BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit)) { - pub->period_start = k_uptime_get_32(); - } - - publish_sent(err, pub->mod); - } -} - -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, uint8_t elem_idx, uint8_t mod_idx) -{ - struct bt_mesh_elem *elem; - - if (elem_idx >= dev_comp->elem_count) { - BT_ERR("Invalid element index %u", elem_idx); - return NULL; - } - - elem = &dev_comp->elem[elem_idx]; - - if (vnd) { - if (mod_idx >= elem->vnd_model_count) { - BT_ERR("Invalid vendor model index %u", mod_idx); - return NULL; - } - - return &elem->vnd_models[mod_idx]; - } else { - if (mod_idx >= elem->model_count) { - BT_ERR("Invalid SIG model index %u", mod_idx); - return NULL; - } - - return &elem->models[mod_idx]; - } -} - -#if defined(CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE) -static int bt_mesh_vnd_mod_msg_cid_check(struct bt_mesh_model *mod) -{ - uint16_t cid; - const struct bt_mesh_model_op *op; - - for (op = mod->op; op->func; op++) { - cid = (uint16_t)(op->opcode & 0xffff); - - if (cid == mod->vnd.company) { - continue; - } - - BT_ERR("Invalid vendor model(company:0x%04x" - " id:0x%04x) message opcode 0x%08" PRIx32, - mod->vnd.company, mod->vnd.id, op->opcode); - - return -EINVAL; - } - - return 0; -} -#endif - -static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, - bool vnd, bool primary, void *user_data) -{ - int i; - int *err = user_data; - - if (*err) { - return; - } - - if (mod->pub) { - mod->pub->mod = mod; - k_work_init_delayable(&mod->pub->timer, mod_publish); - k_work_add_arg_delayable(&mod->pub->timer, mod->pub); - } - - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { - mod->keys[i] = BT_MESH_KEY_UNUSED; - } - - mod->elem_idx = elem - dev_comp->elem; - if (vnd) { - mod->mod_idx = mod - elem->vnd_models; - - if (CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE) { - *err = bt_mesh_vnd_mod_msg_cid_check(mod); - if (*err) { - return; - } - } - } else { - mod->mod_idx = mod - elem->models; - } - - if (mod->cb && mod->cb->init) { - *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 || !comp->elem_count) { - return -EINVAL; - } - - dev_comp = comp; - - err = 0; - bt_mesh_model_foreach(mod_init, &err); - - return err; -} - -void bt_mesh_comp_provision(uint16_t addr) -{ - int i; - - dev_primary_addr = addr; - - BT_DBG("addr 0x%04x elem_count %zu", addr, dev_comp->elem_count); - - for (i = 0; i < dev_comp->elem_count; i++) { - struct bt_mesh_elem *elem = &dev_comp->elem[i]; - - elem->addr = addr++; - - BT_DBG("addr 0x%04x mod_count %u vnd_mod_count %u", - elem->addr, elem->model_count, elem->vnd_model_count); - } -} - -void bt_mesh_comp_unprovision(void) -{ - BT_DBG(""); - - dev_primary_addr = BT_MESH_ADDR_UNASSIGNED; -} - -uint16_t bt_mesh_primary_addr(void) -{ - return dev_primary_addr; -} - -static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(mod->groups); i++) { - if (mod->groups[i] == addr) { - return &mod->groups[i]; - } - } - - return NULL; -} - -struct find_group_visitor_ctx { - uint16_t *entry; - struct bt_mesh_model *mod; - uint16_t addr; -}; - -static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod, void *user_data) -{ - struct find_group_visitor_ctx *ctx = user_data; - - if (mod->elem_idx != ctx->mod->elem_idx) { - return BT_MESH_WALK_CONTINUE; - } - - ctx->entry = model_group_get(mod, ctx->addr); - if (ctx->entry) { - ctx->mod = mod; - return BT_MESH_WALK_STOP; - } - - return BT_MESH_WALK_CONTINUE; -} - -uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr) -{ - struct find_group_visitor_ctx ctx = { - .mod = *mod, - .entry = NULL, - .addr = addr, - }; - - bt_mesh_model_extensions_walk(*mod, find_group_mod_visitor, &ctx); - - *mod = ctx.mod; - return ctx.entry; -} - -static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem, - uint16_t group_addr) -{ - struct bt_mesh_model *model; - uint16_t *match; - int i; - - for (i = 0; i < elem->model_count; i++) { - model = &elem->models[i]; - - match = model_group_get(model, group_addr); - if (match) { - return model; - } - } - - for (i = 0; i < elem->vnd_model_count; i++) { - model = &elem->vnd_models[i]; - - match = model_group_get(model, group_addr); - if (match) { - return model; - } - } - - return NULL; -} - -struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr) -{ - uint16_t index; - - if (!BT_MESH_ADDR_IS_UNICAST(addr)) { - return NULL; - } - - index = addr - dev_comp->elem[0].addr; - if (index >= dev_comp->elem_count) { - return NULL; - } - - return &dev_comp->elem[index]; -} - -bool bt_mesh_has_addr(uint16_t addr) -{ - uint16_t index; - - if (BT_MESH_ADDR_IS_UNICAST(addr)) { - return bt_mesh_elem_find(addr) != NULL; - } - - if (MYNEWT_VAL(BLE_MESH_ACCESS_LAYER_MSG) && msg_cb) { - return true; - } - - for (index = 0; index < dev_comp->elem_count; index++) { - struct bt_mesh_elem *elem = &dev_comp->elem[index]; - - if (bt_mesh_elem_find_group(elem, addr)) { - return true; - } - } - - return false; -} - -#if MYNEWT_VAL(BLE_MESH_ACCESS_LAYER_MSG) -void bt_mesh_msg_cb_set(void (*cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf)) -{ - msg_cb = cb; -} -#endif - -int bt_mesh_msg_send(struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf, uint16_t src_addr, - const struct bt_mesh_send_cb *cb, void *cb_data) -{ - struct bt_mesh_net_tx tx = { - .ctx = ctx, - .src = src_addr, - }; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx.ctx->net_idx, - tx.ctx->app_idx, tx.ctx->addr); - BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_is_provisioned()) { - BT_ERR("Local node is not yet provisioned"); - return -EAGAIN; - } - - return bt_mesh_trans_send(&tx, buf, cb, cb_data); -} - -uint8_t bt_mesh_elem_count(void) -{ - return dev_comp->elem_count; -} - -bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { - if (mod->keys[i] == key || - (mod->keys[i] == BT_MESH_KEY_DEV_ANY && - BT_MESH_IS_DEV_KEY(key))) { - return true; - } - } - - return false; -} - -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); - } - - /* 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_elem *elem, - uint32_t opcode, struct bt_mesh_model **model) -{ - uint8_t i; - uint8_t count; - /* This value shall not be used in shipping end products. */ - uint32_t cid = UINT32_MAX; - struct bt_mesh_model *models; - - /* SIG models cannot contain 3-byte (vendor) OpCodes, and - * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so - * we only need to do the lookup in one of the model lists. - */ - if (BT_MESH_MODEL_OP_LEN(opcode) < 3) { - models = elem->models; - count = elem->model_count; - } else { - models = elem->vnd_models; - count = elem->vnd_model_count; - - cid = (uint16_t)(opcode & 0xffff); - } - - for (i = 0U; i < count; i++) { - const struct bt_mesh_model_op *op; - - if (CONFIG_BT_MESH_MODEL_VND_MSG_CID_FORCE && - cid != UINT32_MAX && - cid != models[i].vnd.company) { - continue; - } - *model = &models[i]; - - for (op = (*model)->op; op->func; op++) { - if (op->opcode == opcode) { - return op; - } - } - } - - *model = NULL; - return NULL; -} - -static int get_opcode(struct os_mbuf *buf, uint32_t *opcode) -{ - switch (buf->om_data[0] >> 6) { - case 0x00: - case 0x01: - if (buf->om_data[0] == 0x7f) { - BT_ERR("Ignoring RFU OpCode"); - return -EINVAL; - } - - *opcode = net_buf_simple_pull_u8(buf); - return 0; - case 0x02: - if (buf->om_len < 2) { - BT_ERR("Too short payload for 2-octet OpCode"); - return -EINVAL; - } - - *opcode = net_buf_simple_pull_be16(buf); - return 0; - case 0x03: - if (buf->om_len < 3) { - BT_ERR("Too short payload for 3-octet OpCode"); - return -EINVAL; - } - - *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; - } - - CODE_UNREACHABLE; -} - -void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) -{ - struct bt_mesh_model *model; - const struct bt_mesh_model_op *op; - uint32_t opcode; - int i; - - BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx, - rx->ctx.addr, rx->ctx.recv_dst); - BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (get_opcode(buf, &opcode) < 0) { - BT_WARN("Unable to decode OpCode"); - return; - } - - BT_DBG("OpCode 0x%08x", (unsigned) opcode); - - for (i = 0; i < dev_comp->elem_count; i++) { - struct net_buf_simple_state state; - - op = find_op(&dev_comp->elem[i], opcode, &model); - - if (!op) { - BT_DBG("No OpCode 0x%08x for elem %d", opcode, i); - continue; - } - - if (!bt_mesh_model_has_key(model, rx->ctx.app_idx)) { - continue; - } - - if (!model_has_dst(model, rx->ctx.recv_dst)) { - continue; - } - - if ((op->len >= 0) && (buf->om_len < (size_t)op->len)) { - BT_ERR("Too short message for OpCode 0x%08" PRIx32, opcode); - continue; - } else if ((op->len < 0) && (buf->om_len != (size_t)(-op->len))) { - BT_ERR("Invalid message size for OpCode 0x%08" PRIx32, - opcode); - continue; - } - - /* The callback will likely parse the buffer, so - * store the parsing state in case multiple models - * receive the message. - */ - net_buf_simple_save(buf, &state); - (void)op->func(model, &rx->ctx, buf); - net_buf_simple_restore(buf, &state); - } - - if (MYNEWT_VAL(BLE_MESH_ACCESS_LAYER_MSG) && msg_cb) { - msg_cb(opcode, &rx->ctx, buf); - } -} - -int bt_mesh_model_send(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *msg, - const struct bt_mesh_send_cb *cb, void *cb_data) -{ - if (!bt_mesh_model_has_key(model, ctx->app_idx)) { - BT_ERR("Model not bound to AppKey 0x%04x", ctx->app_idx); - return -EINVAL; - } - - return bt_mesh_msg_send(ctx, msg, bt_mesh_model_elem(model)->addr, cb, cb_data); -} - -int bt_mesh_model_publish(struct bt_mesh_model *model) -{ - struct bt_mesh_model_pub *pub = model->pub; - - if (!pub) { - return -ENOTSUP; - } - - BT_DBG(""); - - if (pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return -EADDRNOTAVAIL; - } - - if (!pub->msg || !pub->msg->om_len) { - BT_ERR("No publication message"); - return -EINVAL; - } - - if (pub->msg->om_len + BT_MESH_MIC_SHORT > BT_MESH_TX_SDU_MAX) { - BT_ERR("Message does not fit maximum SDU size"); - return -EMSGSIZE; - } - - if (pub->count) { - BT_WARN("Clearing publish retransmit timer"); - } - - /* Account for initial transmission */ - pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit) + 1; - - BT_DBG("Publish Retransmit Count %u Interval %ums", pub->count, - BT_MESH_PUB_TRANSMIT_INT(pub->retransmit)); - - k_work_reschedule(&pub->timer, K_NO_WAIT); - - return 0; -} - -struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, - uint16_t company, uint16_t id) -{ - uint8_t i; - - for (i = 0; i < elem->vnd_model_count; i++) { - if (elem->vnd_models[i].vnd.company == company && - elem->vnd_models[i].vnd.id == id) { - return &elem->vnd_models[i]; - } - } - - return NULL; -} - -struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem, - uint16_t id) -{ - uint8_t i; - - for (i = 0; i < elem->model_count; i++) { - if (elem->models[i].id == id) { - return &elem->models[i]; - } - } - - return NULL; -} - -const struct bt_mesh_comp *bt_mesh_comp_get(void) -{ - return dev_comp; -} - -void bt_mesh_model_extensions_walk(struct bt_mesh_model *model, - enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, - void *user_data), - void *user_data) -{ -#ifndef CONFIG_BT_MESH_MODEL_EXTENSIONS - (void)cb(model, user_data); - return; -#else - struct bt_mesh_model *it; - - if (cb(model, user_data) == BT_MESH_WALK_STOP || !model->next) { - return; - } - /* List is circular. Step through all models until we reach the start: */ - for (it = model->next; it != model; it = it->next) { - if (cb(it, user_data) == BT_MESH_WALK_STOP) { - return; - } - } -#endif -} - -#if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS) -int bt_mesh_model_extend(struct bt_mesh_model *extending_mod, struct bt_mesh_model *base_mod) -{ - struct bt_mesh_model *a = extending_mod; - struct bt_mesh_model *b = base_mod; - struct bt_mesh_model *a_next = a->next; - struct bt_mesh_model *b_next = b->next; - struct bt_mesh_model *it; - - base_mod->flags |= BT_MESH_MOD_EXTENDED; - - if (a == b) { - return 0; - } - - /* Check if a's list contains b */ - for (it = a; (it != NULL) && (it->next != a); it = it->next) { - if (it == b) { - return 0; - } - } - - /* Merge lists */ - if (a_next) { - b->next = a_next; - } else { - b->next = a; - } - - if (b_next) { - a->next = b_next; - } else { - a->next = b; - } - - return 0; -} -#endif - -bool bt_mesh_model_is_extended(struct bt_mesh_model *model) -{ - return model->flags & BT_MESH_MOD_EXTENDED; -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static int mod_set_bind(struct bt_mesh_model *mod, char *val) -{ - int len, err, i; - - /* Start with empty array regardless of cleared or set value */ - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { - mod->keys[i] = BT_MESH_KEY_UNUSED; - } - - if (!val) { - BT_DBG("Cleared bindings for model"); - return 0; - } - - len = sizeof(mod->keys); - err = settings_bytes_from_str(val, mod->keys, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; - } - - BT_DBG("Decoded %u bound keys for model", len / sizeof(mod->keys[0])); - return 0; -} - -static int mod_set_sub(struct bt_mesh_model *mod, char *val) -{ - int len, err; - - /* Start with empty array regardless of cleared or set value */ - memset(mod->groups, 0, sizeof(mod->groups)); - - if (!val) { - BT_DBG("Cleared subscriptions for model"); - return 0; - } - - len = sizeof(mod->groups); - err = settings_bytes_from_str(val, mod->groups, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; - } - - BT_DBG("Decoded %u subscribed group addresses for model", - len / sizeof(mod->groups[0])); - return 0; -} - -static int mod_set_pub(struct bt_mesh_model *mod, char *val) -{ - struct mod_pub_val pub; - int len, err; - - if (!mod->pub) { - BT_WARN("Model has no publication context!"); - return -EINVAL; - } - - if (!val) { - mod->pub->addr = BT_MESH_ADDR_UNASSIGNED; - mod->pub->key = 0; - mod->pub->cred = 0; - mod->pub->ttl = 0; - mod->pub->period = 0; - mod->pub->retransmit = 0; - mod->pub->period_div = pub.period_div; - mod->pub->count = 0; - - BT_DBG("Cleared publication for model"); - return 0; - } - - len = sizeof(pub); - err = settings_bytes_from_str(val, &pub, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; - } - - if (len != sizeof(pub)) { - BT_ERR("Invalid length for model publication"); - return -EINVAL; - } - - mod->pub->addr = pub.addr; - mod->pub->key = pub.key; - mod->pub->cred = pub.cred; - mod->pub->ttl = pub.ttl; - mod->pub->period = pub.period; - mod->pub->retransmit = pub.retransmit; - mod->pub->period_div = pub.period_div; - mod->pub->count = 0; - - BT_DBG("Restored model publication, dst 0x%04x app_idx 0x%03x", - pub.addr, pub.key); - - return 0; -} - -static int mod_data_set(struct bt_mesh_model *mod, - char *name, char *len_rd) -{ - char *next; - - settings_name_next(name, &next); - - if (mod->cb && mod->cb->settings_set) { - return mod->cb->settings_set(mod, next, len_rd); - } - - return 0; -} - -static int mod_set(bool vnd, int argc, char **argv, char *val) -{ - struct bt_mesh_model *mod; - uint8_t elem_idx, mod_idx; - uint16_t mod_key; - - if (argc < 2) { - BT_ERR("Too small argc (%d)", argc); - return -ENOENT; - } - - mod_key = strtol(argv[0], NULL, 16); - elem_idx = mod_key >> 8; - mod_idx = mod_key; - - BT_DBG("Decoded mod_key 0x%04x as elem_idx %u mod_idx %u", - mod_key, elem_idx, mod_idx); - - mod = bt_mesh_model_get(vnd, elem_idx, mod_idx); - if (!mod) { - BT_ERR("Failed to get model for elem_idx %u mod_idx %u", - elem_idx, mod_idx); - return -ENOENT; - } - - if (!strcmp(argv[1], "bind")) { - return mod_set_bind(mod, val); - } - - if (!strcmp(argv[1], "sub")) { - return mod_set_sub(mod, val); - } - - if (!strcmp(argv[1], "pub")) { - return mod_set_pub(mod, val); - } - - if (!strcmp(argv[1], "data")) { - return mod_data_set(mod, argv[1], val); - } - - BT_WARN("Unknown module key %s", argv[1]); - return -ENOENT; -} - -static int sig_mod_set(int argc, char **argv, char *val) -{ - return mod_set(false, argc, argv, val); -} - -static int vnd_mod_set(int argc, char **argv, char *val) -{ - return mod_set(true, argc, argv, val); -} - -static void encode_mod_path(struct bt_mesh_model *mod, bool vnd, - const char *key, char *path, size_t path_len) -{ - uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx); - - if (vnd) { - snprintk(path, path_len, "bt_mesh/v/%x/%s", mod_key, key); - } else { - snprintk(path, path_len, "bt_mesh/s/%x/%s", mod_key, key); - } -} - -static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd) -{ - uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT]; - char buf[BT_SETTINGS_SIZE(sizeof(keys))]; - char path[20]; - int i, count, err; - char *val; - - for (i = 0, count = 0; i < ARRAY_SIZE(mod->keys); i++) { - if (mod->keys[i] != BT_MESH_KEY_UNUSED) { - keys[count++] = mod->keys[i]; - BT_DBG("model key 0x%04x", mod->keys[i]); - } - } - - if (count) { - val = settings_str_from_bytes(keys, count * sizeof(keys[0]), - buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model bindings as value"); - return; - } - } else { - val = NULL; - } - - encode_mod_path(mod, vnd, "bind", path, sizeof(path)); - - BT_DBG("Saving %s as %s", path, val ? val : "(null)"); - err = settings_save_one(path, val); - if (err) { - BT_ERR("Failed to store bind"); - } else { - BT_DBG("Stored bind"); - } -} - -static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd) -{ - uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT]; - char buf[BT_SETTINGS_SIZE(sizeof(groups))]; - char path[20]; - int i, count, err; - char *val; - - for (i = 0, count = 0; i < CONFIG_BT_MESH_MODEL_GROUP_COUNT; i++) { - if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { - groups[count++] = mod->groups[i]; - } - } - - if (count) { - val = settings_str_from_bytes(groups, count * sizeof(groups[0]), - buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model subscription as value"); - return; - } - } else { - val = NULL; - } - - encode_mod_path(mod, vnd, "sub", path, sizeof(path)); - - BT_DBG("Saving %s as %s", path, val ? val : "(null)"); - err = settings_save_one(path, val); - if (err) { - BT_ERR("Failed to store sub"); - } else { - BT_DBG("Stored sub"); - } -} - -static void store_pending_mod_pub(struct bt_mesh_model *mod, bool vnd) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))]; - struct mod_pub_val pub; - char path[20]; - char *val; - int err; - - if (!mod->pub || mod->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - val = NULL; - } else { - pub.addr = mod->pub->addr; - pub.key = mod->pub->key; - pub.ttl = mod->pub->ttl; - pub.retransmit = mod->pub->retransmit; - pub.period = mod->pub->period; - pub.period_div = mod->pub->period_div; - pub.cred = mod->pub->cred; - - val = settings_str_from_bytes(&pub, sizeof(pub), buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model publication as value"); - return; - } - } - - encode_mod_path(mod, vnd, "pub", path, sizeof(path)); - - BT_DBG("Saving %s as %s", path, val ? val : "(null)"); - err = settings_save_one(path, val); - if (err) { - BT_ERR("Failed to store pub"); - } else { - BT_DBG("Stored pub"); - } -} - -static void store_pending_mod(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, bool vnd, - bool primary, void *user_data) -{ - if (!mod->flags) { - return; - } - - if (mod->flags & BT_MESH_MOD_BIND_PENDING) { - mod->flags &= ~BT_MESH_MOD_BIND_PENDING; - store_pending_mod_bind(mod, vnd); - } - - if (mod->flags & BT_MESH_MOD_SUB_PENDING) { - mod->flags &= ~BT_MESH_MOD_SUB_PENDING; - store_pending_mod_sub(mod, vnd); - } - - if (mod->flags & BT_MESH_MOD_PUB_PENDING) { - mod->flags &= ~BT_MESH_MOD_PUB_PENDING; - store_pending_mod_pub(mod, vnd); - } -} - -void bt_mesh_model_pending_store(void) -{ - bt_mesh_model_foreach(store_pending_mod, NULL); -} - -void bt_mesh_model_bind_store(struct bt_mesh_model *mod) -{ - mod->flags |= BT_MESH_MOD_BIND_PENDING; - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); -} - -void bt_mesh_model_sub_store(struct bt_mesh_model *mod) -{ - mod->flags |= BT_MESH_MOD_SUB_PENDING; - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); -} - -void bt_mesh_model_pub_store(struct bt_mesh_model *mod) -{ - mod->flags |= BT_MESH_MOD_PUB_PENDING; - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_MOD_PENDING); -} - -int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, - const char *name, const void *data, - size_t data_len) -{ - char path[30]; - char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))]; - char *val; - int err; - - encode_mod_path(mod, vnd, "data", path, sizeof(path)); - if (name) { - strcat(path, "/"); - strncat(path, name, SETTINGS_MAX_DIR_DEPTH); - } - - if (data_len) { - val = settings_str_from_bytes(data, data_len, buf, sizeof(buf)); - if (!val) { - BT_ERR("Unable to encode model publication as value"); - return -EINVAL; - } - err = settings_save_one(path, val); - } else { - err = settings_save_one(path, NULL); - } - - if (err) { - BT_ERR("Failed to store %s value", path); - } else { - BT_DBG("Stored %s value", path); - } - return err; -} -#endif - -static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, - bool vnd, bool primary, void *user_data) -{ - if (mod->pub && mod->pub->update && - mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) { - int32_t ms = bt_mesh_model_pub_period_get(mod); - - if (ms > 0) { - BT_DBG("Starting publish timer (period %u ms)", ms); - k_work_schedule(&mod->pub->timer, K_MSEC(ms)); - } - } - - if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - return; - } - - for (int i = 0; i < ARRAY_SIZE(mod->groups); i++) { - if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { - bt_mesh_lpn_group_add(mod->groups[i]); - } - } -} - -void bt_mesh_model_settings_commit(void) -{ - bt_mesh_model_foreach(commit_mod, NULL); -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static struct conf_handler bt_mesh_sig_mod_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = sig_mod_set, - .ch_commit = NULL, - .ch_export = NULL, -}; - -static struct conf_handler bt_mesh_vnd_mod_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = vnd_mod_set, - .ch_commit = NULL, - .ch_export = NULL, -}; -#endif - -void bt_mesh_access_init(void) -{ - #if MYNEWT_VAL(BLE_MESH_SETTINGS) - int rc; - - rc = conf_register(&bt_mesh_sig_mod_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_access conf"); - rc = conf_register(&bt_mesh_vnd_mod_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_access conf"); - #endif -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/access.h b/src/nimble/nimble/host/mesh/src/access.h deleted file mode 100644 index 9b359e5ba..000000000 --- a/src/nimble/nimble/host/mesh/src/access.h +++ /dev/null @@ -1,88 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __ACCESS_H__ -#define __ACCESS_H__ - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -/* Tree walk return codes */ -enum bt_mesh_walk { - BT_MESH_WALK_STOP, - BT_MESH_WALK_CONTINUE, -}; - -void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count); - -uint8_t bt_mesh_elem_count(void); - -/* Find local element based on unicast address */ -struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); - -bool bt_mesh_has_addr(uint16_t addr); -bool bt_mesh_model_has_key(struct bt_mesh_model *mod, uint16_t key); - -void bt_mesh_model_extensions_walk(struct bt_mesh_model *root, - enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, - void *user_data), - void *user_data); - -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, - bool vnd, bool primary, - void *user_data), - void *user_data); - -int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod); - -void bt_mesh_comp_provision(uint16_t addr); -void bt_mesh_comp_unprovision(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, uint8_t elem_idx, uint8_t mod_idx); - -void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); - -int bt_mesh_comp_register(const struct bt_mesh_comp *comp); - -void bt_mesh_model_pending_store(void); -void bt_mesh_model_bind_store(struct bt_mesh_model *mod); -void bt_mesh_model_sub_store(struct bt_mesh_model *mod); -void bt_mesh_model_pub_store(struct bt_mesh_model *mod); -void bt_mesh_model_settings_commit(void); - -/** @brief Register a callback function hook for mesh model messages. - * - * Register a callback function to act as a hook for recieving mesh model layer messages - * directly to the application without having instantiated the relevant models. - * - * @param cb A pointer to the callback function. - */ -void bt_mesh_msg_cb_set(void (*cb)(uint32_t opcode, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf)); - -/** @brief Send a mesh model message. - * - * Send a mesh model layer message out into the mesh network without having instantiated - * the relevant mesh models. - * - * @param ctx The Bluetooth mesh message context. - * @param buf The message payload. - * - * @return 0 on success or negative error code on failure. - */ -int bt_mesh_msg_send(struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf, uint16_t src_addr, - const struct bt_mesh_send_cb *cb, void *cb_data); - -void bt_mesh_access_init(void); -#endif diff --git a/src/nimble/nimble/host/mesh/src/adv.c b/src/nimble/nimble/host/mesh/src/adv.c deleted file mode 100644 index 01caafeee..000000000 --- a/src/nimble/nimble/host/mesh/src/adv.c +++ /dev/null @@ -1,261 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2018 Nordic Semiconductor ASA - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_ADV_LOG - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/include/host/ble_hs_adv.h" -#include "nimble/nimble/host/include/host/ble_gap.h" -#include "nimble/nimble/host/mesh/include/mesh/porting.h" -#include "nimble/porting/nimble/include/nimble/nimble_port.h" - -#include "adv.h" -#include "net.h" -#include "foundation.h" -#include "beacon.h" -#include "prov.h" -#include "proxy.h" - -/* Window and Interval are equal for continuous scanning */ -#define MESH_SCAN_INTERVAL BT_MESH_ADV_SCAN_UNIT(BT_MESH_SCAN_INTERVAL_MS) -#define MESH_SCAN_WINDOW BT_MESH_ADV_SCAN_UNIT(BT_MESH_SCAN_WINDOW_MS) - -const uint8_t bt_mesh_adv_type[BT_MESH_ADV_TYPES] = { - [BT_MESH_ADV_PROV] = BT_DATA_MESH_PROV, - [BT_MESH_ADV_DATA] = BT_DATA_MESH_MESSAGE, - [BT_MESH_ADV_BEACON] = BT_DATA_MESH_BEACON, - [BT_MESH_ADV_URI] = BT_DATA_URI, -}; -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - -extern uint8_t g_mesh_addr_type; - -struct os_mbuf_pool adv_os_mbuf_pool; -struct ble_npl_eventq bt_mesh_adv_queue; - -os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( - MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; -struct os_mempool adv_buf_mempool; - -static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT]; - -static struct bt_mesh_adv *adv_alloc(int id) -{ - return &adv_pool[id]; -} - -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, - uint8_t xmit, int32_t timeout) -{ - struct bt_mesh_adv *adv; - struct os_mbuf *buf; - - if (atomic_test_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) { - BT_WARN("Refusing to allocate buffer while suspended"); - return NULL; - } - - buf = os_mbuf_get_pkthdr(pool, BT_MESH_ADV_USER_DATA_SIZE); - if (!buf) { - return NULL; - } - - adv = get_id(net_buf_id(buf)); - BT_MESH_ADV(buf) = adv; - - memset(adv, 0, sizeof(*adv)); - - adv->type = type; - adv->xmit = xmit; - - adv->ref_cnt = 1; - ble_npl_event_set_arg(&adv->ev, buf); - - return buf; -} - -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); -} - -void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - BT_DBG("buf %p, type 0x%02x len %u: %s", buf, BT_MESH_ADV(buf)->type, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - BT_MESH_ADV(buf)->cb = cb; - BT_MESH_ADV(buf)->cb_data = cb_data; - BT_MESH_ADV(buf)->busy = 1; - - net_buf_put(&bt_mesh_adv_queue, net_buf_ref(buf)); - bt_mesh_adv_buf_ready(); -} - -static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi, - uint8_t adv_type, struct os_mbuf *buf) -{ - if (adv_type != BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) { - return; - } - -#if BT_MESH_EXTENDED_DEBUG - BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); -#endif - - while (buf->om_len > 1) { - struct net_buf_simple_state state; - uint8_t len, type; - - len = net_buf_simple_pull_u8(buf); - /* Check for early termination */ - if (len == 0) { - return; - } - - if (len > buf->om_len) { - BT_WARN("AD malformed"); - return; - } - - net_buf_simple_save(buf, &state); - - type = net_buf_simple_pull_u8(buf); - - switch (type) { - case BLE_HS_ADV_TYPE_MESH_MESSAGE: - bt_mesh_net_recv(buf, rssi, BT_MESH_NET_IF_ADV); - break; -#if MYNEWT_VAL(BLE_MESH_PB_ADV) - case BLE_HS_ADV_TYPE_MESH_PROV: - bt_mesh_pb_adv_recv(buf); - break; -#endif - case BLE_HS_ADV_TYPE_MESH_BEACON: - bt_mesh_beacon_recv(buf); - break; - default: - break; - } - - net_buf_simple_restore(buf, &state); - net_buf_simple_pull_mem(buf, len); - } -} - -int -ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg) -{ -#if MYNEWT_VAL(BLE_EXT_ADV) - struct ble_gap_ext_disc_desc *ext_desc; -#endif - struct ble_gap_disc_desc *desc; - struct os_mbuf *buf = NULL; - -#if BT_MESH_EXTENDED_DEBUG - BT_DBG("event->type %d", event->type); -#endif - - switch (event->type) { -#if MYNEWT_VAL(BLE_EXT_ADV) - case BLE_GAP_EVENT_EXT_DISC: - ext_desc = &event->ext_disc; - buf = os_mbuf_get_pkthdr(&adv_os_mbuf_pool, 0); - if (!buf || os_mbuf_append(buf, ext_desc->data, ext_desc->length_data)) { - BT_ERR("Could not append data"); - goto done; - } - bt_mesh_scan_cb(&ext_desc->addr, ext_desc->rssi, - ext_desc->legacy_event_type, buf); - break; -#endif - case BLE_GAP_EVENT_DISC: - desc = &event->disc; - buf = os_mbuf_get_pkthdr(&adv_os_mbuf_pool, 0); - if (!buf || os_mbuf_append(buf, desc->data, desc->length_data)) { - BT_ERR("Could not append data"); - goto done; - } - - bt_mesh_scan_cb(&desc->addr, desc->rssi, desc->event_type, buf); - break; - default: - break; - } - -done: - if (buf) { - os_mbuf_free_chain(buf); - } - - return 0; -} - -int bt_mesh_scan_enable(void) -{ - int err; - -#if MYNEWT_VAL(BLE_EXT_ADV) - struct ble_gap_ext_disc_params uncoded_params = - { .itvl = MESH_SCAN_INTERVAL, .window = MESH_SCAN_WINDOW, - .passive = 1 }; - - BT_DBG(""); - - err = ble_gap_ext_disc(g_mesh_addr_type, 0, 0, 0, 0, 0, - &uncoded_params, NULL, NULL, NULL); -#else - struct ble_gap_disc_params scan_param = - { .passive = 1, .filter_duplicates = 0, .itvl = - MESH_SCAN_INTERVAL, .window = MESH_SCAN_WINDOW }; - - BT_DBG(""); - - err = ble_gap_disc(g_mesh_addr_type, BLE_HS_FOREVER, &scan_param, - NULL, NULL); -#endif - if (err && err != BLE_HS_EALREADY) { - BT_ERR("starting scan failed (err %d)", err); - return err; - } - - return 0; -} - -int bt_mesh_scan_disable(void) -{ - int err; - - BT_DBG(""); - - err = ble_gap_disc_cancel(); - if (err && err != BLE_HS_EALREADY) { - BT_ERR("stopping scan failed (err %d)", err); - return err; - } - - return 0; -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/adv.h b/src/nimble/nimble/host/mesh/src/adv.h deleted file mode 100644 index 3aa56c5e9..000000000 --- a/src/nimble/nimble/host/mesh/src/adv.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __ADV_H__ -#define __ADV_H__ - -/* Maximum advertising data payload for a single data type */ -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -#define BT_MESH_ADV(om) (*(struct bt_mesh_adv **) OS_MBUF_USRHDR(om)) - -#define BT_MESH_ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) -#define BT_MESH_SCAN_INTERVAL_MS 30 -#define BT_MESH_SCAN_WINDOW_MS 30 - -#define BT_MESH_ADV_DATA_SIZE 31 - -/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */ -#define BT_MESH_ADV_USER_DATA_SIZE 4 - -#define BT_MESH_MBUF_HEADER_SIZE (sizeof(struct os_mbuf_pkthdr) + \ - BT_MESH_ADV_USER_DATA_SIZE +\ - sizeof(struct os_mbuf)) - -/* We declare it as extern here to share it between 'adv' and 'adv_legacy' */ -extern struct os_mbuf_pool adv_os_mbuf_pool; -extern struct ble_npl_eventq bt_mesh_adv_queue; -extern struct os_mempool adv_buf_mempool; -extern os_membuf_t adv_buf_mem[]; - -enum bt_mesh_adv_type -{ - BT_MESH_ADV_PROV, - BT_MESH_ADV_DATA, - BT_MESH_ADV_BEACON, - BT_MESH_ADV_URI, - - BT_MESH_ADV_TYPES, -}; - -typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration, - int err, void *user_data); - - -static inline void adv_send_start(uint16_t duration, int err, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (cb && cb->start) { - cb->start(duration, err, cb_data); - } -} - -struct bt_mesh_adv { - /** Fragments associated with this buffer. */ - struct os_mbuf *frags; - - const struct bt_mesh_send_cb *cb; - void *cb_data; - - uint8_t type:2, - started:1, - busy:1; - - uint8_t xmit; - - uint8_t flags; - - int ref_cnt; - struct ble_npl_event ev; -}; - -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, 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, - 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); - -void bt_mesh_adv_update(void); - -void bt_mesh_adv_init(void); - -int bt_mesh_scan_enable(void); - -int bt_mesh_scan_disable(void); -int bt_mesh_adv_enable(void); - -void bt_mesh_adv_buf_ready(void); - -int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, - const struct bt_data *ad, size_t ad_len, - const struct bt_data *sd, size_t sd_len); - -static inline void bt_mesh_adv_send_start(uint16_t duration, int err, - struct bt_mesh_adv *adv) -{ - if (!adv->started) { - adv->started = 1; - - if (adv->cb && adv->cb->start) { - adv->cb->start(duration, err, adv->cb_data); - } - - if (err) { - adv->cb = NULL; - } - } -} - -static inline void bt_mesh_adv_send_end( - int err, struct bt_mesh_adv const *adv) -{ - if (adv->started && adv->cb && adv->cb->end) { - adv->cb->end(err, adv->cb_data); - } -} -int ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg); -#endif diff --git a/src/nimble/nimble/host/mesh/src/adv_ext.c b/src/nimble/nimble/host/mesh/src/adv_ext.c deleted file mode 100644 index ec3ebcea9..000000000 --- a/src/nimble/nimble/host/mesh/src/adv_ext.c +++ /dev/null @@ -1,345 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2018 Nordic Semiconductor ASA - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define MESH_LOG_MODULE BLE_MESH_ADV_LOG - - -#include "adv.h" -#include "net.h" -#include "proxy.h" -#include "pb_gatt_srv.h" -#include "syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_gap.h" - -#if MYNEWT_VAL(BLE_MESH_ADV_EXT) -/* Convert from ms to 0.625ms units */ -#define ADV_INT_FAST_MS 20 -#define BT_ID_DEFAULT 0 - -static struct ble_gap_ext_adv_params adv_param = { - .itvl_min = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS), - .itvl_max = BT_MESH_ADV_SCAN_UNIT(ADV_INT_FAST_MS), -}; - -bool ext_adv_configured = false; - -enum { - /** Controller is currently advertising */ - ADV_FLAG_ACTIVE, - /** Currently performing proxy advertising */ - ADV_FLAG_PROXY, - /** The send-call has been scheduled. */ - ADV_FLAG_SCHEDULED, - /** Custom adv params have been set, we need to update the parameters on - * the next send. - */ - ADV_FLAG_UPDATE_PARAMS, - - /* Number of adv flags. */ - ADV_FLAGS_NUM -}; - -static struct { - ATOMIC_DEFINE(flags, ADV_FLAGS_NUM); - struct bt_le_ext_adv *instance; - struct os_mbuf *buf; - int64_t timestamp; - struct k_work_delayable work; -} adv; - - -static void schedule_send(void) -{ - int64_t timestamp = adv.timestamp; - int64_t delta; - - if (atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { - ble_gap_ext_adv_stop(BT_ID_DEFAULT); - atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); - } - - if (atomic_test_bit(adv.flags, ADV_FLAG_ACTIVE) || - atomic_test_and_set_bit(adv.flags, ADV_FLAG_SCHEDULED)) { - return; - } - - /* The controller will send the next advertisement immediately. - * Introduce a delay here to avoid sending the next mesh packet closer - * to the previous packet than what's permitted by the specification. - */ - delta = k_uptime_delta(×tamp); - k_work_reschedule(&adv.work, K_MSEC(ADV_INT_FAST_MS - delta)); -} - -static int -ble_mesh_ext_adv_event_handler(struct ble_gap_event *event, void *arg) -{ - int64_t duration; - - switch (event->type) { - case BLE_GAP_EVENT_CONNECT: - if (atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { - atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); - schedule_send(); - } - break; - case BLE_GAP_EVENT_ADV_COMPLETE: - /* Calling k_uptime_delta on a timestamp moves it to the current time. - * This is essential here, as schedule_send() uses the end of the event - * as a reference to avoid sending the next advertisement too soon. - */ - duration = k_uptime_delta(&adv.timestamp); - - BT_DBG("Advertising stopped after %u ms", (uint32_t)duration); - - atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); - - if (!atomic_test_and_clear_bit(adv.flags, ADV_FLAG_PROXY)) { - net_buf_unref(adv.buf); - } - - schedule_send(); - break; - default: - return 0; - } - return 0; -} - -static int adv_start(const struct ble_gap_ext_adv_params *param, - uint32_t timeout, - const struct bt_data *ad, size_t ad_len, - const struct bt_data *sd, size_t sd_len) -{ - int err; - struct os_mbuf *ad_data; - struct os_mbuf *sd_data; - - ad_data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0); - assert(ad_data); - sd_data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0); - assert(sd_data); - if (!adv.instance) { - BT_ERR("Mesh advertiser not enabled"); - err = -ENODEV; - goto error; - } - - if (atomic_test_and_set_bit(adv.flags, ADV_FLAG_ACTIVE)) { - BT_ERR("Advertiser is busy"); - err = -EBUSY; - goto error; - } - - if (atomic_test_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS)) { - err = ble_gap_ext_adv_configure(BT_ID_DEFAULT, param, NULL, - ble_mesh_ext_adv_event_handler, NULL); - if (err) { - BT_ERR("Failed updating adv params: %d", err); - atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); - goto error; - } - - atomic_set_bit_to(adv.flags, ADV_FLAG_UPDATE_PARAMS, - param != &adv_param); - } - - assert(ad_data); - err = os_mbuf_append(ad_data, ad, ad_len); - if (err) { - goto error; - } - - err = ble_gap_ext_adv_set_data(BT_ID_DEFAULT, ad_data); - if (err) { - BT_ERR("Failed setting adv data: %d", err); - atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); - goto error; - } - - err = os_mbuf_append(sd_data, sd, sd_len); - if (err) { - goto error; - } - err = ble_gap_ext_adv_rsp_set_data(BT_ID_DEFAULT, sd_data); - if (err) { - BT_ERR("Failed setting scan response data: %d", err); - atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); - goto error; - } - - adv.timestamp = k_uptime_get(); - - err = ble_gap_ext_adv_start(BT_ID_DEFAULT, timeout, 0); - if (err) { - BT_ERR("Advertising failed: err %d", err); - atomic_clear_bit(adv.flags, ADV_FLAG_ACTIVE); - } - -error: - if (ad_data) { - os_mbuf_free_chain(ad_data); - } - - if (sd_data) { - os_mbuf_free_chain(sd_data); - } - return err; -} - -static int buf_send(struct os_mbuf *buf) -{ - static const uint8_t bt_mesh_adv_type[] = { - [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV, - [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE, - [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON, - [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI, - }; - - struct bt_le_ext_adv_start_param start = { - .num_events = - BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, - }; - uint16_t duration, adv_int; - struct bt_data ad; - int err; - - adv_int = MAX(ADV_INT_FAST_MS, - BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit)); - /* Upper boundary estimate: */ - duration = start.num_events * (adv_int + 10); - - BT_DBG("type %u len %u: %s", BT_MESH_ADV(buf)->type, - buf->om_len, bt_hex(buf->om_data, buf->om_len)); - BT_DBG("count %u interval %ums duration %ums", - BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int, - duration); - - ad.type = bt_mesh_adv_type[BT_MESH_ADV(buf)->type]; - ad.data_len = buf->om_len; - ad.data = buf->om_data; - - /* Only update advertising parameters if they're different */ - if (adv_param.itvl_min != BT_MESH_ADV_SCAN_UNIT(adv_int)) { - adv_param.itvl_min = BT_MESH_ADV_SCAN_UNIT(adv_int); - adv_param.itvl_max = adv_param.itvl_min; - atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS); - } - - err = adv_start(&adv_param, duration, &ad, 1, NULL, 0); - if (!err) { - adv.buf = net_buf_ref(buf); - } - - bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf)); - - return err; -} - -static void send_pending_adv(struct ble_npl_event *work) -{ - struct os_mbuf *buf; - int err; - - atomic_clear_bit(adv.flags, ADV_FLAG_SCHEDULED); - - while ((buf = net_buf_get(&bt_mesh_adv_queue, K_NO_WAIT))) { - /* busy == 0 means this was canceled */ - if (!BT_MESH_ADV(buf)->busy) { - net_buf_unref(buf); - continue; - } - - BT_MESH_ADV(buf)->busy = 0U; - err = buf_send(buf); - - net_buf_unref(buf); - - if (!err) { - return; /* Wait for advertising to finish */ - } - } - - if (!MYNEWT_VAL(BLE_MESH_GATT_SERVER)) { - return; - } - - /* No more pending buffers */ - if (bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - err = bt_mesh_proxy_adv_start(); - BT_DBG("Proxy Advertising"); - } - } else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - err = bt_mesh_pb_gatt_adv_start(); - BT_DBG("PB-GATT Advertising"); - } - - if (!err) { - atomic_set_bit(adv.flags, ADV_FLAG_PROXY); - } -} - -void bt_mesh_adv_update(void) -{ - BT_DBG(""); - - schedule_send(); -} - -void bt_mesh_adv_buf_ready(void) -{ - schedule_send(); -} - -void bt_mesh_adv_init(void) -{ - int rc; - - rc = os_mempool_init(&adv_buf_mempool, MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, - adv_buf_mem, "adv_buf_pool"); - assert(rc == 0); - - rc = os_mbuf_pool_init(&adv_os_mbuf_pool, &adv_buf_mempool, - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, - MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)); - assert(rc == 0); - - ble_npl_eventq_init(&bt_mesh_adv_queue); - - k_work_init_delayable(&adv.work, send_pending_adv); -} - -int bt_mesh_adv_enable(void) -{ - /* No need to initialize extended advertiser instance here */ - return 0; -} - -int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, - const struct bt_data *ad, size_t ad_len, - const struct bt_data *sd, size_t sd_len) -{ - static uint32_t adv_timeout; - struct ble_gap_ext_adv_params params = { - .itvl_min = param->itvl_min, - .itvl_max = param->itvl_max - }; - - /* In NimBLE duration is in ms, not 10ms units */ - adv_timeout = (duration == BLE_HS_FOREVER) ? 0 : duration; - - BT_DBG("Start advertising %d ms", duration); - - atomic_set_bit(adv.flags, ADV_FLAG_UPDATE_PARAMS); - - return adv_start(¶ms, adv_timeout, ad, ad_len, sd, sd_len); -} -#endif diff --git a/src/nimble/nimble/host/mesh/src/adv_legacy.c b/src/nimble/nimble/host/mesh/src/adv_legacy.c deleted file mode 100644 index 1df8690ae..000000000 --- a/src/nimble/nimble/host/mesh/src/adv_legacy.c +++ /dev/null @@ -1,257 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2018 Nordic Semiconductor ASA - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_ADV_LOG - -#include "adv.h" -#include "net.h" -#include "foundation.h" -#include "beacon.h" -#include "prov.h" -#include "proxy.h" -#include "nimble/nimble/host/mesh/include/mesh/glue.h" -#include "pb_gatt_srv.h" - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#if MYNEWT_VAL(BLE_MESH_ADV_LEGACY) -/* Convert from ms to 0.625ms units */ -#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) - -#if (MYNEWT_VAL(BSP_NRF51) && !MYNEWT_VAL(BLE_CONTROLLER)) -#define CONFIG_BT_CTLR_LOW_LAT 1 -#else -#define CONFIG_BT_CTLR_LOW_LAT 0 -#endif - -/* Pre-5.0 controllers enforce a minimum interval of 100ms - * whereas 5.0+ controllers can go down to 20ms. - */ -#define ADV_INT_DEFAULT_MS 100 -#define ADV_INT_FAST_MS 20 - -static int32_t adv_int_min = ADV_INT_DEFAULT_MS; - -static int adv_initialized = false; -/* TinyCrypt PRNG consumes a lot of stack space, so we need to have - * an increased call stack whenever it's used. - */ -#ifdef MYNEWT -OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); -struct os_task adv_task; -#endif - -static int32_t adv_timeout; - -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, - }; - - struct ble_gap_adv_params param = { 0 }; - uint16_t duration, adv_int; - struct bt_data ad; - int err; - - adv_int = MAX(adv_int_min, - BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit)); -#if MYNEWT_VAL(BLE_CONTROLLER) - duration = ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * - (adv_int + 10)); -#else - /* Zephyr Bluetooth Low Energy Controller for mesh stack uses - * pre-emptible continuous scanning, allowing advertising events to be - * transmitted without delay when advertising is enabled. No need to - * compensate with scan window duration. - * An advertising event could be delayed by upto one interval when - * advertising is stopped and started in quick succession, hence add - * advertising interval to the total advertising duration. - */ - duration = (adv_int + - ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * - (adv_int + 10))); - - /* Zephyr Bluetooth Low Energy Controller built for nRF51x SoCs use - * CONFIG_BT_CTLR_LOW_LAT=y, and continuous scanning cannot be - * pre-empted, hence, scanning will block advertising events from - * being transmitted. Increase the advertising duration by the - * amount of scan window duration to compensate for the blocked - * advertising events. - */ - if (CONFIG_BT_CTLR_LOW_LAT) { - duration += BT_MESH_SCAN_WINDOW_MS; - } -#endif - - BT_DBG("type %u om_len %u: %s", BT_MESH_ADV(buf)->type, - buf->om_len, bt_hex(buf->om_data, buf->om_len)); - BT_DBG("count %u interval %ums duration %ums", - BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1, adv_int, - duration); - - ad.type = adv_type[BT_MESH_ADV(buf)->type]; - ad.data_len = buf->om_len; - ad.data = buf->om_data; - - param.itvl_min = ADV_SCAN_UNIT(adv_int); - param.itvl_max = param.itvl_min; - param.conn_mode = BLE_GAP_CONN_MODE_NON; - - int64_t time = k_uptime_get(); - - err = bt_le_adv_start(¶m, &ad, 1, NULL, 0); - - bt_mesh_adv_send_start(duration, err, BT_MESH_ADV(buf)); - if (err) { - BT_ERR("Advertising failed: err %d", err); - return; - } - - BT_DBG("Advertising started. Sleeping %u ms", duration); - - k_sleep(K_MSEC(duration)); - - err = bt_le_adv_stop(); - if (err) { - BT_ERR("Stopping advertising failed: err %d", err); - return; - } - - BT_DBG("Advertising stopped (%u ms)", (uint32_t) k_uptime_delta(&time)); -} - -void -mesh_adv_thread(void *args) -{ - static struct ble_npl_event *ev; - struct os_mbuf *buf; - - BT_DBG("started"); - - while (1) { - if (MYNEWT_VAL(BLE_MESH_GATT_SERVER)) { - ev = ble_npl_eventq_get(&bt_mesh_adv_queue, 0); - while (!ev) { - /* Adv timeout may be set by a call from proxy - * to bt_mesh_adv_start: - */ - adv_timeout = K_FOREVER; - if (bt_mesh_is_provisioned()) { - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - bt_mesh_proxy_adv_start(); - BT_DBG("Proxy Advertising up to %d ms", (int) adv_timeout); - } - } else if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - bt_mesh_pb_gatt_adv_start(); - BT_DBG("PB-GATT Advertising up to %d ms", (int) adv_timeout); - } - - ev = ble_npl_eventq_get(&bt_mesh_adv_queue, ble_npl_time_ms_to_ticks32(adv_timeout)); - bt_le_adv_stop(); - } - } else { - ev = ble_npl_eventq_get(&bt_mesh_adv_queue, BLE_NPL_TIME_FOREVER); - } - if (!ev || !ble_npl_event_get_arg(ev)) { - continue; - } - - buf = ble_npl_event_get_arg(ev); - - /* busy == 0 means this was canceled */ - if (BT_MESH_ADV(buf)->busy) { - BT_MESH_ADV(buf)->busy = 0; - adv_send(buf); - } - - net_buf_unref(buf); - - /* os_sched(NULL); */ - } -} - -void bt_mesh_adv_update(void) -{ - static struct ble_npl_event ev = { }; - - BT_DBG(""); - - ble_npl_eventq_put(&bt_mesh_adv_queue, &ev); -} - -void bt_mesh_adv_buf_ready(void) -{ - /* Will be handled automatically */ -} - -void bt_mesh_adv_init(void) -{ - int rc; - - /* Advertising should only be initialized once. Calling - * os_task init the second time will result in an assert. */ - if (adv_initialized) { - return; - } - - rc = os_mempool_init(&adv_buf_mempool, MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT), - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, - adv_buf_mem, "adv_buf_pool"); - assert(rc == 0); - - rc = os_mbuf_pool_init(&adv_os_mbuf_pool, &adv_buf_mempool, - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, - MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)); - assert(rc == 0); - - ble_npl_eventq_init(&bt_mesh_adv_queue); - -#ifdef MYNEWT - os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL, - MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER, - g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); -#endif - - /* For BT5 controllers we can have fast advertising interval */ - if (ble_hs_hci_get_hci_version() >= BLE_HCI_VER_BCS_5_0) { - adv_int_min = ADV_INT_FAST_MS; - } - - adv_initialized = true; -} - -int bt_mesh_adv_enable(void) -{ - /* Dummy function - in legacy adv thread is started on init*/ - return 0; -} - -int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, - const struct bt_data *ad, size_t ad_len, - const struct bt_data *sd, size_t sd_len) -{ - adv_timeout = duration; - return bt_le_adv_start(param, ad, ad_len, sd, sd_len); -} -#endif - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/aes-ccm.c b/src/nimble/nimble/host/mesh/src/aes-ccm.c deleted file mode 100644 index 170b0e72e..000000000 --- a/src/nimble/nimble/host/mesh/src/aes-ccm.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#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) */ diff --git a/src/nimble/nimble/host/mesh/src/app_keys.c b/src/nimble/nimble/host/mesh/src/app_keys.c deleted file mode 100644 index 2e148a875..000000000 --- a/src/nimble/nimble/host/mesh/src/app_keys.c +++ /dev/null @@ -1,722 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#include -#include -#include "nimble/nimble/host/mesh/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" - -/* Tracking of what storage changes are pending for App Keys. We track this in - * a separate array here instead of within the respective bt_mesh_app_key - * struct itselve, since once a key gets deleted its struct becomes invalid - * and may be reused for other keys. - */ -struct app_key_update { - uint16_t key_idx:12, /* AppKey Index */ - valid:1, /* 1 if this entry is valid, 0 if not */ - clear:1; /* 1 if key needs clearing, 0 if storing */ -}; - -/* AppKey information for persistent storage. */ -struct app_key_val { - uint16_t net_idx; - bool updated; - uint8_t val[2][16]; -} __packed; - -/** Mesh Application Key. */ -struct app_key { - uint16_t net_idx; - uint16_t app_idx; - bool updated; - struct bt_mesh_app_cred { - uint8_t id; - uint8_t val[16]; - } keys[2]; -}; - -static struct app_key_update app_key_updates[CONFIG_BT_MESH_APP_KEY_COUNT]; - -static struct app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = { - [0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = { - .app_idx = BT_MESH_KEY_UNUSED, - .net_idx = BT_MESH_KEY_UNUSED, - } -}; - -static struct app_key *app_get(uint16_t app_idx) -{ - for (int i = 0; i < ARRAY_SIZE(apps); i++) { - if (apps[i].app_idx == app_idx) { - return &apps[i]; - } - } - - return NULL; -} - -static void clear_app_key(uint16_t app_idx) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - char path[20]; - int err; - - BT_DBG("AppKeyIndex 0x%03x", app_idx); - - snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx); - } else { - BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx); - } -#endif -} - -static void store_app_key(uint16_t app_idx) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - const struct app_key *app; - struct app_key_val key; - char path[20]; - char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; - int err; - char *str; - - snprintk(path, sizeof(path), "bt_mesh/AppKey/%x", app_idx); - - app = app_get(app_idx); - if (!app) { - BT_WARN("ApKeyIndex 0x%03x not found", app_idx); - return; - } - - key.net_idx = app->net_idx, - key.updated = app->updated, - - memcpy(key.val[0], app->keys[0].val, 16); - memcpy(key.val[1], app->keys[1].val, 16); - str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); - - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store AppKey"); - } else { - BT_DBG("Stored AppKey %s value"); - } -#endif -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static struct app_key_update *app_key_update_find(uint16_t key_idx, - struct app_key_update **free_slot) - { - struct app_key_update *match; - int i; - - match = NULL; - *free_slot = NULL; - - for (i = 0; i < ARRAY_SIZE(app_key_updates); i++) { - struct app_key_update *update = &app_key_updates[i]; - - if (!update->valid) { - *free_slot = update; - continue; - } - - if (update->key_idx == key_idx) { - match = update; - } - } - - return match; -} -#endif - -static void update_app_key_settings(uint16_t app_idx, bool store) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - struct app_key_update *update, *free_slot; - uint8_t clear = store ? 0U : 1U; - - BT_DBG("AppKeyIndex 0x%03x", app_idx); - - update = app_key_update_find(app_idx, &free_slot); - if (update) { - update->clear = clear; - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_APP_KEYS_PENDING); - return; - } - - if (!free_slot) { - if (store) { - store_app_key(app_idx); - } else { - clear_app_key(app_idx); - } - return; - } - - free_slot->valid = 1U; - free_slot->key_idx = app_idx; - free_slot->clear = clear; - - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_APP_KEYS_PENDING); -#endif -} - -static void app_key_evt(struct app_key *app, enum bt_mesh_key_evt evt) -{ - int i; - - for (i = 0; i < (sizeof(bt_mesh_app_key_cb_list)/sizeof(void *)); i++) { - if (bt_mesh_app_key_cb_list[i]) { - BT_DBG("app_key_evt %d", i); - bt_mesh_app_key_cb_list[i] (app->app_idx, app->net_idx, evt); - } - } -} - -static struct app_key *app_key_alloc(uint16_t app_idx) -{ - struct 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 app_key *app) -{ - BT_DBG("AppIdx 0x%03x", app->app_idx); - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - update_app_key_settings(app->app_idx, false); - } - - 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 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)) { - update_app_key_settings(app->app_idx, true); - } - - 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 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 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_NETKEY; - } - - 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"); - update_app_key_settings(app->app_idx, true); - } - - app_key_evt(app, BT_MESH_KEY_ADDED); - - return STATUS_SUCCESS; -} - -uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx, - const uint8_t key[16]) -{ - struct 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"); - update_app_key_settings(app->app_idx, true); - } - - 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 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 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 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 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_has_addr(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 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 app_key *app = &apps[i]; - - if (app->app_idx != BT_MESH_KEY_UNUSED) { - app_key_del(app); - } - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static int app_key_set(int argc, char **argv, char *val) -{ - struct app_key_val key; - uint16_t app_idx; - int len_rd, err; - - BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); - - app_idx = strtol(argv[0], NULL, 16); - len_rd = strtol(argv[1], NULL, 16); - - - if (!len_rd) { - return 0; - } - - err = settings_bytes_from_str(val, &key, &len_rd); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - err = bt_mesh_app_key_set(app_idx, key.net_idx, key.val[0], - key.updated ? key.val[1] : NULL); - if (err) { - BT_ERR("Failed to set \'app-key\'"); - return err; - } - - BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx); - - return 0; -} -#endif - -void bt_mesh_app_key_pending_store(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(app_key_updates); i++) { - struct app_key_update *update = &app_key_updates[i]; - - if (!update->valid) { - continue; - } - - if (update->clear) { - clear_app_key(update->key_idx); - } else { - store_app_key(update->key_idx); - } - - update->valid = 0U; - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static struct conf_handler bt_mesh_app_key_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = app_key_set, - .ch_commit = NULL, - .ch_export = NULL, -}; -#endif - -void bt_mesh_app_key_init(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - int rc; - - rc = conf_register(&bt_mesh_app_key_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_app_key conf"); -#endif -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/app_keys.h b/src/nimble/nimble/host/mesh/src/app_keys.h deleted file mode 100644 index d936e8a81..000000000 --- a/src/nimble/nimble/host/mesh/src/app_keys.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "subnet.h" - -/** @brief Reset the app keys module. */ -void bt_mesh_app_keys_reset(void); - -/** @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); - -extern void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx, - enum bt_mesh_key_evt evt); - -/** @brief Store pending application keys in persistent storage. */ -void bt_mesh_app_key_pending_store(void); -void bt_mesh_app_key_init(void); -#endif /* _BT_MESH_APP_KEYS_H_ */ diff --git a/src/nimble/nimble/host/mesh/src/atomic.h b/src/nimble/nimble/host/mesh/src/atomic.h deleted file mode 100644 index 2c7317948..000000000 --- a/src/nimble/nimble/host/mesh/src/atomic.h +++ /dev/null @@ -1,409 +0,0 @@ -/* 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/src/nimble/nimble/host/mesh/src/beacon.c b/src/nimble/nimble/host/mesh/src/beacon.c deleted file mode 100644 index 6ca3e857b..000000000 --- a/src/nimble/nimble/host/mesh/src/beacon.c +++ /dev/null @@ -1,476 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_BEACON_LOG - -#include -#include -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -#include "adv.h" -#include "mesh_priv.h" -#include "net.h" -#include "prov.h" -#include "crypto.h" -#include "beacon.h" -#include "foundation.h" -#include "atomic.h" - -#define PROVISIONED_INTERVAL (K_SECONDS(10)) - -#define BEACON_TYPE_UNPROVISIONED 0x00 -#define BEACON_TYPE_SECURE 0x01 - -/* 3 transmissions, 20ms interval */ -#define UNPROV_XMIT BT_MESH_TRANSMIT(2, 20) - -/* 1 transmission, 20ms interval */ -#define PROV_XMIT BT_MESH_TRANSMIT(0, 20) - -static struct k_work_delayable beacon_timer; - -static int cache_check(struct bt_mesh_subnet *sub, void *beacon_data) -{ - return !memcmp(sub->beacon_cache, beacon_data, 21); -} - -static void cache_add(uint8_t data[21], struct bt_mesh_subnet *sub) -{ - memcpy(sub->beacon_cache, data, 21); -} - -static void beacon_complete(int err, void *user_data) -{ - struct bt_mesh_subnet *sub = user_data; - - BT_DBG("err %d", err); - - sub->beacon_sent = k_uptime_get_32(); -} - -void bt_mesh_beacon_create(struct bt_mesh_subnet *sub, - struct os_mbuf *buf) -{ - uint8_t flags = bt_mesh_net_flags(sub); - struct bt_mesh_subnet_keys *keys; - - net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE); - - keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)]; - - net_buf_simple_add_u8(buf, flags); - - /* Network ID */ - net_buf_simple_add_mem(buf, keys->net_id, 8); - - /* IV Index */ - net_buf_simple_add_be32(buf, bt_mesh.iv_index); - - net_buf_simple_add_mem(buf, sub->auth, 8); - - BT_DBG("net_idx 0x%04x flags 0x%02x NetID %s", sub->net_idx, - flags, bt_hex(keys->net_id, 8)); - BT_DBG("IV Index 0x%08x Auth %s", (unsigned) bt_mesh.iv_index, - bt_hex(sub->auth, 8)); -} - -/* If the interval has passed or is within 5 seconds from now send a beacon */ -#define BEACON_THRESHOLD(sub) (K_SECONDS(10 * ((sub)->beacons_last + 1)) - \ - K_SECONDS(5)) - -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, - }; - uint32_t now = k_uptime_get_32(); - struct os_mbuf *buf; - uint32_t time_diff; - - BT_DBG(""); - - 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; - uint8_t uri_hash[16] = { 0 }; - struct os_mbuf *buf; - uint16_t oob_info; - - BT_DBG("unprovisioned_beacon_send"); - - buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, UNPROV_XMIT, K_NO_WAIT); - if (!buf) { - BT_ERR("Unable to allocate beacon buffer"); - return -ENOBUFS; - } - - prov = bt_mesh_prov_get(); - - net_buf_add_u8(buf, BEACON_TYPE_UNPROVISIONED); - net_buf_add_mem(buf, prov->uuid, 16); - - if (prov->uri && bt_mesh_s1(prov->uri, uri_hash) == 0) { - oob_info = prov->oob_info | BT_MESH_PROV_OOB_URI; - } else { - oob_info = prov->oob_info; - } - - net_buf_add_be16(buf, oob_info); - net_buf_add_mem(buf, uri_hash, 4); - - bt_mesh_adv_send(buf, NULL, NULL); - net_buf_unref(buf); - - if (prov->uri) { - size_t len; - - buf = bt_mesh_adv_create(BT_MESH_ADV_URI, UNPROV_XMIT, - K_NO_WAIT); - if (!buf) { - BT_ERR("Unable to allocate URI buffer"); - return -ENOBUFS; - } - - len = strlen(prov->uri); - if (net_buf_tailroom(buf) < len) { - BT_WARN("Too long URI to fit advertising data"); - } else { - net_buf_add_mem(buf, prov->uri, len); - bt_mesh_adv_send(buf, NULL, NULL); - } - - net_buf_unref(buf); - } - - return 0; -} - -static void unprovisioned_beacon_recv(struct os_mbuf *buf) -{ - const struct bt_mesh_prov *prov; - 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); - return; - } - - uuid = net_buf_simple_pull_mem(buf, 16); - oob_info = net_buf_simple_pull_be16(buf); - - if (buf->om_len == 4) { - uri_hash_val = net_buf_simple_pull_be32(buf); - uri_hash = &uri_hash_val; - } - - BT_DBG("uuid %s", bt_hex(uuid, 16)); - - prov = bt_mesh_prov_get(); - - if (prov->unprovisioned_beacon) { - prov->unprovisioned_beacon(uuid, - (bt_mesh_prov_oob_info_t)oob_info, - uri_hash); - } -} - -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; - - /* Observation period is 20 seconds, whereas the beacon timer - * runs every 10 seconds. We process what's happened during the - * window only after the seconnd half. - */ - first_half = !first_half; - if (first_half) { - return; - } - - bt_mesh_subnet_foreach(sub_update_beacon_observation); -} - -static void beacon_send(struct ble_npl_event *work) -{ - - BT_DBG(""); - - if (bt_mesh_is_provisioned()) { - if (!bt_mesh_beacon_enabled() && - !atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { - return; - } - - update_beacon_observation(); - (void)bt_mesh_subnet_find(secure_beacon_send, NULL); - - k_work_schedule(&beacon_timer, PROVISIONED_INTERVAL); - - return; - } - - if (IS_ENABLED(BLE_MESH_PB_ADV)) { - /* Don't send anything if we have an active provisioning link */ - if (!bt_mesh_prov_active()) { - unprovisioned_beacon_send(); - } - - k_work_schedule(&beacon_timer, K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT))); - } -} - -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) -{ - struct beacon_params params; - struct bt_mesh_subnet *sub; - uint8_t *data; - - if (buf->om_len < 21) { - BT_ERR("Too short secure beacon (len %u)", buf->om_len); - return; - } - - 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; - } - - /* So we can add to the cache if auth matches */ - data = 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", - params.flags, bt_hex(params.net_id, 8), params.iv_index); - - 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 && !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) { - BT_WARN("Ignoring secure beacon on non-primary subnet"); - goto update_stats; - } - - BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x", - 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(params.flags))) { - bt_mesh_beacon_ivu_initiator(false); - } - - bt_mesh_net_iv_update(params.iv_index, BT_MESH_IV_UPDATE(params.flags)); - -update_stats: - if (bt_mesh_beacon_enabled() && - sub->beacons_cur < 0xff) { - sub->beacons_cur++; - } -} - -void bt_mesh_beacon_recv(struct os_mbuf *buf) -{ - uint8_t type; - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_len < 1) { - BT_ERR("Too short beacon"); - return; - } - - type = net_buf_simple_pull_u8(buf); - switch (type) { - case BEACON_TYPE_UNPROVISIONED: - if (IS_ENABLED(BLE_MESH_PB_ADV)) { - unprovisioned_beacon_recv(buf); - } - break; - case BEACON_TYPE_SECURE: - secure_beacon_recv(buf); - break; - default: - BT_WARN("Unknown beacon type 0x%02x", type); - break; - } -} - -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_work_init_delayable(&beacon_timer, beacon_send); -} - -void bt_mesh_beacon_ivu_initiator(bool enable) -{ - atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable); - - /* Fire the beacon handler straight away if it's not already pending - - * in which case we'll fire according to the ongoing periodic sending. - * If beacons are disabled, the handler will exit early. - * - * An alternative solution would be to check whether beacons are enabled - * here, and cancel if not. As the cancel operation may fail, we would - * still have to implement an early exit mechanism, so we might as well - * just use this every time. - */ - k_work_schedule(&beacon_timer, K_NO_WAIT); -} - -static void subnet_beacon_enable(struct bt_mesh_subnet *sub) -{ - sub->beacons_last = 0U; - sub->beacons_cur = 0U; - - bt_mesh_beacon_update(sub); -} - -void bt_mesh_beacon_enable(void) -{ - if (bt_mesh_is_provisioned()) { - bt_mesh_subnet_foreach(subnet_beacon_enable); - } - - k_work_reschedule(&beacon_timer, K_NO_WAIT); -} - -void bt_mesh_beacon_disable(void) -{ - if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { - /* If this fails, we'll do an early exit in the work handler. */ - (void)k_work_cancel_delayable(&beacon_timer); - } -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/beacon.h b/src/nimble/nimble/host/mesh/src/beacon.h deleted file mode 100644 index 50f27cff9..000000000 --- a/src/nimble/nimble/host/mesh/src/beacon.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __BEACON_H__ -#define __BEACON_H__ - -#include "nimble/porting/nimble/include/os/os_mbuf.h" - -void bt_mesh_beacon_enable(void); -void bt_mesh_beacon_disable(void); - -void bt_mesh_beacon_ivu_initiator(bool enable); - -void bt_mesh_beacon_recv(struct os_mbuf *buf); - -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/src/nimble/nimble/host/mesh/src/cdb.c b/src/nimble/nimble/host/mesh/src/cdb.c deleted file mode 100644 index 7407949e9..000000000 --- a/src/nimble/nimble/host/mesh/src/cdb.c +++ /dev/null @@ -1,1147 +0,0 @@ -/* - * Copyright (c) 2019 Tobias Svehagen - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_LOG -#include "nimble/porting/nimble/include/log/log.h" -#include - -#include "cdb_priv.h" -#include "net.h" -#include "rpl.h" -#include "settings.h" -#include "mesh_priv.h" -#include "nimble/nimble/host/mesh/include/mesh/glue.h" - -#if MYNEWT_VAL(BLE_MESH_CDB) -/* Tracking of what storage changes are pending for App and Net Keys. We - * track this in a separate array here instead of within the respective - * bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key - * gets deleted its struct becomes invalid and may be reused for other keys. - */ -struct key_update { - uint16_t key_idx:12, /* AppKey or NetKey Index */ - valid:1, /* 1 if this entry is valid, 0 if not */ - app_key:1, /* 1 if this is an AppKey, 0 if a NetKey */ - clear:1; /* 1 if key needs clearing, 0 if storing */ -}; - -/* Tracking of what storage changes are pending for node settings. */ -struct node_update { - uint16_t addr; - bool clear; -}; - -/* Node information for persistent storage. */ -struct node_val { - uint16_t net_idx; - uint8_t num_elem; - uint8_t flags; -#define F_NODE_CONFIGURED 0x01 - uint8_t uuid[16]; - uint8_t dev_key[16]; -} __packed; - -/* NetKey storage information */ -struct net_key_val { - uint8_t kr_flag:1, - kr_phase:7; - uint8_t val[2][16]; -} __packed; - -/* AppKey information for persistent storage. */ -struct app_key_val { - uint16_t net_idx; - bool updated; - uint8_t val[2][16]; -} __packed; - -/* IV Index & IV Update information for persistent storage. */ -struct net_val { - uint32_t iv_index; - bool iv_update; -} __packed; - -static struct node_update cdb_node_updates[MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)]; -static struct key_update cdb_key_updates[MYNEWT_VAL(BLE_MESH_CDB_SUBNET_COUNT) + - MYNEWT_VAL(BLE_MESH_CDB_APP_KEY_COUNT)]; - -struct bt_mesh_cdb bt_mesh_cdb = { - .nodes = { - [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = { - .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; -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static int cdb_net_set(int argc, char *val) -{ - struct net_val net; - int len, err; - - len = sizeof(net); - err = settings_bytes_from_str(val, &net, &len); - if (err) { - BT_ERR("Failed to set \'cdb_net\'"); - return err; - } - - bt_mesh_cdb.iv_index = net.iv_index; - - if (net.iv_update) { - atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS); - } - - atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID); - - return 0; -} - -static int cdb_node_set(int argc, char *str) -{ - struct bt_mesh_cdb_node *node; - struct node_val val; - uint16_t addr; - int len, err; - - if (argc < 1) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; - } - - addr = strtol(str, NULL, 16); - len = sizeof(str); - - if (argc < 1) { - BT_DBG("val (null)"); - BT_DBG("Deleting node 0x%04x", addr); - - node = bt_mesh_cdb_node_get(addr); - if (node) { - bt_mesh_cdb_node_del(node, false); - } - - return 0; - } - - err = settings_bytes_from_str(str, &val, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return -EINVAL; - } - - if (len != sizeof(struct node_val)) { - BT_ERR("Invalid length for node_val"); - return -EINVAL; - } - - node = bt_mesh_cdb_node_get(addr); - if (!node) { - node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem, - val.net_idx); - } - - if (!node) { - BT_ERR("No space for a new node"); - return -ENOMEM; - } - - if (val.flags & F_NODE_CONFIGURED) { - atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED); - } - - memcpy(node->uuid, val.uuid, 16); - memcpy(node->dev_key, val.dev_key, 16); - - BT_DBG("Node 0x%04x recovered from storage", addr); - - return 0; -} - -static int cdb_subnet_set(int argc, char *name) -{ - struct bt_mesh_cdb_subnet *sub; - struct net_key_val key; - uint16_t net_idx; - int len, len_rd, err; - - if (!name) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; - } - - len_rd = sizeof(sub); - net_idx = strtol(name, NULL, 16); - sub = bt_mesh_cdb_subnet_get(net_idx); - - if (len_rd == 0) { - BT_DBG("val (null)"); - if (!sub) { - BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx); - return -ENOENT; - } - - BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx); - bt_mesh_cdb_subnet_del(sub, false); - return 0; - } - - len = sizeof(key); - err = settings_bytes_from_str(name, &key, &len); - if (err) { - BT_ERR("Failed to set \'net-key\'"); - return err; - } - - if (sub) { - BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx); - - sub->kr_phase = key.kr_phase; - memcpy(sub->keys[0].net_key, &key.val[0], 16); - memcpy(sub->keys[1].net_key, &key.val[1], 16); - - return 0; - } - - sub = bt_mesh_cdb_subnet_alloc(net_idx); - if (!sub) { - BT_ERR("No space to allocate a new subnet"); - return -ENOMEM; - } - - sub->kr_phase = key.kr_phase; - memcpy(sub->keys[0].net_key, &key.val[0], 16); - memcpy(sub->keys[1].net_key, &key.val[1], 16); - - BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx); - - return 0; -} - -static int cdb_app_key_set(int argc, char *name) -{ - struct bt_mesh_cdb_app_key *app; - struct app_key_val key; - uint16_t app_idx; - int len_rd, err; - - app_idx = strtol(name, NULL, 16); - len_rd = sizeof(key); - - if (len_rd == 0) { - BT_DBG("val (null)"); - BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx); - - app = bt_mesh_cdb_app_key_get(app_idx); - if (app) { - bt_mesh_cdb_app_key_del(app, false); - } - - return 0; - } - - err = settings_bytes_from_str(name, &key, &len_rd); - if (err) { - BT_ERR("Failed to set \'app-key\'"); - return err; - } - - app = bt_mesh_cdb_app_key_get(app_idx); - if (!app) { - app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx); - } - - if (!app) { - BT_ERR("No space for a new app key"); - return -ENOMEM; - } - - memcpy(app->keys[0].app_key, key.val[0], 16); - memcpy(app->keys[1].app_key, key.val[1], 16); - - BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx); - - return 0; -} - -static int cdb_set(int argc, char **argv, char *name) -{ - int len; - char *next; - - if (argc < 1) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; - } - - if (!strcmp(name, "Net")) { - return cdb_net_set(1, name); - } - - len = settings_name_next(name, &next); - - if (!next) { - BT_ERR("Insufficient number of arguments"); - return -ENOENT; - } - - if (!strncmp(name, "Node", len)) { - return cdb_node_set(1, next); - } - - if (!strncmp(name, "Subnet", len)) { - return cdb_subnet_set(1, next); - } - - if (!strncmp(name, "AppKey", len)) { - return cdb_app_key_set(1, next); - } - - BT_WARN("Unknown module key %s", name); - return -ENOENT; -} -#endif - -static void store_cdb_node(const struct bt_mesh_cdb_node *node) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - char buf[BT_SETTINGS_SIZE(sizeof(struct node_val))]; - struct node_val val; - char path[30]; - char *str; - int err; - - val.net_idx = node->net_idx; - val.num_elem = node->num_elem; - val.flags = 0; - - if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) { - val.flags |= F_NODE_CONFIGURED; - } - - memcpy(val.uuid, node->uuid, 16); - memcpy(val.dev_key, node->dev_key, 16); - - snprintk(path, sizeof(path), "bt_mesh/cdb/Node/%x", node->addr); - - str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Node as value"); - return; - } - - - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store Node %s value", path); - } else { - BT_DBG("Stored Node %s value", path); - } -#endif -} - -static void clear_cdb_node(uint16_t addr) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - char path[30]; - int err; - - BT_DBG("Node 0x%04x", addr); - - snprintk(path, sizeof(path), "bt_mesh/cdb/Node/%x", addr); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear Node 0x%04x", addr); - } else { - BT_DBG("Cleared Node 0x%04x", addr); - } -#endif -} - -static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))]; - struct net_key_val key; - char path[30]; - int err; - char *str; - - BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx, - bt_hex(sub->keys[0].net_key, 16)); - - memcpy(&key.val[0], sub->keys[0].net_key, 16); - memcpy(&key.val[1], sub->keys[1].net_key, 16); - key.kr_flag = 0U; /* Deprecated */ - key.kr_phase = sub->kr_phase; - - snprintk(path, sizeof(path), "bt_mesh/cdb/Subnet/%x", sub->net_idx); - - - str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Subnet as value"); - return; - } - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store Subnet value"); - } else { - BT_DBG("Stored Subnet value"); - } -#endif -} - -static void clear_cdb_subnet(uint16_t net_idx) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - 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); - } -#endif -} - -static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; - struct app_key_val key; - char path[30]; - 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"); - } -#endif -} - -static void clear_cdb_app_key(uint16_t app_idx) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - 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); - } -#endif -} - -static void schedule_cdb_store(int flag) -{ - atomic_set_bit(bt_mesh_cdb.flags, flag); - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CDB_PENDING); -} - -static void update_cdb_net_settings(void) -{ - schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING); -} - -static struct node_update *cdb_node_update_find(uint16_t addr, - struct node_update **free_slot) -{ - struct node_update *match; - int i; - - match = NULL; - *free_slot = NULL; - - for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) { - struct node_update *update = &cdb_node_updates[i]; - - if (update->addr == BT_MESH_ADDR_UNASSIGNED) { - *free_slot = update; - continue; - } - - if (update->addr == addr) { - match = update; - } - } - - return match; -} - -static void update_cdb_node_settings(const struct bt_mesh_cdb_node *node, - bool store) -{ - struct node_update *update, *free_slot; - - BT_DBG("Node 0x%04x", node->addr); - - update = cdb_node_update_find(node->addr, &free_slot); - if (update) { - update->clear = !store; - schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); - return; - } - - if (!free_slot) { - if (store) { - store_cdb_node(node); - } else { - clear_cdb_node(node->addr); - } - return; - } - - free_slot->addr = node->addr; - free_slot->clear = !store; - - schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); -} - -static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx, - struct key_update **free_slot) -{ - struct key_update *match; - int i; - - match = NULL; - *free_slot = NULL; - - for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) { - struct key_update *update = &cdb_key_updates[i]; - - if (!update->valid) { - *free_slot = update; - continue; - } - - if (update->app_key != app_key) { - continue; - } - - if (update->key_idx == key_idx) { - match = update; - } - } - - return match; -} - -static void update_cdb_subnet_settings(const struct bt_mesh_cdb_subnet *sub, - bool store) -{ - struct key_update *update, *free_slot; - uint8_t clear = store ? 0U : 1U; - - BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); - - update = cdb_key_update_find(false, sub->net_idx, &free_slot); - if (update) { - update->clear = clear; - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); - return; - } - - if (!free_slot) { - if (store) { - store_cdb_subnet(sub); - } else { - clear_cdb_subnet(sub->net_idx); - } - return; - } - - free_slot->valid = 1U; - free_slot->key_idx = sub->net_idx; - free_slot->app_key = 0U; - free_slot->clear = clear; - - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); -} - -static void update_cdb_app_key_settings(const struct bt_mesh_cdb_app_key *key, - bool store) -{ - struct key_update *update, *free_slot; - uint8_t clear = store ? 0U : 1U; - - BT_DBG("AppKeyIndex 0x%03x", key->app_idx); - - update = cdb_key_update_find(true, key->app_idx, &free_slot); - if (update) { - update->clear = clear; - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); - return; - } - - if (!free_slot) { - if (store) { - store_cdb_app_key(key); - } else { - clear_cdb_app_key(key->app_idx); - } - - return; - } - - free_slot->valid = 1U; - free_slot->key_idx = key->app_idx; - free_slot->app_key = 1U; - free_slot->clear = clear; - - schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); -} - -int bt_mesh_cdb_create(const uint8_t key[16]) -{ - struct bt_mesh_cdb_subnet *sub; - - 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)) { - update_cdb_net_settings(); - update_cdb_subnet_settings(sub, true); - } - - 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)) { - update_cdb_net_settings(); - } -} - -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)) { - update_cdb_net_settings(); - } -} - -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) { - update_cdb_subnet_settings(sub, false); - } - - 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 (IS_ENABLED(CONFIG_BT_SETTINGS)) { - update_cdb_subnet_settings(sub, true); - } -} - -uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub) -{ - uint8_t flags = 0x00; - - if (sub && SUBNET_KEY_TX_IDX(sub)) { - 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) { - update_cdb_node_settings(node, false); - } - - 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 (IS_ENABLED(CONFIG_BT_SETTINGS)) { - update_cdb_node_settings(node, true); - } -} - -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) { - update_cdb_app_key_settings(key, false); - } - - key->net_idx = BT_MESH_KEY_UNUSED; - 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 (IS_ENABLED(CONFIG_BT_SETTINGS)) { - update_cdb_app_key_settings(key, true); - } -} - -static void clear_cdb_net(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - char path[30]; - int err; - - snprintk(path, sizeof(path), "bt_mesh/cdb/Net"); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear Net"); - } else { - BT_DBG("Cleared NetKeyIndex 0x%03x"); - } -#endif -} - -static void store_cdb_pending_net(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - struct net_val net; - int err; - char buf[BT_SETTINGS_SIZE(sizeof(struct net_val))]; - 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"); - } -#endif -} - -static void store_cdb_pending_nodes(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) { - struct node_update *update = &cdb_node_updates[i]; - - if (update->addr == BT_MESH_ADDR_UNASSIGNED) { - continue; - } - - BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear); - - if (update->clear) { - clear_cdb_node(update->addr); - } else { - struct bt_mesh_cdb_node *node; - - node = bt_mesh_cdb_node_get(update->addr); - if (node) { - store_cdb_node(node); - } else { - BT_WARN("Node 0x%04x not found", update->addr); - } - } - - update->addr = BT_MESH_ADDR_UNASSIGNED; - } -} - -static void store_cdb_pending_keys(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) { - struct key_update *update = &cdb_key_updates[i]; - - if (!update->valid) { - continue; - } - - if (update->clear) { - if (update->app_key) { - clear_cdb_app_key(update->key_idx); - } else { - clear_cdb_subnet(update->key_idx); - } - } else { - if (update->app_key) { - struct bt_mesh_cdb_app_key *key; - - key = bt_mesh_cdb_app_key_get(update->key_idx); - if (key) { - store_cdb_app_key(key); - } else { - BT_WARN("AppKeyIndex 0x%03x not found", - update->key_idx); - } - } else { - struct bt_mesh_cdb_subnet *sub; - - sub = bt_mesh_cdb_subnet_get(update->key_idx); - if (sub) { - store_cdb_subnet(sub); - } else { - BT_WARN("NetKeyIndex 0x%03x not found", - update->key_idx); - } - } - } - - update->valid = 0U; - } -} - -void bt_mesh_cdb_pending_store(void) -{ - if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_SUBNET_PENDING)) { - if (atomic_test_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_VALID)) { - store_cdb_pending_net(); - } else { - clear_cdb_net(); - } - } - - if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_NODES_PENDING)) { - store_cdb_pending_nodes(); - } - - if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, - BT_MESH_CDB_KEYS_PENDING)) { - store_cdb_pending_keys(); - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static struct conf_handler bt_mesh_cdb_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = cdb_set, - .ch_commit = NULL, - .ch_export = NULL, -}; -#endif - -void bt_mesh_cdb_init(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - int rc; - - rc = conf_register(&bt_mesh_cdb_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_net conf"); -#endif -} -#endif - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/cdb_priv.h b/src/nimble/nimble/host/mesh/src/cdb_priv.h deleted file mode 100644 index ff865a56f..000000000 --- a/src/nimble/nimble/host/mesh/src/cdb_priv.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* ommitted `bt_mesh_cdb_node_store` declaration - every header - * includes mesh/mesh.h, which already has it - * void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node); - */ -void bt_mesh_cdb_pending_store(void); -void bt_mesh_cdb_init(void); diff --git a/src/nimble/nimble/host/mesh/src/cfg.c b/src/nimble/nimble/host/mesh/src/cfg.c deleted file mode 100644 index 231fcf83a..000000000 --- a/src/nimble/nimble/host/mesh/src/cfg.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#include "nimble/nimble/host/mesh/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 "nimble/nimble/host/mesh/include/mesh/glue.h" - -#define MESH_LOG_MODULE BLE_MESH_LOG -#include "nimble/porting/nimble/include/log/log.h" - -/* Miscellaneous configuration server model states */ -struct cfg_val { - uint8_t net_transmit; - uint8_t relay; - uint8_t relay_retransmit; - uint8_t beacon; - uint8_t gatt_proxy; - uint8_t frnd; - uint8_t default_ttl; -}; - -void bt_mesh_beacon_set(bool beacon) -{ - if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) { - 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_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); - } -} - -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_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); - } - - 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_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); - } - - 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_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); - } - - 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_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); - } -} - -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_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); - } - - 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; - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static int cfg_set(int argc, char **argv, char *val) -{ - struct cfg_val cfg; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - if (!val) { - BT_DBG("Cleared configuration state"); - return 0; - } - - len = sizeof(cfg); - err = settings_bytes_from_str(val, &cfg, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(cfg)) { - BT_ERR("Unexpected value length (%d != %zu)", len, - sizeof(cfg)); - return -EINVAL; - } - - bt_mesh_net_transmit_set(cfg.net_transmit); - bt_mesh_relay_set(cfg.relay, cfg.relay_retransmit); - bt_mesh_beacon_set(cfg.beacon); - bt_mesh_gatt_proxy_set(cfg.gatt_proxy); - bt_mesh_friend_set(cfg.frnd); - bt_mesh_default_ttl_set(cfg.default_ttl); - - BT_DBG("Restored configuration state"); - - return 0; -} - -static void clear_cfg(void) -{ - int err; - - err = settings_save_one("bt_mesh/Cfg", NULL); - if (err) { - BT_ERR("Failed to clear configuration"); - } else { - BT_DBG("Cleared configuration"); - } -} - -static void store_pending_cfg(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct cfg_val))]; - struct cfg_val val; - char *str; - int err; - - val.net_transmit = bt_mesh_net_transmit_get(); - val.relay = bt_mesh_relay_get(); - val.relay_retransmit = bt_mesh_relay_retransmit_get(); - val.beacon = bt_mesh_beacon_enabled(); - val.gatt_proxy = bt_mesh_gatt_proxy_get(); - val.frnd = bt_mesh_friend_get(); - val.default_ttl = bt_mesh_default_ttl_get(); - - str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode configuration as value"); - return; - } - - BT_DBG("Saving configuration as value %s", str); - err = settings_save_one("bt_mesh/Cfg", str); - if (err) { - BT_ERR("Failed to store configuration"); - } else { - BT_DBG("Stored configuration"); - } -} - -void bt_mesh_cfg_pending_store(void) -{ - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - store_pending_cfg(); - } else { - clear_cfg(); - } -} - -static struct conf_handler bt_mesh_cfg_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = cfg_set, - .ch_commit = NULL, - .ch_export = NULL, -}; -#endif - -void bt_mesh_cfg_default_set(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - int rc; - - rc = conf_register(&bt_mesh_cfg_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_settings conf"); -#endif - - bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL; - bt_mesh.net_xmit = - 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) */ diff --git a/src/nimble/nimble/host/mesh/src/cfg.h b/src/nimble/nimble/host/mesh/src/cfg.h deleted file mode 100644 index 4901655f5..000000000 --- a/src/nimble/nimble/host/mesh/src/cfg.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -void bt_mesh_cfg_default_set(void); -void bt_mesh_cfg_pending_store(void); - -bool bt_mesh_fixed_group_match(uint16_t addr); diff --git a/src/nimble/nimble/host/mesh/src/cfg_cli.c b/src/nimble/nimble/host/mesh/src/cfg_cli.c deleted file mode 100644 index 0c83a19a2..000000000 --- a/src/nimble/nimble/host/mesh/src/cfg_cli.c +++ /dev/null @@ -1,2714 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG -#if MYNEWT_VAL(BLE_MESH_CFG_CLI) - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -#include -#include -#include - -#include "net.h" -#include "foundation.h" - -#define CID_NVAL 0xffff - -/* 2 byte dummy opcode for getting compile time buffer sizes. */ -#define DUMMY_2_BYTE_OP BT_MESH_MODEL_OP_2(0xff, 0xff) - -struct comp_data { - uint8_t *page; - struct os_mbuf *comp; -}; - -static int32_t msg_timeout = K_SECONDS(5); - -static struct bt_mesh_cfg_cli *cli; - -static int comp_data_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct comp_data *param; - size_t to_copy; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_DEV_COMP_DATA_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - if (param->page) { - *(param->page) = net_buf_simple_pull_u8(buf); - } - to_copy = MIN(net_buf_simple_tailroom(param->comp), buf->om_len); - net_buf_simple_add_mem(param->comp, buf->om_data, to_copy); - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -static int state_status_u8(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf, - uint32_t expect_status) -{ - uint8_t *status; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, expect_status, ctx->addr, - (void **)&status)) { - return -ENOENT; - } - - *status = net_buf_simple_pull_u8(buf); - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -static int beacon_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - return state_status_u8(model, ctx, buf, OP_BEACON_STATUS); -} - -static int ttl_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - return state_status_u8(model, ctx, buf, OP_DEFAULT_TTL_STATUS); -} - -static int friend_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - return state_status_u8(model, ctx, buf, OP_FRIEND_STATUS); -} - -static int gatt_proxy_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - return state_status_u8(model, ctx, buf, OP_GATT_PROXY_STATUS); -} - -static int transmit_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - return state_status_u8(model, ctx, buf, OP_NET_TRANSMIT_STATUS); -} - - struct krp_param { - uint8_t *status; - uint16_t net_idx; - uint8_t *phase; -}; - -static int krp_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct krp_param *param; - uint16_t net_idx; - uint8_t status, phase; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_KRP_STATUS, ctx->addr, (void **)¶m)) { - return -ENOENT; - } - - status = net_buf_simple_pull_u8(buf); - net_idx = net_buf_simple_pull_le16(buf) & 0xfff; - phase = net_buf_simple_pull_u8(buf); - - if (param->net_idx != net_idx) { - return -ENOENT; - } - - if (param->status) { - *param->status = status; - } - - if (param->phase) { - *param->phase = phase; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct relay_param { - uint8_t *status; - uint8_t *transmit; -}; - -static int relay_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - struct relay_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_RELAY_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - *param->status = net_buf_simple_pull_u8(buf); - *param->transmit = net_buf_simple_pull_u8(buf); - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -static int net_transmit_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - return state_status_u8(model, ctx, buf, OP_NET_TRANSMIT_STATUS); -} - -struct net_key_param { - uint8_t *status; - uint16_t net_idx; -}; - -static int net_key_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct net_key_param *param; - uint16_t net_idx; - uint8_t status; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_KEY_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - status = net_buf_simple_pull_u8(buf); - net_idx = net_buf_simple_pull_le16(buf) & 0xfff; - - if (param->net_idx != net_idx) { - BT_WARN("Net Key Status key index does not match"); - return -ENOENT; - } - - if (param->status) { - *param->status = status; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct net_key_list_param { - uint16_t *keys; - size_t *key_cnt; -}; - -static int net_key_list(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct net_key_list_param *param; - int i; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NET_KEY_LIST, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - 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; - } - - if (buf->om_len > 0) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - *param->key_cnt = i; - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -static int node_reset_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - bool *param = NULL; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x", ctx->net_idx, - ctx->app_idx, ctx->addr); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NODE_RESET_STATUS, - ctx->addr, (void **)¶m)) { - return -ENOENT; - } - - if (param) { - *param = true; - } - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct app_key_param { - uint8_t *status; - uint16_t net_idx; - uint16_t app_idx; -}; - -static int app_key_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - struct app_key_param *param; - uint16_t net_idx, app_idx; - uint8_t status; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_APP_KEY_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - status = net_buf_simple_pull_u8(buf); - key_idx_unpack(buf, &net_idx, &app_idx); - - if (param->net_idx != net_idx || param->app_idx != app_idx) { - BT_WARN("App Key Status key indices did not match"); - return -ENOENT; - } - - if (param->status) { - *param->status = status; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct app_key_list_param { - uint16_t net_idx; - uint8_t *status; - uint16_t *keys; - size_t *key_cnt; -}; - -static int app_key_list(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct app_key_list_param *param; - uint16_t net_idx; - 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 (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_APP_KEY_LIST, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - status = net_buf_simple_pull_u8(buf); - net_idx = net_buf_simple_pull_le16(buf) & 0xfff; - - if (param->net_idx != net_idx) { - BT_WARN("App Key List Net Key index did not match"); - return -ENOENT; - } - - 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; - } - - if (buf->om_len > 0U) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EINVAL; - } - - *param->key_cnt = i; - if (param->status) { - *param->status = status; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct mod_app_param { - uint8_t *status; - uint16_t elem_addr; - uint16_t mod_app_idx; - uint16_t mod_id; - uint16_t cid; -}; - -static int mod_app_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - uint16_t elem_addr, mod_app_idx, mod_id, cid; - struct mod_app_param *param; - uint8_t status; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if ((buf->om_len != 7U) && (buf->om_len != 9U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_APP_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - status = net_buf_simple_pull_u8(buf); - elem_addr = net_buf_simple_pull_le16(buf); - mod_app_idx = net_buf_simple_pull_le16(buf); - - if (buf->om_len >= 4) { - cid = net_buf_simple_pull_le16(buf); - } else { - cid = CID_NVAL; - } - - mod_id = net_buf_simple_pull_le16(buf); - - if (param->elem_addr != elem_addr || - param->mod_app_idx != mod_app_idx || param->mod_id != mod_id || - param->cid != cid) { - BT_WARN("Model App Status parameters did not match"); - return -ENOENT; - } - - if (param->status) { - *param->status = status; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -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 int mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf, bool vnd, - struct mod_member_list_param *param) -{ - uint16_t elem_addr, mod_id, cid; - uint8_t status; - int i; - - if ((vnd && buf->om_len < 7U) || (buf->om_len < 5U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - status = net_buf_simple_pull_u8(buf); - elem_addr = net_buf_simple_pull_le16(buf); - if (vnd) { - cid = net_buf_simple_pull_le16(buf); - } - - mod_id = net_buf_simple_pull_le16(buf); - - 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 -ENOENT; - } - - if (buf->om_len % 2U) { - BT_ERR("Model Member List invalid length"); - return -EMSGSIZE; - } - - for (i = 0; i < *param->member_cnt && buf->om_len; i++) { - param->members[i] = net_buf_simple_pull_le16(buf); - } - - *param->member_cnt = i; - if (param->status) { - *param->status = status; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -static int mod_app_list(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct mod_member_list_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_SIG_MOD_APP_LIST, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - return mod_member_list_handle(ctx, buf, false, param); -} - -static int mod_app_list_vnd(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct mod_member_list_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_VND_MOD_APP_LIST, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - return mod_member_list_handle(ctx, buf, true, param); -} - -struct mod_pub_param { - uint16_t mod_id; - uint16_t cid; - uint16_t elem_addr; - uint8_t *status; - struct bt_mesh_cfg_mod_pub *pub; -}; - -static int mod_pub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - uint16_t mod_id, cid, elem_addr; - struct mod_pub_param *param; - uint8_t status; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if ((buf->om_len != 12U) && (buf->om_len != 14U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EINVAL; - } - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_PUB_STATUS, ctx->addr, - (void **)¶m)) { - BT_WARN("Unexpected Model Pub Status message"); - return -ENOENT; - } - - if (param->cid != CID_NVAL) { - if (buf->om_len < 14) { - BT_WARN("Unexpected Mod Pub Status with SIG Model"); - return -ENOENT; - } - - cid = sys_get_le16(&buf->om_data[10]); - mod_id = sys_get_le16(&buf->om_data[12]); - } else { - if (buf->om_len > 12) { - BT_WARN("Unexpected Mod Pub Status with Vendor Model"); - return -ENOENT; - } - - cid = CID_NVAL; - mod_id = sys_get_le16(&buf->om_data[10]); - } - - if (mod_id != param->mod_id || cid != param->cid) { - BT_WARN("Mod Pub Model ID or Company ID mismatch"); - return -ENOENT; - } - - status = net_buf_simple_pull_u8(buf); - - elem_addr = net_buf_simple_pull_le16(buf); - if (elem_addr != param->elem_addr) { - BT_WARN("Model Pub Status for unexpected element (0x%04x)", - elem_addr); - return -ENOENT; - } - - if (param->status) { - *param->status = status; - } - - if (param->pub) { - param->pub->addr = net_buf_simple_pull_le16(buf); - param->pub->app_idx = net_buf_simple_pull_le16(buf); - param->pub->cred_flag = (param->pub->app_idx & BIT(12)); - param->pub->app_idx &= BIT_MASK(12); - param->pub->ttl = net_buf_simple_pull_u8(buf); - param->pub->period = net_buf_simple_pull_u8(buf); - param->pub->transmit = net_buf_simple_pull_u8(buf); - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct mod_sub_param { - uint8_t *status; - uint16_t elem_addr; - uint16_t *sub_addr; - uint16_t *expect_sub; - uint16_t mod_id; - uint16_t cid; -}; - -static int mod_sub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - uint16_t elem_addr, sub_addr, mod_id, cid; - struct mod_sub_param *param; - uint8_t status; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if ((buf->om_len != 7U) && (buf->om_len != 9U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EINVAL; - } - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - status = net_buf_simple_pull_u8(buf); - elem_addr = net_buf_simple_pull_le16(buf); - sub_addr = net_buf_simple_pull_le16(buf); - - if (buf->om_len >= 4) { - cid = net_buf_simple_pull_le16(buf); - } else { - cid = CID_NVAL; - } - - mod_id = net_buf_simple_pull_le16(buf); - - if (param->elem_addr != elem_addr || param->mod_id != mod_id || - (param->expect_sub && *param->expect_sub != sub_addr) || - param->cid != cid) { - BT_WARN("Model Subscription Status parameters did not match"); - return -ENOENT; - } - - if (param->sub_addr) { - *param->sub_addr = sub_addr; - } - - if (param->status) { - *param->status = status; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -static int mod_sub_list(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct mod_member_list_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_LIST, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - return mod_member_list_handle(ctx, buf, false, param); -} - -static int mod_sub_list_vnd(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct mod_member_list_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_MOD_SUB_LIST_VND, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - return mod_member_list_handle(ctx, buf, true,param); -} - -struct hb_sub_param { - uint8_t *status; - struct bt_mesh_cfg_hb_sub *sub; -}; - -static int hb_sub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf*buf) -{ - struct hb_sub_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_HEARTBEAT_SUB_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - *param->status = net_buf_simple_pull_u8(buf); - - param->sub->src = net_buf_simple_pull_le16(buf); - param->sub->dst = net_buf_simple_pull_le16(buf); - param->sub->period = net_buf_simple_pull_u8(buf); - param->sub->count = net_buf_simple_pull_u8(buf); - param->sub->min = net_buf_simple_pull_u8(buf); - param->sub->max = net_buf_simple_pull_u8(buf); - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct hb_pub_param { - uint8_t *status; - struct bt_mesh_cfg_hb_pub *pub; -}; - -static int hb_pub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct hb_pub_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_HEARTBEAT_PUB_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - *param->status = net_buf_simple_pull_u8(buf); - - if (param->pub) { - param->pub->dst = net_buf_simple_pull_le16(buf); - param->pub->count = net_buf_simple_pull_u8(buf); - param->pub->period = net_buf_simple_pull_u8(buf); - param->pub->ttl = net_buf_simple_pull_u8(buf); - param->pub->feat = net_buf_simple_pull_u8(buf); - param->pub->net_idx = net_buf_simple_pull_u8(buf); - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct node_idt_param { - uint8_t *status; - uint16_t net_idx; - uint8_t *identity; -}; - -static int node_identity_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct node_idt_param *param; - uint16_t net_idx, identity; - uint8_t status; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_NODE_IDENTITY_STATUS, - ctx->addr, (void **)¶m)) { - return -ENOENT; - } - - status = net_buf_simple_pull_u8(buf); - net_idx = net_buf_simple_pull_le16(buf) & 0xfff; - identity = net_buf_simple_pull_u8(buf); - - if (param && param->status) { - *param->status = status; - } - - if (param->net_idx != net_idx) { - return -ENOENT; - } - - if (param && param->identity) { - *param->identity = identity; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -struct lpn_timeout_param { - uint16_t unicast_addr; - int32_t *polltimeout; -}; - -static int lpn_timeout_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct lpn_timeout_param *param; - uint16_t unicast_addr; - int32_t polltimeout; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, OP_LPN_TIMEOUT_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - unicast_addr = net_buf_simple_pull_le16(buf); - polltimeout = net_buf_simple_pull_le24(buf); - - if (param->unicast_addr != unicast_addr) { - return -ENOENT; - } - - if (param->polltimeout) { - *param->polltimeout = polltimeout; - } - - bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); - - return 0; -} - -const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { - { OP_DEV_COMP_DATA_STATUS, BT_MESH_LEN_MIN(15), comp_data_status }, - { OP_BEACON_STATUS, BT_MESH_LEN_EXACT(1), beacon_status }, - { OP_DEFAULT_TTL_STATUS, BT_MESH_LEN_EXACT(1), ttl_status }, - { OP_FRIEND_STATUS, BT_MESH_LEN_EXACT(1), friend_status }, - { OP_GATT_PROXY_STATUS, BT_MESH_LEN_EXACT(1), gatt_proxy_status }, - { OP_RELAY_STATUS, BT_MESH_LEN_EXACT(2), relay_status }, - { OP_NET_TRANSMIT_STATUS, BT_MESH_LEN_EXACT(1), net_transmit_status }, - { OP_NET_KEY_STATUS, BT_MESH_LEN_EXACT(3), net_key_status }, - { OP_NET_KEY_LIST, BT_MESH_LEN_MIN(0), net_key_list }, - { OP_APP_KEY_STATUS, BT_MESH_LEN_EXACT(4), app_key_status }, - { OP_APP_KEY_LIST, BT_MESH_LEN_MIN(3), app_key_list }, - { OP_MOD_APP_STATUS, BT_MESH_LEN_MIN(7), mod_app_status }, - { OP_SIG_MOD_APP_LIST, BT_MESH_LEN_MIN(5), mod_app_list }, - { OP_VND_MOD_APP_LIST, BT_MESH_LEN_MIN(7), mod_app_list_vnd }, - { OP_MOD_PUB_STATUS, BT_MESH_LEN_MIN(12), mod_pub_status }, - { OP_MOD_SUB_STATUS, BT_MESH_LEN_MIN(7), mod_sub_status }, - { OP_MOD_SUB_LIST, BT_MESH_LEN_MIN(5), mod_sub_list }, - { OP_MOD_SUB_LIST_VND, BT_MESH_LEN_MIN(7), mod_sub_list_vnd }, - { OP_HEARTBEAT_SUB_STATUS, BT_MESH_LEN_EXACT(9), hb_sub_status }, - { OP_HEARTBEAT_PUB_STATUS, BT_MESH_LEN_EXACT(10), hb_pub_status }, - { OP_NODE_RESET_STATUS, BT_MESH_LEN_EXACT(0), node_reset_status }, - { OP_NODE_IDENTITY_STATUS, BT_MESH_LEN_EXACT(4), node_identity_status}, - { OP_LPN_TIMEOUT_STATUS, BT_MESH_LEN_EXACT(5), lpn_timeout_status }, - { OP_NET_TRANSMIT_STATUS, BT_MESH_LEN_EXACT(1), transmit_status}, - { OP_KRP_STATUS, BT_MESH_LEN_EXACT(4), krp_status}, - BT_MESH_MODEL_OP_END, -}; - -static int cfg_cli_init(struct bt_mesh_model *model) -{ - BT_DBG(""); - - if (!bt_mesh_model_in_primary(model)) { - BT_ERR("Configuration Client only allowed in primary element"); - return -EINVAL; - } - - if (!model->user_data) { - BT_ERR("No Configuration Client context provided"); - return -EINVAL; - } - - cli = model->user_data; - cli->model = model; - - /* - * Configuration Model security is device-key based and both the local - * and remote keys are allowed to access this model. - */ - model->keys[0] = BT_MESH_KEY_DEV_ANY; - - bt_mesh_msg_ack_ctx_init(&cli->ack_ctx); - - return 0; -} - -const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = { - .init = cfg_cli_init, -}; - -static int cli_prepare(void *param, uint32_t op, uint16_t addr) -{ - if (!cli) { - BT_ERR("No available Configuration Client context!"); - return -EINVAL; - } - - return bt_mesh_msg_ack_ctx_prepare(&cli->ack_ctx, op, addr, param); -} - -int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, - uint8_t *rsp, struct os_mbuf *comp) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEV_COMP_DATA_GET, 1); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct comp_data param = { - .page = rsp, - .comp = comp, - }; - int err; - - err = cli_prepare(¶m, OP_DEV_COMP_DATA_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_DEV_COMP_DATA_GET); - net_buf_simple_add_u8(msg, page); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - int err; - - err = cli_prepare(val, rsp, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, op); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - int err; - - err = cli_prepare(val, rsp, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, op); - net_buf_simple_add_u8(msg, new_val); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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_krp_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, - uint8_t *status, uint8_t *phase) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_GET, 2); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct krp_param param = { - .status = status, - .phase = phase, - }; - int err; - - err = cli_prepare(¶m, OP_KRP_STATUS, addr); - if (err) { - return err; - } - - bt_mesh_model_msg_init(msg, OP_KRP_GET); - net_buf_simple_add_le16(msg, key_net_idx); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int bt_mesh_cfg_krp_set(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, - uint8_t transition, uint8_t *status, uint8_t *phase) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_SET, 3); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct krp_param param = { - .status = status, - .phase = phase, - }; - int err; - - err = cli_prepare(¶m, OP_KRP_STATUS, addr); - if (err) { - return err; - } - - bt_mesh_model_msg_init(msg, OP_KRP_SET); - net_buf_simple_add_le16(msg, key_net_idx); - net_buf_simple_add_u8(msg, transition); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status) -{ - return set_state_u8(net_idx, addr, OP_BEACON_SET, OP_BEACON_STATUS, - val, status); -} - -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(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(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(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(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(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_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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct relay_param param = { - .status = status, - .transmit = transmit, - }; - int err; - - err = cli_prepare(¶m, OP_RELAY_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_RELAY_GET); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct relay_param param = { - .status = status, - .transmit = transmit, - }; - int err; - - err = cli_prepare(¶m, OP_RELAY_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_RELAY_SET); - net_buf_simple_add_u8(msg, new_relay); - net_buf_simple_add_u8(msg, new_transmit); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct net_key_param param = { - .status = status, - .net_idx = key_net_idx, - }; - int err; - - err = cli_prepare(¶m, OP_NET_KEY_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_NET_KEY_ADD); - net_buf_simple_add_le16(msg, key_net_idx); - net_buf_simple_add_mem(msg, net_key, 16); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -int bt_mesh_cfg_net_key_update(uint16_t net_idx, uint16_t addr, - uint16_t key_net_idx, const uint8_t net_key[16], - uint8_t *status) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_UPDATE, 18); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct net_key_param param = { - .status = status, - .net_idx = key_net_idx, - }; - int err; - - err = cli_prepare(¶m, OP_NET_KEY_STATUS, addr); - if (err) { - return err; - } - - bt_mesh_model_msg_init(msg, OP_NET_KEY_UPDATE); - net_buf_simple_add_le16(msg, key_net_idx); - net_buf_simple_add_mem(msg, net_key, 16); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return 0; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys, - size_t *key_cnt) -{ - 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, addr); - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - os_mbuf_free_chain(msg); - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr, - 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, addr); - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct app_key_param param = { - .status = status, - .net_idx = key_net_idx, - .app_idx = key_app_idx, - }; - int err; - - err = cli_prepare(¶m, OP_APP_KEY_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_APP_KEY_ADD); - key_idx_pack(msg, key_net_idx, key_app_idx); - net_buf_simple_add_mem(msg, app_key, 16); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -int bt_mesh_cfg_app_key_update(uint16_t net_idx, uint16_t addr, - uint16_t key_net_idx, uint16_t key_app_idx, - const uint8_t app_key[16], uint8_t *status) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_UPDATE, 19); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct app_key_param param = { - .status = status, - .net_idx = key_net_idx, - .app_idx = key_app_idx, - }; - int err; - - err = cli_prepare(¶m, OP_APP_KEY_STATUS, addr); - if (err) { - return err; - } - - bt_mesh_model_msg_init(msg, OP_APP_KEY_UPDATE); - key_idx_pack(msg, key_net_idx, key_app_idx); - net_buf_simple_add_mem(msg, app_key, 16); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return 0; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET, 0); - 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, addr); - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -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, addr); - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - os_mbuf_free_chain(msg); - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr, - 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, addr); - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - os_mbuf_free_chain(msg); - return 0; - } - - os_mbuf_free_chain(msg); - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -static int mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, - 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 = { - .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, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_MOD_APP_BIND); - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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(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_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id, cid, - 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, addr); - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - err = 0; - goto done; - } - -done: - os_mbuf_free_chain(msg); - if (err) { - return err; - } else { - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); - } -} - -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, addr); - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -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, - 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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct mod_sub_param param = { - .status = status, - .elem_addr = elem_addr, - .expect_sub = &sub_addr, - .mod_id = mod_id, - .cid = cid, - }; - int err; - - err = cli_prepare(¶m, OP_MOD_SUB_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, op); - net_buf_simple_add_le16(msg, elem_addr); - - if (sub_addr != BT_MESH_ADDR_UNASSIGNED) { - net_buf_simple_add_le16(msg, sub_addr); - } - - if (cid != CID_NVAL) { - net_buf_simple_add_le16(msg, cid); - } - - net_buf_simple_add_le16(msg, mod_id); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - err = 0; - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, - uint16_t sub_addr, uint16_t mod_id, uint8_t *status) -{ - if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { - return -EINVAL; - } - - return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr, - mod_id, CID_NVAL, status); -} - -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 (!BT_MESH_ADDR_IS_GROUP(sub_addr) || cid == CID_NVAL) { - return -EINVAL; - } - - return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr, - mod_id, cid, 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) -{ - if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { - return -EINVAL; - } - - return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr, - mod_id, CID_NVAL, status); -} - -int bt_mesh_cfg_mod_sub_del_all(uint16_t net_idx, uint16_t addr, - uint16_t elem_addr, uint16_t mod_id, - uint8_t *status) -{ - return mod_sub(OP_MOD_SUB_DEL_ALL, net_idx, addr, elem_addr, - BT_MESH_ADDR_UNASSIGNED, mod_id, CID_NVAL, status); -} - -int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, - uint16_t sub_addr, uint16_t mod_id, uint16_t cid, - uint8_t *status) -{ - if (!BT_MESH_ADDR_IS_GROUP(sub_addr) || cid == CID_NVAL) { - return -EINVAL; - } - - return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr, - mod_id, cid, status); -} - -int bt_mesh_cfg_mod_sub_del_all_vnd(uint16_t net_idx, uint16_t addr, - uint16_t elem_addr, uint16_t mod_id, - uint16_t cid, uint8_t *status) -{ - if (cid == CID_NVAL) { - return -EINVAL; - } - - return mod_sub(OP_MOD_SUB_DEL_ALL, net_idx, addr, elem_addr, - BT_MESH_ADDR_UNASSIGNED, mod_id, cid, status); -} - -int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, - uint16_t sub_addr, uint16_t mod_id, uint8_t *status) -{ - if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { - return -EINVAL; - } - - return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr, - sub_addr, mod_id, CID_NVAL, status); -} - -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 (!BT_MESH_ADDR_IS_GROUP(sub_addr) || cid == CID_NVAL) { - return -EINVAL; - } - - return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr, - sub_addr, mod_id, cid, 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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct mod_sub_param param = { - .status = status, - .elem_addr = elem_addr, - .sub_addr = virt_addr, - .mod_id = mod_id, - .cid = cid, - }; - int err; - - err = cli_prepare(¶m, OP_MOD_SUB_STATUS, addr); - if (err) { - goto done; - } - - BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x label %s", - net_idx, addr, elem_addr, bt_hex(label, 16)); - BT_DBG("mod_id 0x%04x cid 0x%04x", mod_id, cid); - - bt_mesh_model_msg_init(msg, op); - net_buf_simple_add_le16(msg, elem_addr); - net_buf_simple_add_mem(msg, label, 16); - - if (cid != CID_NVAL) { - net_buf_simple_add_le16(msg, cid); - } - - net_buf_simple_add_le16(msg, mod_id); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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(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; - } - - return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label, - mod_id, cid, virt_addr, 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(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; - } - - return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label, - mod_id, cid, virt_addr, 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(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; - } - - return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr, - label, mod_id, cid, virt_addr, 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, - 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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct mod_pub_param param = { - .mod_id = mod_id, - .cid = cid, - .elem_addr = elem_addr, - .status = status, - .pub = pub, - }; - int err; - - err = cli_prepare(¶m, OP_MOD_PUB_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_MOD_PUB_GET); - - 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); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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(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; - } - - return mod_pub_get(net_idx, addr, elem_addr, mod_id, cid, pub, 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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct mod_pub_param param = { - .mod_id = mod_id, - .cid = cid, - .elem_addr = elem_addr, - .status = status, - .pub = pub, - }; - int err; - - err = cli_prepare(¶m, OP_MOD_PUB_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_MOD_PUB_SET); - - 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_u8(msg, pub->ttl); - net_buf_simple_add_u8(msg, pub->period); - net_buf_simple_add_u8(msg, pub->transmit); - - if (cid != CID_NVAL) { - net_buf_simple_add_le16(msg, cid); - } - - net_buf_simple_add_le16(msg, mod_id); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -static int mod_pub_va_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, - uint16_t mod_id, uint16_t cid, - struct bt_mesh_cfg_mod_pub *pub, uint8_t *status) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_VA_SET, 27); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct mod_pub_param param = { - .mod_id = mod_id, - .cid = cid, - .elem_addr = elem_addr, - .status = status, - .pub = pub, - }; - int err; - - err = cli_prepare(¶m, OP_MOD_PUB_STATUS, addr); - if (err) { - return err; - } - BT_DBG("app_idx 0x%04x", pub->app_idx); - bt_mesh_model_msg_init(msg, OP_MOD_PUB_VA_SET); - - net_buf_simple_add_le16(msg, elem_addr); - net_buf_simple_add_mem(msg, pub->uuid, 16); - net_buf_simple_add_le16(msg, (pub->app_idx | (pub->cred_flag << 12))); - net_buf_simple_add_u8(msg, pub->ttl); - net_buf_simple_add_u8(msg, pub->period); - net_buf_simple_add_u8(msg, pub->transmit); - - if (cid != CID_NVAL) { - net_buf_simple_add_le16(msg, cid); - } - - net_buf_simple_add_le16(msg, mod_id); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return 0; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - - -int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, - uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub, - uint8_t *status) -{ - if (pub->uuid) { - return mod_pub_va_set(net_idx, addr, elem_addr, mod_id, CID_NVAL, pub, status); - } else { - return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL, pub, status); - } -} - -int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr, - uint16_t mod_id, uint16_t cid, struct bt_mesh_cfg_mod_pub *pub, - uint8_t *status) -{ - if (cid == CID_NVAL) { - return -EINVAL; - } - - if (pub->uuid) { - return mod_pub_va_set(net_idx, addr, elem_addr, mod_id, cid, pub, status); - } else { - return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status); - } -} - -int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr, - 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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct hb_sub_param param = { - .status = status, - .sub = sub, - }; - int err; - - err = cli_prepare(¶m, OP_HEARTBEAT_SUB_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_HEARTBEAT_SUB_SET); - net_buf_simple_add_le16(msg, sub->src); - net_buf_simple_add_le16(msg, sub->dst); - net_buf_simple_add_u8(msg, sub->period); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct hb_sub_param param = { - .status = status, - .sub = sub, - }; - int err; - - err = cli_prepare(¶m, OP_HEARTBEAT_SUB_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_HEARTBEAT_SUB_GET); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct hb_pub_param param = { - .status = status, - }; - int err; - - err = cli_prepare(¶m, OP_HEARTBEAT_PUB_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_HEARTBEAT_PUB_SET); - net_buf_simple_add_le16(msg, pub->dst); - net_buf_simple_add_u8(msg, pub->count); - net_buf_simple_add_u8(msg, 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); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct hb_pub_param param = { - .status = status, - .pub = pub, - }; - int err; - - err = cli_prepare(¶m, OP_HEARTBEAT_PUB_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_HEARTBEAT_PUB_GET); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -int bt_mesh_cfg_node_identity_set(uint16_t net_idx, uint16_t addr, - uint16_t key_net_idx, uint8_t new_identity, - uint8_t *status, uint8_t *identity) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_SET, 4); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct node_idt_param param = { - .status = status, - .net_idx = key_net_idx, - .identity = identity, - }; - int err; - - err = cli_prepare(¶m, OP_NODE_IDENTITY_STATUS, addr); - if (err) { - return err; - } - - bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_SET); - net_buf_simple_add_le16(msg, key_net_idx); - net_buf_simple_add_u8(msg, new_identity); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return 0; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int bt_mesh_cfg_node_identity_get(uint16_t net_idx, uint16_t addr, - uint16_t key_net_idx, uint8_t *status, - uint8_t *identity) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_GET, 2); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct node_idt_param param = { - .status = status, - .net_idx = key_net_idx, - .identity = identity, - }; - int err; - - err = cli_prepare(¶m, OP_NODE_IDENTITY_STATUS, addr); - if (err) { - return err; - } - - bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_GET); - net_buf_simple_add_le16(msg, key_net_idx); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - if (!status) { - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return 0; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int bt_mesh_cfg_lpn_timeout_get(uint16_t net_idx, uint16_t addr, - uint16_t unicast_addr, int32_t *polltimeout) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_GET, 2); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, - .app_idx = BT_MESH_KEY_DEV_REMOTE, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct lpn_timeout_param param = { - .unicast_addr = unicast_addr, - .polltimeout = polltimeout, - }; - int err; - - err = cli_prepare(¶m, OP_LPN_TIMEOUT_STATUS, addr); - if (err) { - return err; - } - - bt_mesh_model_msg_init(msg, OP_LPN_TIMEOUT_GET); - net_buf_simple_add_le16(msg, unicast_addr); - - err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&cli->ack_ctx); - return err; - } - - return bt_mesh_msg_ack_ctx_wait(&cli->ack_ctx, K_MSEC(msg_timeout)); -} - -int32_t bt_mesh_cfg_cli_timeout_get(void) -{ - return msg_timeout; -} - -void bt_mesh_cfg_cli_timeout_set(int32_t timeout) -{ - msg_timeout = timeout; -} - -int bt_mesh_comp_p0_get(struct bt_mesh_comp_p0 *page, - struct os_mbuf *buf) -{ - if (buf->om_len < 10) { - return -EINVAL; - } - - page->cid = net_buf_simple_pull_le16(buf); - page->pid = net_buf_simple_pull_le16(buf); - page->vid = net_buf_simple_pull_le16(buf); - page->crpl = net_buf_simple_pull_le16(buf); - page->feat = net_buf_simple_pull_le16(buf); - page->_buf = buf; - - return 0; -} - -struct bt_mesh_comp_p0_elem *bt_mesh_comp_p0_elem_pull(const struct bt_mesh_comp_p0 *page, - struct bt_mesh_comp_p0_elem *elem) -{ - size_t modlist_size; - - if (page->_buf->om_len < 4) { - return NULL; - } - - elem->loc = net_buf_simple_pull_le16(page->_buf); - elem->nsig = net_buf_simple_pull_u8(page->_buf); - elem->nvnd = net_buf_simple_pull_u8(page->_buf); - - modlist_size = elem->nsig * 2 + elem->nvnd * 4; - - if (page->_buf->om_len < modlist_size) { - return NULL; - } - - elem->_buf = net_buf_simple_pull_mem(page->_buf, modlist_size); - - return elem; -} - -uint16_t bt_mesh_comp_p0_elem_mod(struct bt_mesh_comp_p0_elem *elem, int idx) - { - CHECKIF(idx >= elem->nsig) { - return 0xffff; - } - - return sys_get_le16(&elem->_buf[idx * 2]); -} - -struct bt_mesh_mod_id_vnd bt_mesh_comp_p0_elem_mod_vnd(struct bt_mesh_comp_p0_elem *elem, int idx) - { - CHECKIF(idx >= elem->nvnd) { - return (struct bt_mesh_mod_id_vnd){ 0xffff, 0xffff }; - } - - size_t offset = elem->nsig * 2 + idx * 4; - struct bt_mesh_mod_id_vnd mod = { - .company = sys_get_le16(&elem->_buf[offset]), - .id = sys_get_le16(&elem->_buf[offset + 2]), - }; - - return mod; -} -#endif diff --git a/src/nimble/nimble/host/mesh/src/cfg_srv.c b/src/nimble/nimble/host/mesh/src/cfg_srv.c deleted file mode 100644 index 4df783280..000000000 --- a/src/nimble/nimble/host/mesh/src/cfg_srv.c +++ /dev/null @@ -1,2649 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG - -#include -#include -#include - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -#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" - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - -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) -{ - struct bt_mesh_model *mod; - int i; - - if (net_buf_simple_tailroom(buf) < - 4 + (elem->model_count * 2) + (elem->vnd_model_count * 4)) { - BT_ERR("Too large device composition"); - return -E2BIG; - } - - net_buf_simple_add_le16(buf, elem->loc); - - net_buf_simple_add_u8(buf, elem->model_count); - net_buf_simple_add_u8(buf, elem->vnd_model_count); - - for (i = 0; i < elem->model_count; i++) { - mod = &elem->models[i]; - net_buf_simple_add_le16(buf, mod->id); - } - - for (i = 0; i < elem->vnd_model_count; i++) { - mod = &elem->vnd_models[i]; - net_buf_simple_add_le16(buf, mod->vnd.company); - net_buf_simple_add_le16(buf, mod->vnd.id); - } - - return 0; -} - -static int comp_get_page_0(struct os_mbuf *buf) -{ - uint16_t feat = 0; - const struct bt_mesh_comp *comp; - int i; - - comp = bt_mesh_comp_get(); - - if ((MYNEWT_VAL(BLE_MESH_RELAY))) { - feat |= BT_MESH_FEAT_RELAY; - } - - if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) { - feat |= BT_MESH_FEAT_PROXY; - } - - if ((MYNEWT_VAL(BLE_MESH_FRIEND))) { - feat |= BT_MESH_FEAT_FRIEND; - } - - if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) { - feat |= BT_MESH_FEAT_LOW_POWER; - } - - net_buf_simple_add_le16(buf, comp->cid); - net_buf_simple_add_le16(buf, comp->pid); - net_buf_simple_add_le16(buf, comp->vid); - net_buf_simple_add_le16(buf, MYNEWT_VAL(BLE_MESH_CRPL)); - net_buf_simple_add_le16(buf, feat); - - for (i = 0; i < comp->elem_count; i++) { - int err; - - err = comp_add_elem(buf, &comp->elem[i], i == 0); - if (err) { - return err; - } - } - - return 0; -} - -static int dev_comp_data_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - uint8_t page; - int err; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - page = net_buf_simple_pull_u8(buf); - if (page != 0U) { - BT_DBG("Composition page %u not available", page); - page = 0U; - } - - bt_mesh_model_msg_init(sdu, OP_DEV_COMP_DATA_STATUS); - - net_buf_simple_add_u8(sdu, page); - err = comp_get_page_0(sdu); - if (err) { - BT_ERR("Unable to get composition page 0"); - goto done; - } - - if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) { - BT_ERR("Unable to send Device Composition Status response"); - } - -done: - os_mbuf_free_chain(sdu); - return err; -} - -static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, - struct os_mbuf *buf, bool *vnd) -{ - if (buf->om_len < 4) { - uint16_t id; - - id = net_buf_simple_pull_le16(buf); - - BT_DBG("ID 0x%04x addr 0x%04x", id, elem->addr); - - *vnd = false; - - return bt_mesh_model_find(elem, id); - } else { - uint16_t company, id; - - company = net_buf_simple_pull_le16(buf); - id = net_buf_simple_pull_le16(buf); - - BT_DBG("Company 0x%04x ID 0x%04x addr 0x%04x", company, id, - elem->addr); - - *vnd = true; - - return bt_mesh_model_find_vnd(elem, company, id); - } -} - -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; - } - - if (!(MYNEWT_VAL(BLE_MESH_LOW_POWER)) && cred_flag) { - return STATUS_FEAT_NOT_SUPP; - } - - if (!model->pub->update && period) { - return STATUS_NVAL_PUB_PARAM; - } - - if (pub_addr == BT_MESH_ADDR_UNASSIGNED) { - if (model->pub->addr == BT_MESH_ADDR_UNASSIGNED) { - return STATUS_SUCCESS; - } - - model->pub->addr = BT_MESH_ADDR_UNASSIGNED; - model->pub->key = 0; - model->pub->cred = 0; - model->pub->ttl = 0; - model->pub->period = 0; - model->pub->retransmit = 0; - model->pub->count = 0; - - if (model->pub->update) { - /* If this fails, the timer will check pub->addr and - * exit without transmitting. - */ - (void)k_work_cancel_delayable(&model->pub->timer); - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_model_pub_store(model); - } - - return STATUS_SUCCESS; - } - - if (!bt_mesh_app_key_exists(app_idx) || !bt_mesh_model_has_key(model, 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; - model->pub->ttl = ttl; - model->pub->period = period; - model->pub->retransmit = retransmit; - - if (model->pub->update) { - int32_t period_ms; - - period_ms = bt_mesh_model_pub_period_get(model); - BT_DBG("period %u ms", (unsigned) period_ms); - - if (period_ms > 0) { - k_work_reschedule(&model->pub->timer, period_ms); - } else { - /* If this fails, publication will stop after the - * ongoing set of retransmits. - */ - k_work_cancel_delayable(&model->pub->timer); - } - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_model_pub_store(model); - } - - return STATUS_SUCCESS; -} - -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 (!bt_mesh_app_key_exists(key_idx)) { - return STATUS_INVALID_APPKEY; - } - - for (i = 0; i < ARRAY_SIZE(model->keys); i++) { - /* Treat existing binding as success */ - if (model->keys[i] == key_idx) { - return STATUS_SUCCESS; - } - } - - for (i = 0; i < ARRAY_SIZE(model->keys); i++) { - if (model->keys[i] == BT_MESH_KEY_UNUSED) { - model->keys[i] = key_idx; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_model_bind_store(model); - } - - return STATUS_SUCCESS; - } - } - - return STATUS_INSUFF_RESOURCES; -} - -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 (!bt_mesh_app_key_exists(key_idx)) { - return STATUS_INVALID_APPKEY; - } - - for (i = 0; i < ARRAY_SIZE(model->keys); i++) { - if (model->keys[i] != key_idx) { - continue; - } - - model->keys[i] = BT_MESH_KEY_UNUSED; - - if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_model_bind_store(model); - } - - if (model->pub && model->pub->key == key_idx) { - _mod_pub_set(model, BT_MESH_ADDR_UNASSIGNED, - 0, 0, 0, 0, 0, store); - } - } - - return STATUS_SUCCESS; -} - -static int send_app_key_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - uint8_t status, - uint16_t app_idx, uint16_t net_idx) -{ - struct os_mbuf *msg = NET_BUF_SIMPLE( - BT_MESH_MODEL_BUF_LEN(OP_APP_KEY_STATUS, 4)); - - 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 (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send App Key Status response"); - } - - os_mbuf_free_chain(msg); - return 0; -} - -static int app_key_add(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t key_net_idx, key_app_idx; - uint8_t status; - - key_idx_unpack(buf, &key_net_idx, &key_app_idx); - - BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); - - status = bt_mesh_app_key_add(key_app_idx, key_net_idx, buf->om_data); - - return send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); -} - -static int app_key_update(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t key_net_idx, key_app_idx; - uint8_t status; - - key_idx_unpack(buf, &key_net_idx, &key_app_idx); - - BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); - - status = bt_mesh_app_key_update(key_app_idx, key_net_idx, buf->om_data); - BT_DBG("status 0x%02x", status); - return send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); -} - -static void mod_app_key_del(struct bt_mesh_model *mod, - struct bt_mesh_elem *elem, bool vnd, bool primary, - void *user_data) -{ - uint16_t *app_idx = user_data; - - mod_unbind(mod, *app_idx, true); -} - -static void app_key_evt(uint16_t app_idx, uint16_t net_idx, - enum bt_mesh_key_evt evt) -{ - if (evt == BT_MESH_KEY_DELETED) { - bt_mesh_model_foreach(&mod_app_key_del, &app_idx); - } -} - -static int app_key_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t key_net_idx, key_app_idx; - uint8_t status; - - key_idx_unpack(buf, &key_net_idx, &key_app_idx); - - BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); - - status = bt_mesh_app_key_del(key_app_idx, key_net_idx); - - return send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); -} - -/* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */ -#define IDX_LEN(num) (((num) / 2) * 3 + ((num) % 2) * 2) - -static int app_key_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = - BT_MESH_MODEL_BUF(OP_APP_KEY_LIST, - 3 + IDX_LEN(CONFIG_BT_MESH_APP_KEY_COUNT)); - uint16_t app_idx[CONFIG_BT_MESH_APP_KEY_COUNT]; - uint16_t get_idx; - uint8_t status; - ssize_t count; - int i; - int err = 0; - - get_idx = net_buf_simple_pull_le16(buf); - if (get_idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", get_idx); - err = -EINVAL; - goto done; - } - - BT_DBG("idx 0x%04x", get_idx); - - bt_mesh_model_msg_init(msg, OP_APP_KEY_LIST); - - if (!bt_mesh_subnet_exists(get_idx)) { - status = STATUS_INVALID_NETKEY; - } else { - status = STATUS_SUCCESS; - } - - net_buf_simple_add_u8(msg, status); - net_buf_simple_add_le16(msg, get_idx); - - if (status != STATUS_SUCCESS) { - goto send_status; - } - - 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); - } - - 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: - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send AppKey List"); - } - -done: - os_mbuf_free_chain(msg); - return err; -} - -static int beacon_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_BEACON_STATUS, 1); - - 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)); - - bt_mesh_model_msg_init(msg, OP_BEACON_STATUS); - 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"); - } - - return 0; - os_mbuf_free_chain(msg); -} - -static int beacon_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - int err = 0; - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_BEACON_STATUS, 1); - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { - BT_WARN("Invalid Config Beacon value 0x%02x", buf->om_data[0]); - err = -EINVAL; - goto done; - } - - bt_mesh_beacon_set(buf->om_data[0]); - - bt_mesh_model_msg_init(msg, OP_BEACON_STATUS); - 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"); - } - -done: - os_mbuf_free_chain(msg); - return err; -} - -static int default_ttl_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1); - - 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)); - - bt_mesh_model_msg_init(msg, OP_DEFAULT_TTL_STATUS); - net_buf_simple_add_u8(msg, bt_mesh_default_ttl_get()); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Default TTL Status response"); - } - - os_mbuf_free_chain(msg); - return 0; -} - -static int default_ttl_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1); - int err; - - 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)); - - 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, buf->om_data[0]); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Default TTL Status response"); - } - -done: - os_mbuf_free_chain(msg); - return err; -} - -static int send_gatt_proxy_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_GATT_PROXY_STATUS, 1); - - bt_mesh_model_msg_init(msg, OP_GATT_PROXY_STATUS); - net_buf_simple_add_u8(msg, bt_mesh_gatt_proxy_get()); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send GATT Proxy Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int gatt_proxy_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - return send_gatt_proxy_status(model, ctx); -} - -static int gatt_proxy_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { - BT_WARN("Invalid GATT Proxy value 0x%02x", buf->om_data[0]); - return -EINVAL; - } - - (void)bt_mesh_gatt_proxy_set(buf->om_data[0]); - - return send_gatt_proxy_status(model, ctx); -} - -static int net_transmit_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1); - - 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)); - - bt_mesh_model_msg_init(msg, OP_NET_TRANSMIT_STATUS); - net_buf_simple_add_u8(msg, bt_mesh_net_transmit_get()); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Config Network Transmit Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int net_transmit_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1); - - 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)); - - BT_DBG("Transmit 0x%02x (count %u interval %ums)", buf->om_data[0], - BT_MESH_TRANSMIT_COUNT(buf->om_data[0]), - BT_MESH_TRANSMIT_INT(buf->om_data[0])); - - 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, buf->om_data[0]); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Network Transmit Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int relay_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_RELAY_STATUS, 2); - - 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)); - - 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()); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Config Relay Status response"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int relay_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_STATUS, 2); - int err = 0; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { - BT_WARN("Invalid Relay value 0x%02x", buf->om_data[0]); - err = -EINVAL; - goto done; - } - - (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()); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Relay Status response"); - } - -done: - os_mbuf_free_chain(msg); - return err; -} - -static int send_mod_pub_status(struct bt_mesh_model *cfg_mod, - struct bt_mesh_msg_ctx *ctx, - uint16_t elem_addr, uint16_t pub_addr, - bool vnd, struct bt_mesh_model *mod, - uint8_t status, uint8_t *mod_id) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_STATUS, 14); - - bt_mesh_model_msg_init(msg, OP_MOD_PUB_STATUS); - - net_buf_simple_add_u8(msg, status); - net_buf_simple_add_le16(msg, elem_addr); - - if (status != STATUS_SUCCESS) { - memset(net_buf_simple_add(msg, 7), 0, 7); - } else { - uint16_t idx_cred; - - net_buf_simple_add_le16(msg, pub_addr); - - 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); - net_buf_simple_add_u8(msg, mod->pub->retransmit); - } - - if (vnd) { - memcpy(net_buf_simple_add(msg, 4), mod_id, 4); - } else { - memcpy(net_buf_simple_add(msg, 2), mod_id, 2); - } - - if (bt_mesh_model_send(cfg_mod, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Model Publication Status"); - } - - os_mbuf_free_chain(msg); - return 0; -} - -static int mod_pub_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t elem_addr, pub_addr = 0; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *mod_id, status; - bool vnd; - - if ((buf->om_len != 4U) && (buf->om_len != 6U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - mod_id = buf->om_data; - - 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_SUCCESS; - -send_status: - return send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); -} - -static int mod_pub_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t retransmit, status, pub_ttl, pub_period, cred_flag; - uint16_t elem_addr, pub_addr, pub_app_idx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *mod_id; - bool vnd; - - if ((buf->om_len != 11U) && (buf->om_len != 13U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - pub_addr = net_buf_simple_pull_le16(buf); - pub_app_idx = net_buf_simple_pull_le16(buf); - cred_flag = ((pub_app_idx >> 12) & BIT_MASK(1)); - pub_app_idx &= BIT_MASK(12); - - pub_ttl = net_buf_simple_pull_u8(buf); - if (pub_ttl > BT_MESH_TTL_MAX && pub_ttl != BT_MESH_TTL_DEFAULT) { - BT_ERR("Invalid TTL value 0x%02x", pub_ttl); - return -EINVAL; - } - - pub_period = net_buf_simple_pull_u8(buf); - retransmit = net_buf_simple_pull_u8(buf); - mod_id = buf->om_data; - - BT_DBG("elem_addr 0x%04x pub_addr 0x%04x cred_flag %u", - elem_addr, pub_addr, cred_flag); - BT_DBG("pub_app_idx 0x%03x, pub_ttl %u pub_period 0x%02x", - pub_app_idx, pub_ttl, pub_period); - BT_DBG("retransmit 0x%02x (count %u interval %ums)", retransmit, - BT_MESH_PUB_TRANSMIT_COUNT(retransmit), - BT_MESH_PUB_TRANSMIT_INT(retransmit)); - - 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 = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl, - pub_period, retransmit, true); - -send_status: - return send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); -} - -static size_t mod_sub_list_clear(struct bt_mesh_model *mod) -{ - uint8_t *label_uuid; - 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 (!BT_MESH_ADDR_IS_VIRTUAL(mod->groups[i])) { - if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { - mod->groups[i] = BT_MESH_ADDR_UNASSIGNED; - clear_count++; - } - - continue; - } - - label_uuid = bt_mesh_va_label_get(mod->groups[i]); - - mod->groups[i] = BT_MESH_ADDR_UNASSIGNED; - clear_count++; - - if (label_uuid) { - bt_mesh_va_del(label_uuid, NULL); - } else { - BT_ERR("Label UUID not found"); - } - } - - return clear_count; -} - -static int mod_pub_va_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t retransmit, status, pub_ttl, pub_period, cred_flag; - uint16_t elem_addr, pub_addr, pub_app_idx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *label_uuid; - uint8_t *mod_id; - bool vnd; - - if ((buf->om_len != 25U) && (buf->om_len != 27U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - label_uuid = net_buf_simple_pull_mem(buf, 16); - pub_app_idx = net_buf_simple_pull_le16(buf); - cred_flag = ((pub_app_idx >> 12) & BIT_MASK(1)); - pub_app_idx &= BIT_MASK(12); - pub_ttl = net_buf_simple_pull_u8(buf); - if (pub_ttl > BT_MESH_TTL_MAX && pub_ttl != BT_MESH_TTL_DEFAULT) { - BT_ERR("Invalid TTL value 0x%02x", pub_ttl); - return -EINVAL; - } - - pub_period = net_buf_simple_pull_u8(buf); - retransmit = net_buf_simple_pull_u8(buf); - mod_id = buf->om_data; - - BT_DBG("elem_addr 0x%04x cred_flag %u", elem_addr, cred_flag); - BT_DBG("pub_app_idx 0x%03x, pub_ttl %u pub_period 0x%02x", - pub_app_idx, pub_ttl, pub_period); - BT_DBG("retransmit 0x%02x (count %u interval %ums)", retransmit, - BT_MESH_PUB_TRANSMIT_COUNT(retransmit), - BT_MESH_PUB_TRANSMIT_INT(retransmit)); - - elem = bt_mesh_elem_find(elem_addr); - if (!elem) { - mod = NULL; - vnd = (buf->om_len == 4); - pub_addr = 0; - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - mod = get_model(elem, buf, &vnd); - if (!mod) { - pub_addr = 0; - status = STATUS_INVALID_MODEL; - goto send_status; - } - - 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: - return send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); -} - -static int send_mod_sub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, uint8_t status, - uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id, - bool vnd) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_SUB_STATUS, 9); - - BT_DBG("status 0x%02x elem_addr 0x%04x sub_addr 0x%04x", status, - elem_addr, sub_addr); - - bt_mesh_model_msg_init(msg, OP_MOD_SUB_STATUS); - - net_buf_simple_add_u8(msg, status); - net_buf_simple_add_le16(msg, elem_addr); - net_buf_simple_add_le16(msg, sub_addr); - - if (vnd) { - memcpy(net_buf_simple_add(msg, 4), mod_id, 4); - } else { - memcpy(net_buf_simple_add(msg, 2), mod_id, 2); - } - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Model Subscription Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int mod_sub_add(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t elem_addr, sub_addr; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *mod_id; - uint8_t status; - uint16_t *entry; - bool vnd; - - if ((buf->om_len != 6U) && (buf->om_len != 8U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - sub_addr = net_buf_simple_pull_le16(buf); - - BT_DBG("elem_addr 0x%04x, sub_addr 0x%04x", elem_addr, sub_addr); - - 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; - } - - if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - if (bt_mesh_model_find_group(&mod, sub_addr)) { - /* Tried to add existing subscription */ - BT_DBG("found existing subscription"); - status = STATUS_SUCCESS; - goto send_status; - } - - entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED); - if (!entry) { - status = STATUS_INSUFF_RESOURCES; - goto send_status; - } - - *entry = sub_addr; - status = STATUS_SUCCESS; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_model_sub_store(mod); - } - - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - bt_mesh_lpn_group_add(sub_addr); - } - - -send_status: - return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); -} - -static int mod_sub_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t elem_addr, sub_addr; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *mod_id; - uint16_t *match; - uint8_t status; - bool vnd; - - if ((buf->om_len != 6U) && (buf->om_len != 8U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - sub_addr = net_buf_simple_pull_le16(buf); - - BT_DBG("elem_addr 0x%04x sub_addr 0x%04x", elem_addr, sub_addr); - - 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; - } - - if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - /* An attempt to remove a non-existing address shall be treated - * as a success. - */ - status = STATUS_SUCCESS; - - if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) { - bt_mesh_lpn_group_del(&sub_addr, 1); - } - - match = bt_mesh_model_find_group(&mod, sub_addr); - if (match) { - *match = BT_MESH_ADDR_UNASSIGNED; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_model_sub_store(mod); - } - } - -send_status: - return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); -} - -static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, void *user_data) -{ - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups)); - } - - mod_sub_list_clear(mod); - - return BT_MESH_WALK_CONTINUE; -} - -static int mod_sub_overwrite(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t elem_addr, sub_addr; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *mod_id; - uint8_t status; - bool vnd; - - if ((buf->om_len != 6U) && (buf->om_len != 8U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - sub_addr = net_buf_simple_pull_le16(buf); - - BT_DBG("elem_addr 0x%04x sub_addr 0x%04x", elem_addr, sub_addr); - - 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; - } - - if (!BT_MESH_ADDR_IS_GROUP(sub_addr)) { - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - if (ARRAY_SIZE(mod->groups) > 0) { - bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL); - - mod->groups[0] = sub_addr; - status = STATUS_SUCCESS; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_model_sub_store(mod); - } - - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - bt_mesh_lpn_group_add(sub_addr); - } - } else { - status = STATUS_INSUFF_RESOURCES; - } - - -send_status: - return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); -} - -static int mod_sub_del_all(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint16_t elem_addr; - uint8_t *mod_id; - uint8_t status; - bool vnd; - - if ((buf->om_len != 4U) && (buf->om_len != 6U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - BT_DBG("elem_addr 0x%04x", elem_addr); - - 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; - } - - bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL); - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_model_sub_store(mod); - } - - status = STATUS_SUCCESS; - -send_status: - return send_mod_sub_status(model, ctx, status, elem_addr, - BT_MESH_ADDR_UNASSIGNED, mod_id, vnd); -} - -struct mod_sub_list_ctx { - uint16_t elem_idx; - struct os_mbuf *msg; -}; - -static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod, void *ctx) -{ - struct mod_sub_list_ctx *visit = ctx; - int count = 0; - int i; - - if (mod->elem_idx != visit->elem_idx) { - return BT_MESH_WALK_CONTINUE; - } - - for (i = 0; i < ARRAY_SIZE(mod->groups); i++) { - if (mod->groups[i] == BT_MESH_ADDR_UNASSIGNED) { - continue; - } - - if (net_buf_simple_tailroom(visit->msg) < - 2 + BT_MESH_MIC_SHORT) { - BT_WARN("No room for all groups"); - return BT_MESH_WALK_STOP; - } - - net_buf_simple_add_le16(visit->msg, mod->groups[i]); - count++; - } - - BT_DBG("sublist: model %u:%x: %u groups", mod->elem_idx, mod->id, - count); - - return BT_MESH_WALK_CONTINUE; -} - -static int mod_sub_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - struct mod_sub_list_ctx visit_ctx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint16_t addr, id; - int err = 0; - - addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(addr)) { - BT_WARN("Prohibited element address"); - err = -EINVAL; - goto done; - } - - id = net_buf_simple_pull_le16(buf); - - BT_DBG("addr 0x%04x id 0x%04x", addr, id); - - bt_mesh_model_msg_init(msg, OP_MOD_SUB_LIST); - - elem = bt_mesh_elem_find(addr); - if (!elem) { - net_buf_simple_add_u8(msg, STATUS_INVALID_ADDRESS); - net_buf_simple_add_le16(msg, addr); - net_buf_simple_add_le16(msg, id); - goto send_list; - } - - mod = bt_mesh_model_find(elem, id); - if (!mod) { - net_buf_simple_add_u8(msg, STATUS_INVALID_MODEL); - net_buf_simple_add_le16(msg, addr); - net_buf_simple_add_le16(msg, id); - goto send_list; - } - - net_buf_simple_add_u8(msg, STATUS_SUCCESS); - - net_buf_simple_add_le16(msg, addr); - net_buf_simple_add_le16(msg, id); - - visit_ctx.msg = msg; - visit_ctx.elem_idx = mod->elem_idx; - bt_mesh_model_extensions_walk(mod, mod_sub_list_visitor, &visit_ctx); - -send_list: - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Model Subscription List"); - } - -done: - os_mbuf_free_chain(msg); - - return err; -} - -static int mod_sub_get_vnd(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - struct mod_sub_list_ctx visit_ctx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint16_t company, addr, id; - int err = 0; - - addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(addr)) { - BT_WARN("Prohibited element address"); - err = -EINVAL; - goto done; - } - - company = net_buf_simple_pull_le16(buf); - id = net_buf_simple_pull_le16(buf); - - BT_DBG("addr 0x%04x company 0x%04x id 0x%04x", addr, company, id); - - bt_mesh_model_msg_init(msg, OP_MOD_SUB_LIST_VND); - - elem = bt_mesh_elem_find(addr); - if (!elem) { - net_buf_simple_add_u8(msg, STATUS_INVALID_ADDRESS); - net_buf_simple_add_le16(msg, addr); - net_buf_simple_add_le16(msg, company); - net_buf_simple_add_le16(msg, id); - goto send_list; - } - - mod = bt_mesh_model_find_vnd(elem, company, id); - if (!mod) { - net_buf_simple_add_u8(msg, STATUS_INVALID_MODEL); - net_buf_simple_add_le16(msg, addr); - net_buf_simple_add_le16(msg, company); - net_buf_simple_add_le16(msg, id); - goto send_list; - } - - net_buf_simple_add_u8(msg, STATUS_SUCCESS); - - net_buf_simple_add_le16(msg, addr); - 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_extensions_walk(mod, mod_sub_list_visitor, &visit_ctx); - -send_list: - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Vendor Model Subscription List"); - } - -done: - os_mbuf_free_chain(msg); - - return err; -} - -static int mod_sub_va_add(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t elem_addr, sub_addr; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *label_uuid; - uint8_t *mod_id; - uint16_t *entry; - uint8_t status; - bool vnd; - - if ((buf->om_len != 20U) && (buf->om_len != 22U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - label_uuid = net_buf_simple_pull_mem(buf, 16); - - BT_DBG("elem_addr 0x%04x", elem_addr); - - mod_id = buf->om_data; - elem = bt_mesh_elem_find(elem_addr); - if (!elem) { - mod = NULL; - vnd = (buf->om_len == 4); - sub_addr = BT_MESH_ADDR_UNASSIGNED; - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - mod = get_model(elem, buf, &vnd); - if (!mod) { - sub_addr = BT_MESH_ADDR_UNASSIGNED; - status = STATUS_INVALID_MODEL; - goto send_status; - } - - status = bt_mesh_va_add(label_uuid, &sub_addr); - if (status != STATUS_SUCCESS) { - goto send_status; - } - - 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; - } - - - 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; - } - - *entry = sub_addr; - - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - bt_mesh_lpn_group_add(sub_addr); - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_model_sub_store(mod); - } - - status = STATUS_SUCCESS; - -send_status: - return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); -} - -static int mod_sub_va_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t elem_addr, sub_addr; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *label_uuid; - uint8_t *mod_id; - uint16_t *match; - uint8_t status; - bool vnd; - - if ((buf->om_len != 20U) && (buf->om_len != 22U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - label_uuid = net_buf_simple_pull_mem(buf, 16); - - BT_DBG("elem_addr 0x%04x", elem_addr); - - mod_id = buf->om_data; - - elem = bt_mesh_elem_find(elem_addr); - if (!elem) { - mod = NULL; - vnd = (buf->om_len == 4); - sub_addr = BT_MESH_ADDR_UNASSIGNED; - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - mod = get_model(elem, buf, &vnd); - if (!mod) { - sub_addr = BT_MESH_ADDR_UNASSIGNED; - status = STATUS_INVALID_MODEL; - goto send_status; - } - - status = bt_mesh_va_del(label_uuid, &sub_addr); - if (sub_addr == BT_MESH_ADDR_UNASSIGNED) { - goto send_status; - } - - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - bt_mesh_lpn_group_del(&sub_addr, 1); - } - - match = bt_mesh_model_find_group(&mod, sub_addr); - if (match) { - *match = BT_MESH_ADDR_UNASSIGNED; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_model_sub_store(mod); - } - - status = STATUS_SUCCESS; - } else { - status = STATUS_CANNOT_REMOVE; - } - -send_status: - return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); -} - -static int mod_sub_va_overwrite(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *label_uuid; - uint8_t *mod_id; - uint8_t status; - bool vnd; - - if ((buf->om_len != 20U) && (buf->om_len != 22U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return -EINVAL; - } - - label_uuid = net_buf_simple_pull_mem(buf, 16); - - BT_DBG("elem_addr 0x%04x", elem_addr); - - 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; - } - - if (ARRAY_SIZE(mod->groups) > 0) { - status = bt_mesh_va_add(label_uuid, &sub_addr); - if (status == STATUS_SUCCESS) { - bt_mesh_model_extensions_walk(mod, mod_sub_clear_visitor, NULL); - mod->groups[0] = sub_addr; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_model_sub_store(mod); - } - - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - bt_mesh_lpn_group_add(sub_addr); - } - } - } else { - status = STATUS_INSUFF_RESOURCES; - } - -send_status: - return send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, - mod_id, vnd); -} - -static int send_net_key_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - uint16_t idx, uint8_t status) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_STATUS, 3); - - bt_mesh_model_msg_init(msg, OP_NET_KEY_STATUS); - - net_buf_simple_add_u8(msg, status); - net_buf_simple_add_le16(msg, idx); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send NetKey Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int net_key_add(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t status; - uint16_t idx; - - idx = net_buf_simple_pull_le16(buf); - if (idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return -EINVAL; - } - - BT_DBG("idx 0x%04x", idx); - - status = bt_mesh_subnet_add(idx, buf->om_data); - return send_net_key_status(model, ctx, idx, status); -} - -static int net_key_update(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t status; - uint16_t idx; - - idx = net_buf_simple_pull_le16(buf); - if (idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return -EINVAL; - } - - status = bt_mesh_subnet_update(idx, buf->om_data); - - return send_net_key_status(model, ctx, idx, status); -} - -static int net_key_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint16_t del_idx; - - del_idx = net_buf_simple_pull_le16(buf); - if (del_idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", del_idx); - return -EINVAL; - } - - BT_DBG("idx 0x%04x", del_idx); - - /* 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) { - return send_net_key_status(model, ctx, del_idx, - STATUS_CANNOT_REMOVE); - } - - (void)bt_mesh_subnet_del(del_idx); - - return send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS); -} - -static int net_key_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = - BT_MESH_MODEL_BUF(OP_NET_KEY_LIST, - IDX_LEN(CONFIG_BT_MESH_SUBNET_COUNT)); - uint16_t net_idx[CONFIG_BT_MESH_SUBNET_COUNT]; - ssize_t count; - int i; - - bt_mesh_model_msg_init(msg, OP_NET_KEY_LIST); - - 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); - } - - 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)) { - BT_ERR("Unable to send NetKey List"); - } - - os_mbuf_free_chain(msg); - return 0; -} - -static int send_node_id_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - uint8_t status, - uint16_t net_idx, uint8_t node_id) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4); - - 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); - - return 0; -} - -static int node_identity_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - enum bt_mesh_feat_state node_id; - uint8_t status; - 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, - bt_hex(buf->om_data, buf->om_len)); - - idx = net_buf_simple_pull_le16(buf); - if (idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return -EINVAL; - } - - status = bt_mesh_subnet_node_id_get(idx, &node_id); - - return send_node_id_status(model, ctx, status, idx, node_id); -} - -static int node_identity_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t node_id, status; - uint16_t idx; - - 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)); - - idx = net_buf_simple_pull_le16(buf); - if (idx > 0xfff) { - BT_WARN("Invalid NetKeyIndex 0x%04x", idx); - return -EINVAL; - } - - node_id = net_buf_simple_pull_u8(buf); - if (node_id != 0x00 && node_id != 0x01) { - BT_WARN("Invalid Node ID value 0x%02x", node_id); - return -EINVAL; - } - - status = bt_mesh_subnet_node_id_set(idx, node_id); - if (status == STATUS_INVALID_NETKEY) { - return send_node_id_status(model, ctx, status, idx, - BT_MESH_NODE_IDENTITY_STOPPED); - } - - if (status == STATUS_FEAT_NOT_SUPP) { - /* Should return success, even if feature isn't supported: */ - return send_node_id_status(model, ctx, STATUS_SUCCESS, idx, - BT_MESH_NODE_IDENTITY_NOT_SUPPORTED); - } - - return 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, - 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); - - net_buf_simple_add_u8(msg, status); - net_buf_simple_add_le16(msg, elem_addr); - net_buf_simple_add_le16(msg, app_idx); - - if (vnd) { - memcpy(net_buf_simple_add(msg, 4), mod_id, 4); - } else { - memcpy(net_buf_simple_add(msg, 2), mod_id, 2); - } -} - -static int mod_app_bind(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9); - uint16_t elem_addr, key_app_idx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *mod_id, status; - bool vnd; - int err = 0; - - if ((buf->om_len != 6U) && (buf->om_len != 8U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - err = -EINVAL; - goto done; - } - - key_app_idx = net_buf_simple_pull_le16(buf); - 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; - } - - /* Configuration Server only allows device key based access */ - if (model == mod) { - BT_ERR("Client tried to bind AppKey to Configuration Model"); - status = STATUS_CANNOT_BIND; - goto send_status; - } - - status = mod_bind(mod, key_app_idx); - - if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) { - bt_test_mesh_model_bound(ctx->addr, mod, key_app_idx); - } - -send_status: - BT_DBG("status 0x%02x", status); - create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status, - mod_id); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Model App Bind Status response"); - } - -done: - os_mbuf_free_chain(msg); - - return err; -} - -static int mod_app_unbind(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9); - uint16_t elem_addr, key_app_idx; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *mod_id, status; - bool vnd; - int err = 0; - - if ((buf->om_len != 6U) && (buf->om_len != 8U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - err = -EINVAL; - goto done; - } - - key_app_idx = net_buf_simple_pull_le16(buf); - 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 = mod_unbind(mod, key_app_idx, true); - - if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) { - bt_test_mesh_model_unbound(ctx->addr, mod, key_app_idx); - } - -send_status: - BT_DBG("status 0x%02x", status); - create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status, - mod_id); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Model App Unbind Status response"); - } - -done: - os_mbuf_free_chain(msg); - - return err; -} - -#define KEY_LIST_LEN (MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT) * 2) - -static int mod_app_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = NET_BUF_SIMPLE(MAX(BT_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST, - 9 + KEY_LIST_LEN), - BT_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST, - 9 + KEY_LIST_LEN))); - - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - uint8_t *mod_id, status; - uint16_t elem_addr; - bool vnd; - int err = 0; - - if ((buf->om_len != 4U) && (buf->om_len != 6U)) { - BT_ERR("The message size for the application opcode is incorrect."); - return -EMSGSIZE; - } - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - err = -EINVAL; - goto done; - } - - mod_id = buf->om_data; - - 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_list; - } - - mod = get_model(elem, buf, &vnd); - if (!mod) { - status = STATUS_INVALID_MODEL; - goto send_list; - } - - status = STATUS_SUCCESS; - -send_list: - if (vnd) { - bt_mesh_model_msg_init(msg, OP_VND_MOD_APP_LIST); - } else { - bt_mesh_model_msg_init(msg, OP_SIG_MOD_APP_LIST); - } - - net_buf_simple_add_u8(msg, status); - net_buf_simple_add_le16(msg, elem_addr); - - if (vnd) { - net_buf_simple_add_mem(msg, mod_id, 4); - } else { - net_buf_simple_add_mem(msg, mod_id, 2); - } - - if (mod) { - int i; - - for (i = 0; i < ARRAY_SIZE(mod->keys); i++) { - if (mod->keys[i] != BT_MESH_KEY_UNUSED) { - net_buf_simple_add_le16(msg, mod->keys[i]); - } - } - } - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Model Application List message"); - } - -done: - os_mbuf_free_chain(msg); - - return err; -} - -static void reset_send_start(uint16_t duration, int err, void *cb_data) -{ - if (err) { - BT_ERR("Sending Node Reset Status failed (err %d)", err); - bt_mesh_reset(); - } -} - -static void reset_send_end(int err, void *cb_data) -{ - bt_mesh_reset(); -} - -static int node_reset(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - static const struct bt_mesh_send_cb reset_cb = { - .start = reset_send_start, - .end = reset_send_end, - }; - - 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", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - bt_mesh_model_msg_init(msg, OP_NODE_RESET_STATUS); - - if (bt_mesh_model_send(model, ctx, msg, &reset_cb, NULL)) { - BT_ERR("Unable to send Node Reset Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int send_friend_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_FRIEND_STATUS, 1); - - bt_mesh_model_msg_init(msg, OP_FRIEND_STATUS); - 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"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int friend_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - return send_friend_status(model, ctx); -} - -static int friend_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { - BT_WARN("Invalid Friend value 0x%02x", buf->om_data[0]); - return -EINVAL; - } - - (void)bt_mesh_friend_set(buf->om_data[0]); - - return send_friend_status(model, ctx); -} - -static int lpn_timeout_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_STATUS, 5); - struct bt_mesh_friend *frnd; - int32_t timeout_steps; - uint16_t lpn_addr; - int err = 0; - - lpn_addr = net_buf_simple_pull_le16(buf); - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x lpn_addr 0x%02x", - ctx->net_idx, ctx->app_idx, ctx->addr, lpn_addr); - - /* check if it's the address of the Low Power Node? */ - if (!BT_MESH_ADDR_IS_UNICAST(lpn_addr)) { - BT_WARN("Invalid LPNAddress; ignoring msg"); - err = -EINVAL; - goto done; - } - - bt_mesh_model_msg_init(msg, OP_LPN_TIMEOUT_STATUS); - net_buf_simple_add_le16(msg, lpn_addr); - - if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { - timeout_steps = 0; - goto send_rsp; - } - - frnd = bt_mesh_friend_find(BT_MESH_KEY_ANY, lpn_addr, true, true); - if (!frnd) { - timeout_steps = 0; - goto send_rsp; - } - - /* PollTimeout should be reported in steps of 100ms. */ - timeout_steps = frnd->poll_to / 100; - -send_rsp: - net_buf_simple_add_le24(msg, timeout_steps); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send LPN PollTimeout Status"); - } - -done: - os_mbuf_free_chain(msg); - - return err; -} - -static int send_krp_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - uint16_t idx, uint8_t phase, uint8_t status) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_STATUS, 4); - - bt_mesh_model_msg_init(msg, OP_KRP_STATUS); - - net_buf_simple_add_u8(msg, status); - net_buf_simple_add_le16(msg, idx); - net_buf_simple_add_u8(msg, phase); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Key Refresh State Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t kr_phase, status; - uint16_t idx; - - idx = net_buf_simple_pull_le16(buf); - if (idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return -EINVAL; - } - - BT_DBG("idx 0x%04x", idx); - - status = bt_mesh_subnet_kr_phase_get(idx, &kr_phase); - - return send_krp_status(model, ctx, idx, kr_phase, status); -} - -static int krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t phase, status; - uint16_t idx; - - idx = net_buf_simple_pull_le16(buf); - phase = net_buf_simple_pull_u8(buf); - - if (idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - return -EINVAL; - } - - status = bt_mesh_subnet_kr_phase_set(idx, &phase); - if (status == STATUS_CANNOT_UPDATE) { - BT_ERR("Invalid kr phase transition 0x%02x", phase); - return -EINVAL; - } - - return send_krp_status(model, ctx, idx, phase, status); -} - -static uint8_t hb_pub_count_log(uint16_t val) -{ - if (!val) { - return 0x00; - } else if (val == 0x01) { - return 0x01; - } else if (val == 0xffff) { - return 0xff; - } else { - return 32 - __builtin_clz(val - 1) + 1; - } -} - -struct hb_pub_param { - uint16_t dst; - uint8_t count_log; - uint8_t period_log; - uint8_t ttl; - uint16_t feat; - uint16_t net_idx; -} __packed; - -static int hb_pub_send_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, uint8_t status, - const struct bt_mesh_hb_pub *pub) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_STATUS, 10); - - BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status); - - bt_mesh_model_msg_init(msg, OP_HEARTBEAT_PUB_STATUS); - - net_buf_simple_add_u8(msg, status); - - 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); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Heartbeat Publication Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int 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); - - bt_mesh_hb_pub_get(&pub); - - return hb_pub_send_status(model, ctx, STATUS_SUCCESS, &pub); -} - -static int heartbeat_pub_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct hb_pub_param *param = (void *)buf->om_data; - struct bt_mesh_hb_pub pub; - uint8_t status; - - BT_DBG("src 0x%04x", ctx->addr); - - 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(pub.dst)) { - status = STATUS_INVALID_ADDRESS; - goto rsp; - } - - if (param->count_log > 0x11 && param->count_log != 0xff) { - status = STATUS_CANNOT_SET; - goto rsp; - } - - if (param->period_log > 0x10) { - status = STATUS_CANNOT_SET; - goto rsp; - } - - if (param->ttl > BT_MESH_TTL_MAX && param->ttl != BT_MESH_TTL_DEFAULT) { - BT_ERR("Invalid TTL value 0x%02x", param->ttl); - return -EINVAL; - } - - if (pub.net_idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", pub.net_idx); - return -EINVAL; - } - - status = bt_mesh_hb_pub_set(&pub); -rsp: - return hb_pub_send_status(model, ctx, status, &pub); -} - -static int hb_sub_send_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - const struct bt_mesh_hb_sub *sub) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_STATUS, 9); - BT_DBG("src 0x%04x ", ctx->addr); - - bt_mesh_model_msg_init(msg, OP_HEARTBEAT_SUB_STATUS); - - 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)) { - BT_ERR("Unable to send Heartbeat Subscription Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int heartbeat_sub_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_hb_sub sub; - - BT_DBG("src 0x%04x", ctx->addr); - - bt_mesh_hb_sub_get(&sub); - - return hb_sub_send_status(model, ctx, &sub); -} - -static int heartbeat_sub_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t period_log, status; - struct bt_mesh_hb_sub sub; - uint16_t sub_src, sub_dst; - uint32_t period; - int err; - - BT_DBG("src 0x%04x", ctx->addr); - - sub_src = net_buf_simple_pull_le16(buf); - sub_dst = net_buf_simple_pull_le16(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, period_log); - - if (period_log > 0x11) { - BT_WARN("Prohibited subscription period 0x%02x", period_log); - return -EINVAL; - } - - period = bt_mesh_hb_pwr2(period_log); - - 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. - */ - return -EINVAL; - } - - 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 (sub.src == BT_MESH_ADDR_UNASSIGNED || !period_log) { - sub.min_hops = BT_MESH_TTL_MAX; - } - - err = hb_sub_send_status(model, ctx, &sub); - if (err) { - return err; - } - - /* MESH/NODE/CFG/HBS/BV-02-C expects us to return previous - * count value and then reset it to 0. - */ - if (sub.src != BT_MESH_ADDR_UNASSIGNED && - sub.dst != BT_MESH_ADDR_UNASSIGNED && !period) { - bt_mesh_hb_sub_reset_count(); - } - - return 0; -} - -const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = { - { OP_DEV_COMP_DATA_GET, BT_MESH_LEN_EXACT(1), dev_comp_data_get }, - { OP_APP_KEY_ADD, BT_MESH_LEN_EXACT(19), app_key_add }, - { OP_APP_KEY_UPDATE, BT_MESH_LEN_EXACT(19), app_key_update }, - { OP_APP_KEY_DEL, BT_MESH_LEN_EXACT(3), app_key_del }, - { OP_APP_KEY_GET, BT_MESH_LEN_EXACT(2), app_key_get }, - { OP_BEACON_GET, BT_MESH_LEN_EXACT(0), beacon_get }, - { OP_BEACON_SET, BT_MESH_LEN_EXACT(1), beacon_set }, - { OP_DEFAULT_TTL_GET, BT_MESH_LEN_EXACT(0), default_ttl_get }, - { OP_DEFAULT_TTL_SET, BT_MESH_LEN_EXACT(1), default_ttl_set }, - { OP_GATT_PROXY_GET, BT_MESH_LEN_EXACT(0), gatt_proxy_get }, - { OP_GATT_PROXY_SET, BT_MESH_LEN_EXACT(1), gatt_proxy_set }, - { OP_NET_TRANSMIT_GET, BT_MESH_LEN_EXACT(0), net_transmit_get }, - { OP_NET_TRANSMIT_SET, BT_MESH_LEN_EXACT(1), net_transmit_set }, - { OP_RELAY_GET, BT_MESH_LEN_EXACT(0), relay_get }, - { OP_RELAY_SET, BT_MESH_LEN_EXACT(2), relay_set }, - { OP_MOD_PUB_GET, BT_MESH_LEN_MIN(4), mod_pub_get }, - { OP_MOD_PUB_SET, BT_MESH_LEN_MIN(11), mod_pub_set }, - { OP_MOD_PUB_VA_SET, BT_MESH_LEN_MIN(25), mod_pub_va_set }, - { OP_MOD_SUB_ADD, BT_MESH_LEN_MIN(6), mod_sub_add }, - { OP_MOD_SUB_VA_ADD, BT_MESH_LEN_MIN(20), mod_sub_va_add }, - { OP_MOD_SUB_DEL, BT_MESH_LEN_MIN(6), mod_sub_del }, - { OP_MOD_SUB_VA_DEL, BT_MESH_LEN_MIN(20), mod_sub_va_del }, - { OP_MOD_SUB_OVERWRITE, BT_MESH_LEN_MIN(6), mod_sub_overwrite }, - { OP_MOD_SUB_VA_OVERWRITE, BT_MESH_LEN_MIN(20), mod_sub_va_overwrite }, - { OP_MOD_SUB_DEL_ALL, BT_MESH_LEN_MIN(4), mod_sub_del_all }, - { OP_MOD_SUB_GET, BT_MESH_LEN_EXACT(4), mod_sub_get }, - { OP_MOD_SUB_GET_VND, BT_MESH_LEN_EXACT(6), mod_sub_get_vnd }, - { OP_NET_KEY_ADD, BT_MESH_LEN_EXACT(18), net_key_add }, - { OP_NET_KEY_UPDATE, BT_MESH_LEN_EXACT(18), net_key_update }, - { OP_NET_KEY_DEL, BT_MESH_LEN_EXACT(2), net_key_del }, - { OP_NET_KEY_GET, BT_MESH_LEN_EXACT(0), net_key_get }, - { OP_NODE_IDENTITY_GET, BT_MESH_LEN_EXACT(2), node_identity_get }, - { OP_NODE_IDENTITY_SET, BT_MESH_LEN_EXACT(3), node_identity_set }, - { OP_MOD_APP_BIND, BT_MESH_LEN_MIN(6), mod_app_bind }, - { OP_MOD_APP_UNBIND, BT_MESH_LEN_MIN(6), mod_app_unbind }, - { OP_SIG_MOD_APP_GET, BT_MESH_LEN_MIN(4), mod_app_get }, - { OP_VND_MOD_APP_GET, BT_MESH_LEN_MIN(6), mod_app_get }, - { OP_NODE_RESET, BT_MESH_LEN_EXACT(0), node_reset }, - { OP_FRIEND_GET, BT_MESH_LEN_EXACT(0), friend_get }, - { OP_FRIEND_SET, BT_MESH_LEN_EXACT(1), friend_set }, - { OP_LPN_TIMEOUT_GET, BT_MESH_LEN_EXACT(2), lpn_timeout_get }, - { OP_KRP_GET, BT_MESH_LEN_EXACT(2), krp_get }, - { OP_KRP_SET, BT_MESH_LEN_EXACT(3), krp_set }, - { OP_HEARTBEAT_PUB_GET, BT_MESH_LEN_EXACT(0), heartbeat_pub_get }, - { OP_HEARTBEAT_PUB_SET, BT_MESH_LEN_EXACT(9), heartbeat_pub_set }, - { OP_HEARTBEAT_SUB_GET, BT_MESH_LEN_EXACT(0), heartbeat_sub_get }, - { OP_HEARTBEAT_SUB_SET, BT_MESH_LEN_EXACT(5), heartbeat_sub_set }, - BT_MESH_MODEL_OP_END, -}; - -static int cfg_srv_init(struct bt_mesh_model *model) -{ - bt_mesh_app_key_cb_list[0] = app_key_evt; - - BT_DBG(""); - - if (!bt_mesh_model_in_primary(model)) { - BT_ERR("Configuration Server only allowed in primary element"); - 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; - - return 0; -} - -const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb = { - .init = cfg_srv_init, -}; - -static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, - bool vnd, bool primary, void *user_data) -{ - size_t clear_count; - - /* Clear model state that isn't otherwise cleared. E.g. AppKey - * binding and model publication is cleared as a consequence - * of removing all app keys, however model subscription and user data - * clearing must be taken care of here. - */ - - clear_count = mod_sub_list_clear(mod); - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - if (clear_count) { - bt_mesh_model_sub_store(mod); - } - } - - if (mod->cb && mod->cb->reset) { - mod->cb->reset(mod); - } -} - -void bt_mesh_model_reset(void) -{ - bt_mesh_model_foreach(mod_reset, NULL); -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/crypto.c b/src/nimble/nimble/host/mesh/src/crypto.c deleted file mode 100644 index 18f9b1232..000000000 --- a/src/nimble/nimble/host/mesh/src/crypto.c +++ /dev/null @@ -1,609 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG - -#include -#include -#include -#include "syscfg/syscfg.h" - -#if (MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS)) -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#include "mbedtls/cipher.h" -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/cmac.h" -#include "mbedtls/ecdh.h" -#include "mbedtls/ecp.h" - -#else -#include -#include -#include -#include -#include -#endif - -#include "crypto.h" - -#define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4) -#define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4) - -#if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) -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}; - const mbedtls_cipher_info_t *cipher_info; - - mbedtls_cipher_init(&ctx); - - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); - if (cipher_info == NULL) { - goto exit; - } - - if (mbedtls_cipher_setup(&ctx, cipher_info) != 0) { - goto exit; - } - - rc = mbedtls_cipher_cmac_starts(&ctx, key, 128); - if (rc != 0) { - goto exit; - } - - for (; sg_len; sg_len--, sg++) { - if (sg->len != 0 && sg->data != NULL) { - if ((rc = mbedtls_cipher_cmac_update(&ctx, sg->data, sg->len)) != 0) { - goto exit; - } - } - } - rc = mbedtls_cipher_cmac_finish(&ctx, mac); - -exit: - mbedtls_cipher_free(&ctx); - if (rc != 0) { - return -EIO; - } - - return 0; -} - -#else -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; - - if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) { - return -EIO; - } - - for (; sg_len; sg_len--, sg++) { - if (tc_cmac_update(&state, sg->data, - sg->len) == TC_CRYPTO_FAIL) { - return -EIO; - } - } - - if (tc_cmac_final(mac, &state) == TC_CRYPTO_FAIL) { - return -EIO; - } - - return 0; -} -#endif - -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; - - err = bt_mesh_aes_cmac_one(salt, ikm, ikm_len, okm); - if (err < 0) { - return err; - } - - return bt_mesh_aes_cmac_one(okm, info, strlen(info), okm); -} - -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]; - 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)); - BT_DBG("p %s", bt_hex(p, p_len)); - - err = bt_mesh_s1("smk2", salt); - if (err) { - return err; - } - - err = bt_mesh_aes_cmac_one(salt, n, 16, t); - if (err) { - return err; - } - - pad = 0x01; - - sg[0].data = NULL; - sg[0].len = 0; - sg[1].data = p; - sg[1].len = p_len; - sg[2].data = &pad; - sg[2].len = sizeof(pad); - - err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out); - if (err) { - return err; - } - - net_id[0] = out[15] & 0x7f; - - sg[0].data = out; - sg[0].len = sizeof(out); - pad = 0x02; - - err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out); - if (err) { - return err; - } - - memcpy(enc_key, out, 16); - - pad = 0x03; - - err = bt_mesh_aes_cmac(t, sg, ARRAY_SIZE(sg), out); - if (err) { - return err; - } - - memcpy(priv_key, out, 16); - - BT_DBG("NID 0x%02x enc_key %s", net_id[0], bt_hex(enc_key, 16)); - BT_DBG("priv_key %s", bt_hex(priv_key, 16)); - - return 0; -} - -int bt_mesh_k3(const uint8_t n[16], uint8_t out[8]) -{ - uint8_t id64[] = { 'i', 'd', '6', '4', 0x01 }; - uint8_t tmp[16]; - uint8_t t[16]; - int err; - - err = bt_mesh_s1("smk3", tmp); - if (err) { - return err; - } - - err = bt_mesh_aes_cmac_one(tmp, n, 16, t); - if (err) { - return err; - } - - err = bt_mesh_aes_cmac_one(t, id64, sizeof(id64), tmp); - if (err) { - return err; - } - - memcpy(out, tmp + 8, 8); - - return 0; -} - -int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]) -{ - uint8_t id6[] = { 'i', 'd', '6', 0x01 }; - uint8_t tmp[16]; - uint8_t t[16]; - int err; - - err = bt_mesh_s1("smk4", tmp); - if (err) { - return err; - } - - err = bt_mesh_aes_cmac_one(tmp, n, 16, t); - if (err) { - return err; - } - - err = bt_mesh_aes_cmac_one(t, id6, sizeof(id6), tmp); - if (err) { - return err; - } - - out[0] = tmp[15] & BIT_MASK(6); - - return 0; -} - -int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16]) -{ - const char *id128 = "id128\x01"; - uint8_t salt[16]; - int err; - - err = bt_mesh_s1(s, salt); - if (err) { - return err; - } - - return bt_mesh_k1(n, 16, salt, id128, out); -} - -static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu, - uint32_t iv_index) -{ - /* Nonce Type */ - nonce[0] = 0x03; - - /* Pad */ - nonce[1] = 0x00; - - /* Sequence Number */ - nonce[2] = pdu[2]; - nonce[3] = pdu[3]; - nonce[4] = pdu[4]; - - /* Source Address */ - nonce[5] = pdu[5]; - nonce[6] = pdu[6]; - - /* Pad */ - nonce[7] = 0; - nonce[8] = 0; - - /* IV Index */ - sys_put_be32(iv_index, &nonce[9]); -} - -static void create_net_nonce(uint8_t nonce[13], const uint8_t *pdu, - uint32_t iv_index) -{ - /* Nonce Type */ - nonce[0] = 0x00; - - /* FRND + TTL */ - nonce[1] = pdu[1]; - - /* Sequence Number */ - nonce[2] = pdu[2]; - nonce[3] = pdu[3]; - nonce[4] = pdu[4]; - - /* Source Address */ - nonce[5] = pdu[5]; - nonce[6] = pdu[6]; - - /* Pad */ - nonce[7] = 0; - nonce[8] = 0; - - /* IV Index */ - sys_put_be32(iv_index, &nonce[9]); -} - -int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index, - const uint8_t privacy_key[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, - bt_hex(privacy_key, 16)); - - sys_put_be32(iv_index, &priv_rand[5]); - memcpy(&priv_rand[9], &pdu[7], 7); - - BT_DBG("PrivacyRandom %s", bt_hex(priv_rand, 16)); - - err = bt_encrypt_be(privacy_key, priv_rand, tmp); - if (err) { - return err; - } - - for (i = 0; i < 6; i++) { - pdu[1 + i] ^= tmp[i]; - } - - return 0; -} - -int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf, - uint32_t iv_index, bool proxy) -{ - 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, - bt_hex(key, 16), mic_len); - BT_DBG("PDU (len %u) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (IS_ENABLED(CONFIG_BT_MESH_PROXY) && proxy) { - create_proxy_nonce(nonce, buf->om_data, iv_index); - } else { - create_net_nonce(nonce, buf->om_data, iv_index); - } - - BT_DBG("Nonce %s", bt_hex(nonce, 13)); - - 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); - } - - return err; -} - -int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf, - uint32_t iv_index, bool proxy) -{ - 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, - bt_hex(key, 16), mic_len); - - if (IS_ENABLED(CONFIG_BT_MESH_PROXY) && proxy) { - create_proxy_nonce(nonce, buf->om_data, iv_index); - } else { - create_net_nonce(nonce, buf->om_data, iv_index); - } - - BT_DBG("Nonce %s", bt_hex(nonce, 13)); - - buf->om_len -= mic_len; - - 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(uint8_t nonce[13], - const struct bt_mesh_app_crypto_ctx *ctx) -{ - if (ctx->dev_key) { - nonce[0] = 0x02; - } else { - nonce[0] = 0x01; - } - - sys_put_be32((ctx->seq_num | ((uint32_t)ctx->aszmic << 31)), &nonce[1]); - - sys_put_be16(ctx->src, &nonce[5]); - sys_put_be16(ctx->dst, &nonce[7]); - - sys_put_be32(ctx->iv_index, &nonce[9]); -} - -int bt_mesh_app_encrypt(const uint8_t key[16], - const struct bt_mesh_app_crypto_ctx *ctx, - struct os_mbuf *buf) -{ - 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", 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, ctx); - - BT_DBG("Nonce %s", bt_hex(nonce, 13)); - - 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)); - - 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_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; - - BT_DBG("EncData (len %u) %s", buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - create_app_nonce(nonce, ctx); - - BT_DBG("AppKey %s", bt_hex(key, 16)); - BT_DBG("Nonce %s", bt_hex(nonce, 13)); - - 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); - } - - return err; -} - -/* reversed, 8-bit, poly=0x07 */ -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, - 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, - - 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, - 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, - 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, - 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, - - 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, - 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, - 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, - 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, - - 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, - 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, - 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, - 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, - - 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, - 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, - 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, - 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, - - 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, - 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, - 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, - 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, - - 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, - 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, - 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, - 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, - - 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, - 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, - 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, - 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf -}; - -uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len) -{ - uint8_t fcs = 0xff; - - while (data_len--) { - fcs = crc_table[fcs ^ *data++]; - } - - BT_DBG("fcs 0x%02x", 0xff - fcs); - - return 0xff - fcs; -} - -bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs) -{ - 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++]; - } - - return crc_table[fcs ^ received_fcs] == 0xcf; -} - -int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr) -{ - uint8_t salt[16]; - uint8_t tmp[16]; - int err; - - err = bt_mesh_s1("vtad", salt); - if (err) { - return err; - } - - err = bt_mesh_aes_cmac_one(salt, virtual_label, 16, tmp); - if (err) { - return err; - } - - *addr = (sys_get_be16(&tmp[14]) & 0x3fff) | 0x8000; - - return 0; -} - -int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16]) -{ - 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 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 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 } }; - - BT_DBG("ConfirmationKey %s", bt_hex(conf_key, 16)); - BT_DBG("RandomDevice %s", bt_hex(rand, 16)); - BT_DBG("AuthValue %s", bt_hex(auth, 16)); - - return bt_mesh_aes_cmac(conf_key, sg, ARRAY_SIZE(sg), conf); -} - -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_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 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_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 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]) -{ - uint8_t msg[13], tmp[16]; - int err; - - BT_DBG("BeaconKey %s", bt_hex(beacon_key, 16)); - BT_DBG("NetId %s", bt_hex(net_id, 8)); - BT_DBG("IV Index 0x%08x", (unsigned) iv_index); - - msg[0] = flags; - memcpy(&msg[1], net_id, 8); - sys_put_be32(iv_index, &msg[9]); - - BT_DBG("BeaconMsg %s", bt_hex(msg, sizeof(msg))); - - err = bt_mesh_aes_cmac_one(beacon_key, msg, sizeof(msg), tmp); - if (!err) { - memcpy(auth, tmp, 8); - } - - return err; -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/crypto.h b/src/nimble/nimble/host/mesh/src/crypto.h deleted file mode 100644 index 37098301f..000000000 --- a/src/nimble/nimble/host/mesh/src/crypto.h +++ /dev/null @@ -1,171 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __CRYPTO_H__ -#define __CRYPTO_H__ - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -struct bt_mesh_sg { - const void *data; - size_t len; -}; - -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 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, uint8_t salt[16]) -{ - const uint8_t zero[16] = { 0 }; - - return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt); -} - -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 uint8_t salt[16] = salt_str; \ - bt_mesh_k1(ikm, ikm_len, salt, info, okm); \ -}) - -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 uint8_t n[16], uint8_t out[8]); - -int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]); - -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 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 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 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 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 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 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 uint8_t dhkey[32], - const uint8_t prov_salt[16], - uint8_t nonce[13]) -{ - uint8_t tmp[16]; - int err; - - err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp); - if (!err) { - memcpy(nonce, tmp + 3, 13); - } - - return err; -} - -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 uint8_t conf_salt[16], - const uint8_t prov_rand[16], - const uint8_t dev_rand[16], - uint8_t prov_salt[16]) -{ - const uint8_t prov_salt_key[16] = { 0 }; - struct bt_mesh_sg sg[] = { - { conf_salt, 16 }, - { prov_rand, 16 }, - { dev_rand, 16 }, - }; - - return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt); -} - -int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index, - const uint8_t privacy_key[16]); - -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 uint8_t key[16], struct os_mbuf *buf, - uint32_t iv_index, bool proxy); - -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 uint8_t key[16], - const struct bt_mesh_app_crypto_ctx *ctx, - struct os_mbuf *buf); - -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 bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len); - -bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs); - -int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr); - -int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_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(const uint8_t conf_key[16], const uint8_t rand[16], - const uint8_t auth[16], uint8_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_encrypt(const uint8_t key[16], uint8_t nonce[13], - const uint8_t data[25], uint8_t out[25 + 8]); -#endif diff --git a/src/nimble/nimble/host/mesh/src/foundation.h b/src/nimble/nimble/host/mesh/src/foundation.h deleted file mode 100644 index 21734047e..000000000 --- a/src/nimble/nimble/host/mesh/src/foundation.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __FUNDATION_H__ -#define __FUNDATION_H__ - -#define OP_APP_KEY_ADD BT_MESH_MODEL_OP_1(0x00) -#define OP_APP_KEY_UPDATE BT_MESH_MODEL_OP_1(0x01) -#define OP_DEV_COMP_DATA_STATUS BT_MESH_MODEL_OP_1(0x02) -#define OP_MOD_PUB_SET BT_MESH_MODEL_OP_1(0x03) -#define OP_HEALTH_CURRENT_STATUS BT_MESH_MODEL_OP_1(0x04) -#define OP_HEALTH_FAULT_STATUS BT_MESH_MODEL_OP_1(0x05) -#define OP_HEARTBEAT_PUB_STATUS BT_MESH_MODEL_OP_1(0x06) -#define OP_APP_KEY_DEL BT_MESH_MODEL_OP_2(0x80, 0x00) -#define OP_APP_KEY_GET BT_MESH_MODEL_OP_2(0x80, 0x01) -#define OP_APP_KEY_LIST BT_MESH_MODEL_OP_2(0x80, 0x02) -#define OP_APP_KEY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x03) -#define OP_ATTENTION_GET BT_MESH_MODEL_OP_2(0x80, 0x04) -#define OP_ATTENTION_SET BT_MESH_MODEL_OP_2(0x80, 0x05) -#define OP_ATTENTION_SET_UNREL BT_MESH_MODEL_OP_2(0x80, 0x06) -#define OP_ATTENTION_STATUS BT_MESH_MODEL_OP_2(0x80, 0x07) -#define OP_DEV_COMP_DATA_GET BT_MESH_MODEL_OP_2(0x80, 0x08) -#define OP_BEACON_GET BT_MESH_MODEL_OP_2(0x80, 0x09) -#define OP_BEACON_SET BT_MESH_MODEL_OP_2(0x80, 0x0a) -#define OP_BEACON_STATUS BT_MESH_MODEL_OP_2(0x80, 0x0b) -#define OP_DEFAULT_TTL_GET BT_MESH_MODEL_OP_2(0x80, 0x0c) -#define OP_DEFAULT_TTL_SET BT_MESH_MODEL_OP_2(0x80, 0x0d) -#define OP_DEFAULT_TTL_STATUS BT_MESH_MODEL_OP_2(0x80, 0x0e) -#define OP_FRIEND_GET BT_MESH_MODEL_OP_2(0x80, 0x0f) -#define OP_FRIEND_SET BT_MESH_MODEL_OP_2(0x80, 0x10) -#define OP_FRIEND_STATUS BT_MESH_MODEL_OP_2(0x80, 0x11) -#define OP_GATT_PROXY_GET BT_MESH_MODEL_OP_2(0x80, 0x12) -#define OP_GATT_PROXY_SET BT_MESH_MODEL_OP_2(0x80, 0x13) -#define OP_GATT_PROXY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x14) -#define OP_KRP_GET BT_MESH_MODEL_OP_2(0x80, 0x15) -#define OP_KRP_SET BT_MESH_MODEL_OP_2(0x80, 0x16) -#define OP_KRP_STATUS BT_MESH_MODEL_OP_2(0x80, 0x17) -#define OP_MOD_PUB_GET BT_MESH_MODEL_OP_2(0x80, 0x18) -#define OP_MOD_PUB_STATUS BT_MESH_MODEL_OP_2(0x80, 0x19) -#define OP_MOD_PUB_VA_SET BT_MESH_MODEL_OP_2(0x80, 0x1a) -#define OP_MOD_SUB_ADD BT_MESH_MODEL_OP_2(0x80, 0x1b) -#define OP_MOD_SUB_DEL BT_MESH_MODEL_OP_2(0x80, 0x1c) -#define OP_MOD_SUB_DEL_ALL BT_MESH_MODEL_OP_2(0x80, 0x1d) -#define OP_MOD_SUB_OVERWRITE BT_MESH_MODEL_OP_2(0x80, 0x1e) -#define OP_MOD_SUB_STATUS BT_MESH_MODEL_OP_2(0x80, 0x1f) -#define OP_MOD_SUB_VA_ADD BT_MESH_MODEL_OP_2(0x80, 0x20) -#define OP_MOD_SUB_VA_DEL BT_MESH_MODEL_OP_2(0x80, 0x21) -#define OP_MOD_SUB_VA_OVERWRITE BT_MESH_MODEL_OP_2(0x80, 0x22) -#define OP_NET_TRANSMIT_GET BT_MESH_MODEL_OP_2(0x80, 0x23) -#define OP_NET_TRANSMIT_SET BT_MESH_MODEL_OP_2(0x80, 0x24) -#define OP_NET_TRANSMIT_STATUS BT_MESH_MODEL_OP_2(0x80, 0x25) -#define OP_RELAY_GET BT_MESH_MODEL_OP_2(0x80, 0x26) -#define OP_RELAY_SET BT_MESH_MODEL_OP_2(0x80, 0x27) -#define OP_RELAY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x28) -#define OP_MOD_SUB_GET BT_MESH_MODEL_OP_2(0x80, 0x29) -#define OP_MOD_SUB_LIST BT_MESH_MODEL_OP_2(0x80, 0x2a) -#define OP_MOD_SUB_GET_VND BT_MESH_MODEL_OP_2(0x80, 0x2b) -#define OP_MOD_SUB_LIST_VND BT_MESH_MODEL_OP_2(0x80, 0x2c) -#define OP_LPN_TIMEOUT_GET BT_MESH_MODEL_OP_2(0x80, 0x2d) -#define OP_LPN_TIMEOUT_STATUS BT_MESH_MODEL_OP_2(0x80, 0x2e) -#define OP_HEALTH_FAULT_CLEAR BT_MESH_MODEL_OP_2(0x80, 0x2f) -#define OP_HEALTH_FAULT_CLEAR_UNREL BT_MESH_MODEL_OP_2(0x80, 0x30) -#define OP_HEALTH_FAULT_GET BT_MESH_MODEL_OP_2(0x80, 0x31) -#define OP_HEALTH_FAULT_TEST BT_MESH_MODEL_OP_2(0x80, 0x32) -#define OP_HEALTH_FAULT_TEST_UNREL BT_MESH_MODEL_OP_2(0x80, 0x33) -#define OP_HEALTH_PERIOD_GET BT_MESH_MODEL_OP_2(0x80, 0x34) -#define OP_HEALTH_PERIOD_SET BT_MESH_MODEL_OP_2(0x80, 0x35) -#define OP_HEALTH_PERIOD_SET_UNREL BT_MESH_MODEL_OP_2(0x80, 0x36) -#define OP_HEALTH_PERIOD_STATUS BT_MESH_MODEL_OP_2(0x80, 0x37) -#define OP_HEARTBEAT_PUB_GET BT_MESH_MODEL_OP_2(0x80, 0x38) -#define OP_HEARTBEAT_PUB_SET BT_MESH_MODEL_OP_2(0x80, 0x39) -#define OP_HEARTBEAT_SUB_GET BT_MESH_MODEL_OP_2(0x80, 0x3a) -#define OP_HEARTBEAT_SUB_SET BT_MESH_MODEL_OP_2(0x80, 0x3b) -#define OP_HEARTBEAT_SUB_STATUS BT_MESH_MODEL_OP_2(0x80, 0x3c) -#define OP_MOD_APP_BIND BT_MESH_MODEL_OP_2(0x80, 0x3d) -#define OP_MOD_APP_STATUS BT_MESH_MODEL_OP_2(0x80, 0x3e) -#define OP_MOD_APP_UNBIND BT_MESH_MODEL_OP_2(0x80, 0x3f) -#define OP_NET_KEY_ADD BT_MESH_MODEL_OP_2(0x80, 0x40) -#define OP_NET_KEY_DEL BT_MESH_MODEL_OP_2(0x80, 0x41) -#define OP_NET_KEY_GET BT_MESH_MODEL_OP_2(0x80, 0x42) -#define OP_NET_KEY_LIST BT_MESH_MODEL_OP_2(0x80, 0x43) -#define OP_NET_KEY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x44) -#define OP_NET_KEY_UPDATE BT_MESH_MODEL_OP_2(0x80, 0x45) -#define OP_NODE_IDENTITY_GET BT_MESH_MODEL_OP_2(0x80, 0x46) -#define OP_NODE_IDENTITY_SET BT_MESH_MODEL_OP_2(0x80, 0x47) -#define OP_NODE_IDENTITY_STATUS BT_MESH_MODEL_OP_2(0x80, 0x48) -#define OP_NODE_RESET BT_MESH_MODEL_OP_2(0x80, 0x49) -#define OP_NODE_RESET_STATUS BT_MESH_MODEL_OP_2(0x80, 0x4a) -#define OP_SIG_MOD_APP_GET BT_MESH_MODEL_OP_2(0x80, 0x4b) -#define OP_SIG_MOD_APP_LIST BT_MESH_MODEL_OP_2(0x80, 0x4c) -#define OP_VND_MOD_APP_GET BT_MESH_MODEL_OP_2(0x80, 0x4d) -#define OP_VND_MOD_APP_LIST BT_MESH_MODEL_OP_2(0x80, 0x4e) - -#define STATUS_SUCCESS 0x00 -#define STATUS_INVALID_ADDRESS 0x01 -#define STATUS_INVALID_MODEL 0x02 -#define STATUS_INVALID_APPKEY 0x03 -#define STATUS_INVALID_NETKEY 0x04 -#define STATUS_INSUFF_RESOURCES 0x05 -#define STATUS_IDX_ALREADY_STORED 0x06 -#define STATUS_NVAL_PUB_PARAM 0x07 -#define STATUS_NOT_SUB_MOD 0x08 -#define STATUS_STORAGE_FAIL 0x09 -#define STATUS_FEAT_NOT_SUPP 0x0a -#define STATUS_CANNOT_UPDATE 0x0b -#define STATUS_CANNOT_REMOVE 0x0c -#define STATUS_CANNOT_BIND 0x0d -#define STATUS_TEMP_STATE_CHG_FAIL 0x0e -#define STATUS_CANNOT_SET 0x0f -#define STATUS_UNSPECIFIED 0x10 -#define STATUS_INVALID_BINDING 0x11 - -void bt_mesh_model_reset(void); - -void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time); - -static inline void key_idx_pack(struct os_mbuf *buf, - 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, - 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_mem(buf, 3); -} - -#endif diff --git a/src/nimble/nimble/host/mesh/src/friend.c b/src/nimble/nimble/host/mesh/src/friend.c deleted file mode 100644 index a0fad5a39..000000000 --- a/src/nimble/nimble/host/mesh/src/friend.c +++ /dev/null @@ -1,1791 +0,0 @@ - /* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#define MESH_LOG_MODULE BLE_MESH_FRIEND_LOG - -#if MYNEWT_VAL(BLE_MESH_FRIEND) - -#include -#include -#include - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/mesh/include/mesh/slist.h" -#include "mesh_priv.h" -#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. - */ -#define FRIEND_BUF_COUNT ((MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE) + 1) * MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT)) - -static os_membuf_t friend_buf_mem[OS_MEMPOOL_SIZE( - FRIEND_BUF_COUNT, - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; - -struct os_mbuf_pool friend_os_mbuf_pool; -static struct os_mempool friend_buf_mempool; - -#define NET_BUF_FRAGS BIT(0) - -/* PDUs from Friend to the LPN should only be transmitted once with the - * smallest possible interval (20ms). - */ -#define FRIEND_XMIT BT_MESH_TRANSMIT(0, 20) - -struct friend_pdu_info { - uint16_t src; - uint16_t dst; - - uint8_t seq[3]; - - uint8_t ttl:7, - ctl:1; - - uint32_t iv_index; -}; - -static struct friend_adv { - struct bt_mesh_adv adv; - uint16_t app_idx; -} adv_pool[FRIEND_BUF_COUNT]; - -#define FRIEND_ADV(buf) CONTAINER_OF(BT_MESH_ADV(buf), struct friend_adv, adv) - -static struct bt_mesh_adv *adv_alloc(int id) -{ - adv_pool[id].app_idx = BT_MESH_KEY_UNUSED; - return &adv_pool[id].adv; -} - -static bool friend_is_allocated(const struct bt_mesh_friend *frnd) -{ - return frnd->subnet != NULL; -} - -static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr) -{ - if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) { - return false; - } - - return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem)); -} - -struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr, - bool valid, bool established) -{ - int i; - - BT_DBG("net_idx 0x%04x lpn_addr 0x%04x", net_idx, lpn_addr); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - - if (valid && !friend_is_allocated(frnd)) { - continue; - } - - if (established && !frnd->established) { - continue; - } - - if (net_idx != BT_MESH_KEY_ANY && - (!frnd->subnet || frnd->subnet->net_idx != net_idx)) { - continue; - } - - if (is_lpn_unicast(frnd, lpn_addr)) { - return frnd; - } - } - - 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) -{ - while (!net_buf_slist_is_empty(list)) { - struct os_mbuf *buf; - buf = (void *)net_buf_slist_get(list); - BT_MESH_ADV(buf)->frags = NULL; - BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS; - net_buf_unref(buf); - } -} - -/* Intentionally start a little bit late into the ReceiveWindow when - * it's large enough. This may improve reliability with some platforms, - * like the PTS, where the receiver might not have sufficiently compensated - * for internal latencies required to start scanning. - */ -static int32_t recv_delay(struct bt_mesh_friend *frnd) -{ -#if CONFIG_BT_MESH_FRIEND_RECV_WIN > 50 - return (int32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5); -#else - return frnd->recv_delay; -#endif -} - -static void friend_clear(struct bt_mesh_friend *frnd) -{ - int i; - - BT_DBG("LPN 0x%04x", frnd->lpn); - - (void)k_work_cancel_delayable(&frnd->timer); - - memset(frnd->cred, 0, sizeof(frnd->cred)); - - if (frnd->last) { - net_buf_unref(frnd->last); - frnd->last = NULL; - } - - purge_buffers(&frnd->queue); - - for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { - struct bt_mesh_friend_seg *seg = &frnd->seg[i]; - - purge_buffers(&seg->queue); - seg->seg_count = 0U; - } - - frnd->counter++; - frnd->subnet = NULL; - frnd->established = 0; - frnd->pending_buf = 0; - frnd->fsn = 0; - frnd->queue_size = 0; - frnd->pending_req = 0; - memset(frnd->sub_list, 0, sizeof(frnd->sub_list)); -} - -void bt_mesh_friends_clear(void) -{ - int i; - - BT_DBG(""); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - - if (!friend_is_allocated(frnd)) { - continue; - } - - friend_clear(frnd); - } -} - -static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md); - -void bt_mesh_friend_sec_update(uint16_t net_idx) -{ - int i; - - BT_DBG("net_idx 0x%04x", net_idx); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - - if (!friend_is_allocated(frnd)) { - continue; - } - - if (net_idx == BT_MESH_KEY_ANY || - frnd->subnet->net_idx == net_idx) { - enqueue_update(frnd, 0x00); - } - } -} - -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; - uint16_t lpn_addr, lpn_counter; - struct bt_mesh_net_tx tx = { - .sub = rx->sub, - .ctx = &rx->ctx, - .src = bt_mesh_primary_addr(), - .xmit = bt_mesh_net_transmit_get(), - }; - struct bt_mesh_ctl_friend_clear_confirm cfm; - - if (buf->om_len < sizeof(*msg)) { - BT_WARN("Too short Friend Clear"); - return -EINVAL; - } - - lpn_addr = sys_be16_to_cpu(msg->lpn_addr); - lpn_counter = sys_be16_to_cpu(msg->lpn_counter); - - BT_DBG("LPN addr 0x%04x counter 0x%04x", lpn_addr, lpn_counter); - - frnd = bt_mesh_friend_find(rx->sub->net_idx, lpn_addr, false, false); - if (!frnd) { - BT_WARN("No matching LPN addr 0x%04x", lpn_addr); - return 0; - } - - /* A Friend Clear message is considered valid if the result of the - * subtraction of the value of the LPNCounter field of the Friend - * Request message (the one that initiated the friendship) from the - * value of the LPNCounter field of the Friend Clear message, modulo - * 65536, is in the range 0 to 255 inclusive. - */ - if (lpn_counter - frnd->lpn_counter > 255) { - BT_WARN("LPN Counter out of range (old %u new %u)", - frnd->lpn_counter, lpn_counter); - return 0; - } - - tx.ctx->send_ttl = BT_MESH_TTL_MAX; - - cfm.lpn_addr = msg->lpn_addr; - cfm.lpn_counter = msg->lpn_counter; - - bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm, - sizeof(cfm), NULL, NULL); - - friend_clear(frnd); - - return 0; -} - -static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { - if (frnd->sub_list[i] == BT_MESH_ADDR_UNASSIGNED) { - frnd->sub_list[i] = addr; - return; - } - } - - BT_WARN("No space in friend subscription list"); -} - -static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { - if (frnd->sub_list[i] == addr) { - frnd->sub_list[i] = BT_MESH_ADDR_UNASSIGNED; - return; - } - } -} - -static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd, - struct friend_pdu_info *info, - struct os_mbuf *sdu) -{ - struct os_mbuf *buf; - - buf = bt_mesh_adv_create_from_pool(&friend_os_mbuf_pool, adv_alloc, - BT_MESH_ADV_DATA, - FRIEND_XMIT, K_NO_WAIT); - if (!buf) { - return NULL; - } - - net_buf_add_u8(buf, (info->iv_index & 1) << 7); /* Will be reset in encryption */ - - if (info->ctl) { - net_buf_add_u8(buf, info->ttl | 0x80); - } else { - net_buf_add_u8(buf, info->ttl); - } - - net_buf_add_mem(buf, info->seq, sizeof(info->seq)); - - net_buf_add_be16(buf, info->src); - net_buf_add_be16(buf, info->dst); - - net_buf_add_mem(buf, sdu->om_data, sdu->om_len); - - return buf; -} - -struct unseg_app_sdu_meta { - struct bt_mesh_app_crypto_ctx crypto; - const uint8_t *key; - struct bt_mesh_subnet *subnet; - uint8_t aid; -}; - -static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd, - struct os_mbuf *buf, - struct unseg_app_sdu_meta *meta) -{ - uint16_t app_idx = FRIEND_ADV(buf)->app_idx; - struct bt_mesh_net_rx net = { - .ctx = { - .app_idx = app_idx, - .net_idx = frnd->subnet->net_idx, - }, - }; - int err; - - 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; - } - - 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->crypto.ad = NULL; - } - - return 0; -} - -static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd, - struct os_mbuf *buf, - const struct unseg_app_sdu_meta *meta) -{ - struct net_buf_simple_state state; - struct os_mbuf *in = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); - struct os_mbuf *out = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); - int err; - - net_buf_simple_save(buf, &state); - /* Direct the input buffer at the Upper Transport Access PDU, accounting for - * the network header and the 1 byte lower transport header - */ - net_buf_simple_clone(buf, in); - net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN); - net_buf_simple_pull(buf, 1); - in->om_len -= BT_MESH_MIC_SHORT;; - - net_buf_simple_clone(in, out); - err = bt_mesh_app_decrypt(meta->key, &meta->crypto, in, out); - - net_buf_simple_restore(buf, &state); - net_buf_unref(buf); - return err; -} - -static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd, - struct os_mbuf *buf, - const struct unseg_app_sdu_meta *meta) -{ - struct net_buf_simple_state state; - int err; - - BT_DBG(""); - - net_buf_simple_save(buf, &state); - net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN); - net_buf_simple_pull_mem(buf, 1); - buf->om_len -= BT_MESH_MIC_SHORT; - - err = bt_mesh_app_encrypt(meta->key, &meta->crypto, buf); - - net_buf_simple_restore(buf, &state); - return err; -} - -static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, - struct os_mbuf *buf) -{ - struct unseg_app_sdu_meta meta; - int err; - - BT_DBG(""); - - if (FRIEND_ADV(buf)->app_idx == BT_MESH_KEY_UNUSED) { - return 0; - } - - err = unseg_app_sdu_unpack(frnd, buf, &meta); - if (err) { - return err; - } - - /* No need to reencrypt the message if the sequence number is - * unchanged. - */ - if (meta.crypto.seq_num == bt_mesh.seq) { - return 0; - } - - BT_DBG("Re-encrypting friend pdu (SeqNum %06x -> %06x)", - meta.crypto.seq_num, bt_mesh.seq); - - meta.crypto.seq_num = bt_mesh.seq; - - err = unseg_app_sdu_decrypt(frnd, buf, &meta); - if (err) { - BT_WARN("Decryption failed! %d", err); - return err; - } - - meta.crypto.seq_num = bt_mesh.seq; - - err = unseg_app_sdu_encrypt(frnd, buf, &meta); - if (err) { - BT_WARN("Re-encryption failed! %d", err); - } - - return err; -} - -static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf, - bool flooding_cred) -{ - const struct bt_mesh_net_cred *cred; - uint32_t iv_index; - uint16_t src; - int err; - - if (flooding_cred) { - cred = &frnd->subnet->keys[SUBNET_KEY_TX_IDX(frnd->subnet)] - .msg; - } else { - cred = &frnd->cred[SUBNET_KEY_TX_IDX(frnd->subnet)]; - } - - src = sys_get_be16(&buf->om_data[5]); - - if (bt_mesh_has_addr(src)) { - uint32_t seq; - - if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) { - err = unseg_app_sdu_prepare(frnd, buf); - if (err) { - return err; - } - } - - seq = bt_mesh_next_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 { - uint8_t ivi = (buf->om_data[0] >> 7); - iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi)); - } - - buf->om_data[0] = (cred->nid | (iv_index & 1) << 7); - - 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, cred->privacy)) { - BT_ERR("Obfuscating failed"); - return -EINVAL; - } - - return 0; -} - -static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd, - uint8_t ctl_op, - struct os_mbuf *sdu) -{ - struct friend_pdu_info info; - - BT_DBG("LPN 0x%04x", frnd->lpn); - - net_buf_simple_push_u8(sdu, TRANS_CTL_HDR(ctl_op, 0)); - - info.src = bt_mesh_primary_addr(); - info.dst = frnd->lpn; - - info.ctl = 1U; - info.ttl = 0U; - - memset(info.seq, 0, sizeof(info.seq)); - - info.iv_index = BT_MESH_NET_IVI_TX; - - return create_friend_pdu(frnd, &info, sdu); -} - -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 os_mbuf *buf; - - __ASSERT_NO_MSG(friend_is_allocated(frnd)); - - 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(frnd->subnet); - upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index); - upd->md = md; - - buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_UPDATE, sdu); - - os_mbuf_free_chain(sdu); - return buf; -} - -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)); - struct os_mbuf *buf; - - BT_DBG("lpn 0x%04x xact 0x%02x", frnd->lpn, xact); - - net_buf_simple_init(sdu, 1); - - cfm = net_buf_simple_add(sdu, sizeof(*cfm)); - cfm->xact = xact; - - buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_SUB_CFM, sdu); - if (!buf) { - BT_ERR("Unable to encode Subscription List Confirmation"); - goto done; - } - - if (encrypt_friend_pdu(frnd, buf, false)) { - return; - } - - if (frnd->last) { - BT_DBG("Discarding last PDU"); - net_buf_unref(frnd->last); - } - - frnd->last = buf; - frnd->send_last = 1; - -done: - os_mbuf_free_chain(sdu); -} - -static void friend_recv_delay(struct bt_mesh_friend *frnd) -{ - int32_t delay = recv_delay(frnd); - - frnd->pending_req = 1; - k_work_reschedule(&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; - uint8_t xact; - - if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) { - BT_WARN("Too short Friend Subscription Add"); - return -EINVAL; - } - - frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true); - if (!frnd) { - BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr); - return 0; - } - - if (frnd->pending_buf) { - BT_WARN("Previous buffer not yet sent!"); - return 0; - } - - friend_recv_delay(frnd); - - xact = net_buf_simple_pull_u8(buf); - - while (buf->om_len >= 2) { - friend_sub_add(frnd, net_buf_simple_pull_be16(buf)); - } - - enqueue_sub_cfm(frnd, xact); - - return 0; -} - -int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - struct bt_mesh_friend *frnd; - uint8_t xact; - - if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) { - BT_WARN("Too short Friend Subscription Remove"); - return -EINVAL; - } - - frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, true); - if (!frnd) { - BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr); - return 0; - } - - if (frnd->pending_buf) { - BT_WARN("Previous buffer not yet sent!"); - return 0; - } - - friend_recv_delay(frnd); - - xact = net_buf_simple_pull_u8(buf); - - while (buf->om_len >= 2) { - friend_sub_rem(frnd, net_buf_simple_pull_be16(buf)); - } - - enqueue_sub_cfm(frnd, xact); - - return 0; -} - -static void enqueue_buf(struct bt_mesh_friend *frnd, struct os_mbuf *buf) -{ - net_buf_slist_put(&frnd->queue, buf); - frnd->queue_size++; -} - -static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md) -{ - struct os_mbuf *buf; - - buf = encode_update(frnd, md); - if (!buf) { - BT_ERR("Unable to encode Friend Update"); - return; - } - - enqueue_buf(frnd, buf); -} - -int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) -{ - struct bt_mesh_ctl_friend_poll *msg = (void *)buf->om_data; - struct bt_mesh_friend *frnd; - - if (buf->om_len < sizeof(*msg)) { - BT_WARN("Too short Friend Poll"); - return -EINVAL; - } - - frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false); - if (!frnd) { - BT_WARN("No matching LPN addr 0x%04x", rx->ctx.addr); - return 0; - } - - if (msg->fsn & ~1) { - BT_WARN("Prohibited (non-zero) padding bits"); - return -EINVAL; - } - - if (frnd->pending_buf) { - BT_WARN("Previous buffer not yet sent"); - return 0; - } - - BT_DBG("msg->fsn %u frnd->fsn %u", (msg->fsn & 1), frnd->fsn); - - friend_recv_delay(frnd); - - if (!frnd->established) { - BT_DBG("Friendship established with 0x%04x", frnd->lpn); - frnd->established = 1; - } - - if (msg->fsn == frnd->fsn && frnd->last) { - BT_DBG("Re-sending last PDU"); - frnd->send_last = 1; - } else { - if (frnd->last) { - net_buf_unref(frnd->last); - frnd->last = NULL; - } - - frnd->fsn = msg->fsn; - - if (net_buf_slist_is_empty(&frnd->queue)) { - enqueue_update(frnd, 0); - BT_DBG("Enqueued Friend Update to empty queue"); - } - } - - return 0; -} - -static struct bt_mesh_friend *find_clear(uint16_t prev_friend) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - - if (frnd->clear.frnd == prev_friend) { - return frnd; - } - } - - return NULL; -} - -static void friend_clear_sent(int err, void *user_data) -{ - struct bt_mesh_friend *frnd = user_data; - - k_work_reschedule(&frnd->clear.timer, - K_SECONDS(frnd->clear.repeat_sec)); - frnd->clear.repeat_sec *= 2; -} - -static const struct bt_mesh_send_cb clear_sent_cb = { - .end = friend_clear_sent, -}; - -static void send_friend_clear(struct bt_mesh_friend *frnd) -{ - struct bt_mesh_msg_ctx ctx = { - .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 = frnd->subnet, - .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(frnd->lpn), - .lpn_counter = sys_cpu_to_be16(frnd->lpn_counter), - }; - - BT_DBG(""); - - bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req, - 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); - uint32_t duration; - - if (frnd->clear.frnd == BT_MESH_ADDR_UNASSIGNED) { - /* Failed cancelling timer, return early. */ - return; - } - - BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd); - - duration = k_uptime_get_32() - frnd->clear.start; - if (duration > 2 * frnd->poll_to) { - BT_DBG("Clear Procedure timer expired"); - frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED; - return; - } - - send_friend_clear(frnd); -} - -static void clear_procedure_start(struct bt_mesh_friend *frnd) -{ - BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd); - - frnd->clear.start = k_uptime_get_32(); - frnd->clear.repeat_sec = 1U; - - send_friend_clear(frnd); -} - -int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data; - struct bt_mesh_friend *frnd; - uint16_t lpn_addr, lpn_counter; - - BT_DBG(""); - - if (buf->om_len < sizeof(*msg)) { - BT_WARN("Too short Friend Clear Confirm"); - return -EINVAL; - } - - frnd = find_clear(rx->ctx.addr); - if (!frnd) { - BT_WARN("No pending clear procedure for 0x%02x", rx->ctx.addr); - return 0; - } - - lpn_addr = sys_be16_to_cpu(msg->lpn_addr); - if (lpn_addr != frnd->lpn) { - BT_WARN("LPN address mismatch (0x%04x != 0x%04x)", - lpn_addr, frnd->lpn); - return 0; - } - - lpn_counter = sys_be16_to_cpu(msg->lpn_counter); - if (lpn_counter != frnd->lpn_counter) { - BT_WARN("LPN counter mismatch (0x%04x != 0x%04x)", - lpn_counter, frnd->lpn_counter); - return 0; - } - - /* If this fails, the unassigned check will make the handler return early. */ - (void)k_work_cancel_delayable(&frnd->clear.timer); - frnd->clear.frnd = BT_MESH_ADDR_UNASSIGNED; - - return 0; -} - -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)); - struct os_mbuf *buf; - - BT_DBG(""); - - net_buf_simple_init(sdu, 1); - - off = net_buf_simple_add(sdu, sizeof(*off)); - - off->recv_win = CONFIG_BT_MESH_FRIEND_RECV_WIN, - off->queue_size = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE, - off->sub_list_size = ARRAY_SIZE(frnd->sub_list), - off->rssi = rssi, - off->frnd_counter = sys_cpu_to_be16(frnd->counter); - - buf = encode_friend_ctl(frnd, TRANS_CTL_OP_FRIEND_OFFER, sdu); - if (!buf) { - BT_ERR("Unable to encode Friend Offer"); - goto done; - } - - if (encrypt_friend_pdu(frnd, buf, true)) { - goto done; - } - - if (frnd->last) { - net_buf_unref(frnd->last); - } - - frnd->last = buf; - frnd->send_last = 1; - -done: - os_mbuf_free_chain(sdu); -} - -#define RECV_WIN CONFIG_BT_MESH_FRIEND_RECV_WIN -#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 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 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 = (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); - - 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; - 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"); - return -EINVAL; - } - - if (msg->recv_delay <= 0x09) { - BT_WARN("Prohibited ReceiveDelay (0x%02x)", msg->recv_delay); - return -EINVAL; - } - - poll_to = sys_get_be24(msg->poll_to); - - if (poll_to <= 0x000009 || poll_to >= 0x34bc00) { - BT_WARN("Prohibited PollTimeout (0x%06x)", (unsigned) poll_to); - return -EINVAL; - } - - if (msg->num_elem == 0x00) { - BT_WARN("Prohibited NumElements value (0x00)"); - return -EINVAL; - } - - if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr + msg->num_elem - 1)) { - BT_WARN("LPN elements stretch outside of unicast range"); - return -EINVAL; - } - - if (!MIN_QUEUE_SIZE_LOG(msg->criteria)) { - BT_WARN("Prohibited Minimum Queue Size in Friend Request"); - return -EINVAL; - } - - if (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE < MIN_QUEUE_SIZE(msg->criteria)) { - BT_WARN("We have a too small Friend Queue size (%u < %u)", - CONFIG_BT_MESH_FRIEND_QUEUE_SIZE, - (unsigned) MIN_QUEUE_SIZE(msg->criteria)); - return 0; - } - - frnd = bt_mesh_friend_find(rx->sub->net_idx, rx->ctx.addr, true, false); - if (frnd) { - BT_WARN("Existing LPN re-requesting Friendship"); - friend_clear(frnd); - goto init_friend; - } - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - if (!bt_mesh.frnd[i].subnet) { - frnd = &bt_mesh.frnd[i]; - break; - } - } - - if (!frnd) { - BT_WARN("No free Friend contexts for new LPN"); - return -ENOMEM; - } - -init_friend: - frnd->lpn = rx->ctx.addr; - frnd->num_elem = msg->num_elem; - 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); - - if (BT_MESH_ADDR_IS_UNICAST(frnd->clear.frnd) && - !bt_mesh_has_addr(frnd->clear.frnd)) { - clear_procedure_start(frnd); - } - - delay = offer_delay(frnd, rx->ctx.recv_rssi, msg->criteria); - k_work_reschedule(&frnd->timer, K_MSEC(delay)); - - enqueue_offer(frnd, rx->ctx.recv_rssi); - - return 0; -} - -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; - uint16_t buf_seq_zero; - uint16_t buf_src; - - if (!buf) { - return false; - } - - net_buf_simple_save(buf, &state); - net_buf_skip(buf, 5); /* skip IVI, NID, CTL, TTL, SEQ */ - buf_src = net_buf_pull_be16(buf); - net_buf_skip(buf, 3); /* skip DST, OP/AID */ - buf_seq_zero = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK); - net_buf_simple_restore(buf, &state); - - return ((src == buf_src) && (seq_zero == buf_seq_zero)); -} - -static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, - uint16_t src, uint16_t seq_zero, - uint8_t seg_count) -{ - struct bt_mesh_friend_seg *unassigned = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { - struct bt_mesh_friend_seg *seg = &frnd->seg[i]; - - if (is_seg(seg, src, seq_zero)) { - return seg; - } - - if (!unassigned && !net_buf_slist_peek_head(&seg->queue)) { - unassigned = seg; - } - } - - if (unassigned) { - unassigned->seg_count = seg_count; - } - - return unassigned; -} - -static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, - enum bt_mesh_friend_pdu_type type, - uint16_t src, uint8_t seg_count, - struct os_mbuf *buf) -{ - struct bt_mesh_friend_seg *seg; - - BT_DBG("type %u", type); - - if (type == BT_MESH_FRIEND_PDU_SINGLE) { - enqueue_buf(frnd, buf); - return; - } - - 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) { - BT_ERR("No free friend segment RX contexts for 0x%04x", src); - net_buf_unref(buf); - return; - } - - net_buf_slist_put(&seg->queue, buf); - - if (type == BT_MESH_FRIEND_PDU_COMPLETE) { - net_buf_slist_merge_slist(&frnd->queue, &seg->queue); - - frnd->queue_size += seg->seg_count; - seg->seg_count = 0U; - } else { - /* Mark the buffer as having more to come after it */ - BT_MESH_ADV(buf)->flags |= NET_BUF_FRAGS; - } -} - -static void buf_send_start(uint16_t duration, int err, void *user_data) -{ - struct bt_mesh_friend *frnd = user_data; - - BT_DBG("err %d", err); - - frnd->pending_buf = 0; - - /* Friend Offer doesn't follow the re-sending semantics */ - if (!frnd->established && frnd->last) { - net_buf_unref(frnd->last); - frnd->last = NULL; - } -} - -static void buf_send_end(int err, void *user_data) -{ - struct bt_mesh_friend *frnd = user_data; - - BT_DBG("err %d", err); - - if (frnd->pending_req) { - BT_WARN("Another request before previous completed sending"); - return; - } - - if (frnd->established) { - /* Always restart poll timeout timer after sending */ - k_work_reschedule(&frnd->timer, K_MSEC(frnd->poll_to)); - BT_DBG("Waiting %u ms for next poll", - (unsigned) frnd->poll_to); - } else { - /* Friend offer timeout is 1 second */ - k_work_reschedule(&frnd->timer, K_SECONDS(1)); - BT_DBG("Waiting for first poll"); - } -} - -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); - static const struct bt_mesh_send_cb buf_sent_cb = { - .start = buf_send_start, - .end = buf_send_end, - }; - struct os_mbuf *buf; - uint8_t md; - - if (!friend_is_allocated(frnd)) { - return; - } - - __ASSERT_NO_MSG(frnd->pending_buf == 0); - - BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn, - frnd->send_last, frnd->last); - - if (frnd->send_last && frnd->last) { - BT_DBG("Sending frnd->last %p", frnd->last); - frnd->send_last = 0; - goto send_last; - } - - if (frnd->established && !frnd->pending_req) { - BT_WARN("Friendship lost with 0x%04x", frnd->lpn); - friend_clear(frnd); - return; - } - - frnd->last = (void *)net_buf_slist_get(&frnd->queue); - if (!frnd->last) { - BT_WARN("Friendship not established with 0x%04x", - frnd->lpn); - friend_clear(frnd); - 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)->frags = NULL; - - BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x", - frnd->last, frnd->lpn); - frnd->queue_size--; - -send_last: - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, FRIEND_XMIT, K_NO_WAIT); - if (!buf) { - BT_ERR("Unable to allocate friend adv buffer"); - return; - } - - net_buf_add_mem(buf, frnd->last->om_data, frnd->last->om_len); - frnd->pending_req = 0; - frnd->pending_buf = 1; - bt_mesh_adv_send(buf, &buf_sent_cb, frnd); - net_buf_unref(buf); -} - -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; - - rc = os_mempool_init(&friend_buf_mempool, FRIEND_BUF_COUNT, - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, - friend_buf_mem, "friend_buf_pool"); - assert(rc == 0); - - rc = os_mbuf_pool_init(&friend_os_mbuf_pool, &friend_buf_mempool, - BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE, - FRIEND_BUF_COUNT); - assert(rc == 0); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - int j; - - net_buf_slist_init(&frnd->queue); - - k_work_init_delayable(&frnd->timer, friend_timeout); - k_work_add_arg_delayable(&frnd->timer, frnd); - k_work_init_delayable(&frnd->clear.timer, clear_timeout); - k_work_add_arg_delayable(&frnd->clear.timer, frnd); - - for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) { - net_buf_slist_init(&frnd->seg[j].queue); - } - } - - return 0; -} - -static bool is_segack(struct os_mbuf *buf, uint64_t *seqauth, uint16_t src) -{ - struct net_buf_simple_state state; - bool found = false; - - if (buf->om_len != 16) { - return false; - } - - 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_pull(buf, 3); /* skip SEQNUM */ - - if (src != net_buf_pull_be16(buf)) { - goto end; - } - - net_buf_skip(buf, 2); /* skip dst */ - - if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) { - goto end; - } - - found = ((net_buf_pull_be16(buf) >> 2) & TRANS_SEQ_ZERO_MASK) == - (*seqauth & TRANS_SEQ_ZERO_MASK); -end: - net_buf_simple_restore(buf, &state); - return found; -} - -static void friend_purge_old_ack(struct bt_mesh_friend *frnd, uint64_t *seq_auth, - uint16_t src) -{ - struct os_mbuf *cur, *prev = NULL; - - BT_DBG("SeqAuth %llx src 0x%04x", *seq_auth, src); - - for (cur = net_buf_slist_peek_head(&frnd->queue); - cur != NULL; prev = cur, cur = net_buf_slist_peek_next(cur)) { - struct os_mbuf *buf = (void *)cur; - - if (is_segack(buf, seq_auth, src)) { - BT_DBG("Removing old ack from Friend Queue"); - - net_buf_slist_remove(&frnd->queue, prev, cur); - frnd->queue_size--; - /* Make sure old slist entry state doesn't remain */ - BT_MESH_ADV(buf)->frags = NULL; - net_buf_unref(buf); - break; - } - } -} - -static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, - struct bt_mesh_net_rx *rx, - enum bt_mesh_friend_pdu_type type, - uint64_t *seq_auth, uint8_t seg_count, - struct os_mbuf *sbuf) -{ - struct friend_pdu_info info; - struct os_mbuf *buf; - - /* Because of network loopback, tx packets will also be passed into - * this rx function. These packets have already been added to the - * queue, and should be ignored. - */ - if (bt_mesh_has_addr(rx->ctx.addr)) { - return; - } - - BT_DBG("LPN 0x%04x queue_size %u", frnd->lpn, - (unsigned) frnd->queue_size); - - if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) { - friend_purge_old_ack(frnd, seq_auth, rx->ctx.addr); - } - - info.src = rx->ctx.addr; - info.dst = rx->ctx.recv_dst; - - if (rx->net_if == BT_MESH_NET_IF_LOCAL) { - info.ttl = rx->ctx.recv_ttl; - } else { - info.ttl = rx->ctx.recv_ttl - 1; - } - - info.ctl = rx->ctl; - - sys_put_be24(rx->seq, info.seq); - - info.iv_index = BT_MESH_NET_IVI_RX(rx); - - buf = create_friend_pdu(frnd, &info, sbuf); - if (!buf) { - BT_ERR("Failed to encode Friend buffer"); - return; - } - - enqueue_friend_pdu(frnd, type, info.src, seg_count, buf); - - BT_DBG("Queued message for LPN 0x%04x, queue_size %u", - frnd->lpn, (unsigned) frnd->queue_size); -} - -static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, - struct bt_mesh_net_tx *tx, - enum bt_mesh_friend_pdu_type type, - uint64_t *seq_auth, uint8_t seg_count, - struct os_mbuf *sbuf) -{ - struct friend_pdu_info info; - struct os_mbuf *buf; - - BT_DBG("LPN 0x%04x", frnd->lpn); - - if (type == BT_MESH_FRIEND_PDU_SINGLE && seq_auth) { - friend_purge_old_ack(frnd, seq_auth, tx->src); - } - - info.src = tx->src; - info.dst = tx->ctx->addr; - - info.ttl = tx->ctx->send_ttl; - info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED); - - sys_put_be24(bt_mesh.seq, info.seq); - - info.iv_index = BT_MESH_NET_IVI_TX; - - buf = create_friend_pdu(frnd, &info, sbuf); - if (!buf) { - BT_ERR("Failed to encode Friend buffer"); - return; - } - - if (type == BT_MESH_FRIEND_PDU_SINGLE && !info.ctl) { - /* Unsegmented application packets may be reencrypted later, - * as they depend on the the sequence number being the same - * when encrypting in transport and network. - */ - FRIEND_ADV(buf)->app_idx = tx->ctx->app_idx; - } - - enqueue_friend_pdu(frnd, type, info.src, seg_count, buf); - - BT_DBG("Queued message for LPN 0x%04x", frnd->lpn); -} - -static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx, - uint16_t addr) -{ - int i; - - if (!frnd->established) { - return false; - } - - if (net_idx != frnd->subnet->net_idx) { - return false; - } - - if (BT_MESH_ADDR_IS_UNICAST(addr)) { - return is_lpn_unicast(frnd, addr); - } - - for (i = 0; i < ARRAY_SIZE(frnd->sub_list); i++) { - if (frnd->sub_list[i] == addr) { - return true; - } - } - - return false; -} - -bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - - if (friend_lpn_matches(frnd, net_idx, addr)) { - BT_DBG("LPN 0x%04x matched address 0x%04x", - frnd->lpn, addr); - return true; - } - } - - BT_DBG("No matching LPN for address 0x%04x", addr); - - return false; -} - -static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr, - uint64_t *seq_auth, uint8_t seg_count) -{ - uint32_t total = 0; - int i; - - if (seg_count > CONFIG_BT_MESH_FRIEND_QUEUE_SIZE) { - return false; - } - - for (i = 0; i < ARRAY_SIZE(frnd->seg); i++) { - struct bt_mesh_friend_seg *seg = &frnd->seg[i]; - - if (seq_auth && is_seg(seg, addr, *seq_auth & TRANS_SEQ_ZERO_MASK)) { - /* If there's a segment queue for this message then the - * space verification has already happened. - */ - return true; - } - - total += seg->seg_count; - } - - /* If currently pending segments combined with this segmented message - * are more than the Friend Queue Size, then there's no space. This - * is because we don't have a mechanism of aborting already pending - * segmented messages to free up buffers. - */ - return (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - total) > 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; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - - if (!friend_lpn_matches(frnd, net_idx, dst)) { - continue; - } - - friend_match = true; - - if (friend_queue_has_space(frnd, src, seq_auth, seg_count)) { - someone_has_space = true; - } - } - - /* If there were no matched LPNs treat this as success, so the - * transport layer can continue its work. - */ - if (!friend_match) { - return true; - } - - /* From the transport layers perspective it's good enough that at - * least one Friend Queue has space. If there were multiple Friend - * matches then the destination must be a group address, in which - * case e.g. segment acks are not sent. - */ - return someone_has_space; -} - -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; - uint8_t avail_space; - - if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) { - return false; - } - - avail_space = CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - frnd->queue_size; - pending_segments = false; - - while (pending_segments || avail_space < seg_count) { - struct os_mbuf *buf = (void *)net_buf_slist_get(&frnd->queue); - - if (!buf) { - BT_ERR("Unable to free up enough buffers"); - return false; - } - - frnd->queue_size--; - avail_space++; - - pending_segments = (BT_MESH_ADV(buf)->flags & NET_BUF_FRAGS); - BT_DBG("PENDING SEGMENTS %d", pending_segments); - - /* Make sure old slist entry state doesn't remain */ - BT_MESH_ADV(buf)->frags = NULL; - BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS; - - net_buf_unref(buf); - } - - return true; -} - -void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, - enum bt_mesh_friend_pdu_type type, - uint64_t *seq_auth, uint8_t seg_count, - struct os_mbuf *sbuf) -{ - int i; - - if (!rx->friend_match || - (rx->ctx.recv_ttl <= 1 && rx->net_if != BT_MESH_NET_IF_LOCAL) || - bt_mesh_friend_get() != BT_MESH_FRIEND_ENABLED) { - return; - } - - BT_DBG("recv_ttl %u net_idx 0x%04x src 0x%04x dst 0x%04x", - rx->ctx.recv_ttl, rx->sub->net_idx, rx->ctx.addr, - rx->ctx.recv_dst); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - - if (!friend_lpn_matches(frnd, rx->sub->net_idx, - rx->ctx.recv_dst)) { - continue; - } - - if (friend_lpn_matches(frnd, rx->sub->net_idx, - rx->ctx.addr)) { - 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; - } - - friend_lpn_enqueue_rx(frnd, rx, type, seq_auth, seg_count, - sbuf); - } -} - -bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx, - enum bt_mesh_friend_pdu_type type, - uint64_t *seq_auth, uint8_t seg_count, - struct os_mbuf *sbuf) -{ - bool matched = false; - int i; - - if (!bt_mesh_friend_match(tx->sub->net_idx, tx->ctx->addr) || - bt_mesh_friend_get() != BT_MESH_FRIEND_ENABLED) { - return matched; - } - - BT_DBG("net_idx 0x%04x dst 0x%04x src 0x%04x", tx->sub->net_idx, - tx->ctx->addr, tx->src); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - - if (!friend_lpn_matches(frnd, tx->sub->net_idx, - tx->ctx->addr)) { - continue; - } - - if (!friend_queue_prepare_space(frnd, tx->src, seq_auth, - seg_count)) { - continue; - } - - friend_lpn_enqueue_tx(frnd, tx, type, seq_auth, seg_count, - sbuf); - matched = true; - } - - return matched; -} - -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; - - BT_DBG(""); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - int j; - - if (!friend_lpn_matches(frnd, sub->net_idx, dst)) { - continue; - } - - for (j = 0; j < ARRAY_SIZE(frnd->seg); j++) { - struct bt_mesh_friend_seg *seg = &frnd->seg[j]; - - if (!is_seg(seg, src, *seq_auth & TRANS_SEQ_ZERO_MASK)) { - continue; - } - - BT_WARN("Clearing incomplete segments for 0x%04x", src); - - purge_buffers(&seg->queue); - seg->seg_count = 0U; - break; - } - } -} - -#endif /* MYNEWT_VAL(BLE_MESH_FRIEND) */ diff --git a/src/nimble/nimble/host/mesh/src/friend.h b/src/nimble/nimble/host/mesh/src/friend.h deleted file mode 100644 index 9e79f966a..000000000 --- a/src/nimble/nimble/host/mesh/src/friend.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __FRIEND_H__ -#define __FRIEND_H__ - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -enum bt_mesh_friend_pdu_type { - BT_MESH_FRIEND_PDU_SINGLE, - BT_MESH_FRIEND_PDU_PARTIAL, - BT_MESH_FRIEND_PDU_COMPLETE, -}; - -bool bt_mesh_friend_match(uint16_t net_idx, uint16_t 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(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, - 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, - uint64_t *seq_auth, uint8_t seg_count, - struct os_mbuf *sbuf); - -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(uint16_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); -int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); -int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf); -int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf); -int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf); - -int bt_mesh_friend_init(void); - -#endif diff --git a/src/nimble/nimble/host/mesh/src/glue.c b/src/nimble/nimble/host/mesh/src/glue.c deleted file mode 100644 index 97dfcf4d6..000000000 --- a/src/nimble/nimble/host/mesh/src/glue.c +++ /dev/null @@ -1,1041 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) -#define MESH_LOG_MODULE BLE_MESH_LOG - -#include "nimble/nimble/host/mesh/include/mesh/glue.h" -#include "adv.h" -#include "nimble/nimble/host/src/ble_hs_conn_priv.h" -#ifndef MYNEWT -#include "nimble/porting/nimble/include/nimble/nimble_port.h" -#endif - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -#include "base64/base64.h" -#endif - -extern uint8_t g_mesh_addr_type; - -#if MYNEWT_VAL(BLE_EXT_ADV) -/* Store configuration for different bearers */ -#define BT_MESH_ADV_IDX (0) -#define BT_MESH_GATT_IDX (1) -static struct ble_gap_adv_params ble_adv_cur_conf[2]; -#endif - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - -const char * -bt_hex(const void *buf, size_t len) -{ - static const char hex[] = "0123456789abcdef"; - static char hexbufs[4][137]; - static uint8_t curbuf; - const uint8_t *b = buf; - char *str; - int i; - - str = hexbufs[curbuf++]; - curbuf %= ARRAY_SIZE(hexbufs); - - len = MIN(len, (sizeof(hexbufs[0]) - 1) / 2); - - for (i = 0; i < len; i++) { - str[i * 2] = hex[b[i] >> 4]; - str[i * 2 + 1] = hex[b[i] & 0xf]; - } - - str[i * 2] = '\0'; - - return str; -} - -void -net_buf_put(struct ble_npl_eventq *fifo, struct os_mbuf *om) -{ - struct ble_npl_event *ev; - - assert(OS_MBUF_IS_PKTHDR(om)); - ev = &BT_MESH_ADV(om)->ev; - assert(ev); - assert(ble_npl_event_get_arg(ev)); - - ble_npl_eventq_put(fifo, ev); -} - -void * -net_buf_ref(struct os_mbuf *om) -{ - struct bt_mesh_adv *adv; - - /* For bufs with header we count refs*/ - if (OS_MBUF_USRHDR_LEN(om) == 0) { - return om; - } - - adv = BT_MESH_ADV(om); - adv->ref_cnt++; - - return om; -} - -void -net_buf_unref(struct os_mbuf *om) -{ - struct bt_mesh_adv *adv; - - /* For bufs with header we count refs*/ - if (OS_MBUF_USRHDR_LEN(om) == 0) { - goto free; - } - - adv = BT_MESH_ADV(om); - if (adv->started && adv->cb && adv->cb->end) { - adv->cb->end(0, adv->cb_data); - } - - if (--adv->ref_cnt > 0) { - return; - } - -free: - os_mbuf_free_chain(om); -} - -void net_buf_simple_clone(const struct os_mbuf *original, - struct os_mbuf *clone) -{ - memcpy(clone, original, sizeof(struct os_mbuf)); -} - - -#if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) -int -bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data) -{ - mbedtls_aes_context s = {0}; - mbedtls_aes_init(&s); - - if (mbedtls_aes_setkey_enc(&s, key, 128) != 0) { - mbedtls_aes_free(&s); - return BLE_HS_EUNKNOWN; - } - - if (mbedtls_aes_crypt_ecb(&s, MBEDTLS_AES_ENCRYPT, plaintext, enc_data) != 0) { - mbedtls_aes_free(&s); - return BLE_HS_EUNKNOWN; - } - - mbedtls_aes_free(&s); - return 0; -} - -#else -int -bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data) -{ - struct tc_aes_key_sched_struct s = {0}; - - if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) { - return BLE_HS_EUNKNOWN; - } - - if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) { - return BLE_HS_EUNKNOWN; - } - - return 0; -} -#endif - -uint16_t -net_buf_simple_pull_le16(struct os_mbuf *om) -{ - uint16_t val; - struct os_mbuf *old = om; - - om = os_mbuf_pullup(om, sizeof(val)); - assert(om == old); - val = get_le16(om->om_data); - os_mbuf_adj(om, sizeof(val)); - - return val; -} - -uint32_t -net_buf_simple_pull_le24(struct os_mbuf *om) -{ - uint32_t val; - struct os_mbuf *old = om; - - om = os_mbuf_pullup(om, 3); - assert(om == old); - val = get_le24(om->om_data); - os_mbuf_adj(om, 3); - - return val; -} - -uint16_t -net_buf_simple_pull_be16(struct os_mbuf *om) -{ - uint16_t val; - struct os_mbuf *old = om; - - om = os_mbuf_pullup(om, sizeof(val)); - assert(om == old); - val = get_be16(om->om_data); - os_mbuf_adj(om, sizeof(val)); - - return val; -} - -uint32_t -net_buf_simple_pull_be32(struct os_mbuf *om) -{ - uint32_t val; - struct os_mbuf *old = om; - - om = os_mbuf_pullup(om, sizeof(val)); - assert(om == old); - val = get_be32(om->om_data); - os_mbuf_adj(om, sizeof(val)); - - return val; -} - -uint32_t -net_buf_simple_pull_le32(struct os_mbuf *om) -{ - uint32_t val; - struct os_mbuf *old = om; - - om = os_mbuf_pullup(om, sizeof(val)); - assert(om == old); - val = get_le32(om->om_data); - os_mbuf_adj(om, sizeof(val)); - - return val; -} - -uint8_t -net_buf_simple_pull_u8(struct os_mbuf *om) -{ - uint8_t val; - struct os_mbuf *old = om; - - om = os_mbuf_pullup(om, sizeof(val)); - assert(om == old); - val = om->om_data[0]; - os_mbuf_adj(om, 1); - - return val; -} - -void -net_buf_simple_add_le16(struct os_mbuf *om, uint16_t val) -{ - val = htole16(val); - os_mbuf_append(om, &val, sizeof(val)); - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val) -{ - val = htobe16(val); - os_mbuf_append(om, &val, sizeof(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) -{ - val = htobe32(val); - os_mbuf_append(om, &val, sizeof(val)); - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_simple_add_le32(struct os_mbuf *om, uint32_t val) -{ - val = htole32(val); - os_mbuf_append(om, &val, sizeof(val)); - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_simple_add_u8(struct os_mbuf *om, uint8_t val) -{ - os_mbuf_append(om, &val, 1); - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_simple_push_le16(struct os_mbuf *om, uint16_t val) -{ - uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len]; - - assert(headroom >= 2); - om->om_data -= 2; - put_le16(om->om_data, val); - om->om_len += 2; - - if (om->om_pkthdr_len) { - OS_MBUF_PKTHDR(om)->omp_len += 2; - } - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val) -{ - uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len]; - - assert(headroom >= 2); - om->om_data -= 2; - put_be16(om->om_data, val); - om->om_len += 2; - - if (om->om_pkthdr_len) { - OS_MBUF_PKTHDR(om)->omp_len += 2; - } - 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) -{ - uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len]; - - assert(headroom >= 1); - om->om_data -= 1; - om->om_data[0] = val; - om->om_len += 1; - - if (om->om_pkthdr_len) { - OS_MBUF_PKTHDR(om)->omp_len += 1; - } - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_add_zeros(struct os_mbuf *om, uint8_t len) -{ - uint8_t z[len]; - int rc; - - memset(z, 0, len); - - rc = os_mbuf_append(om, z, len); - if(rc) { - assert(0); - } - ASSERT_NOT_CHAIN(om); -} - -void * -net_buf_simple_pull(struct os_mbuf *om, uint8_t len) -{ - os_mbuf_adj(om, len); - return om->om_data; -} - -void * -net_buf_simple_pull_mem(struct os_mbuf *om, uint8_t len) -{ - void *data = om->om_data; - - net_buf_simple_pull(om, len); - return data; -} - -void* -net_buf_simple_add(struct os_mbuf *om, uint8_t len) -{ - void * tmp; - - tmp = os_mbuf_extend(om, len); - ASSERT_NOT_CHAIN(om); - - return tmp; -} - -bool -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, int32_t t) -{ - struct ble_npl_event *ev = ble_npl_eventq_get(fifo, 0); - - if (ev) { - return ble_npl_event_get_arg(ev); - } - - return NULL; -} - -uint8_t * -net_buf_simple_push(struct os_mbuf *om, uint8_t len) -{ - uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len]; - - assert(headroom >= len); - om->om_data -= len; - om->om_len += len; - - return om->om_data; -} - -void -net_buf_reserve(struct os_mbuf *om, size_t reserve) -{ - /* We need reserve to be done on fresh buf */ - assert(om->om_len == 0); - om->om_data += reserve; -} - -void -k_work_init(struct ble_npl_callout *work, ble_npl_event_fn handler) -{ -#ifndef MYNEWT - ble_npl_callout_init(work, nimble_port_get_dflt_eventq(), handler, NULL); -#else - ble_npl_callout_init(work, ble_npl_eventq_dflt_get(), handler, NULL); -#endif -} - -void -k_work_init_delayable(struct k_work_delayable *w, ble_npl_event_fn *f) -{ -#ifndef MYNEWT - ble_npl_callout_init(&w->work, nimble_port_get_dflt_eventq(), f, NULL); -#else - ble_npl_callout_init(&w->work, ble_npl_eventq_dflt_get(), f, NULL); -#endif -} - -bool -k_work_delayable_is_pending(struct k_work_delayable *w) -{ - return ble_npl_callout_is_active(&w->work); -} - -void -k_work_cancel_delayable(struct k_work_delayable *w) -{ - ble_npl_callout_stop(&w->work); -} - -void -k_work_schedule(struct k_work_delayable *w, uint32_t ms) -{ - uint32_t ticks; - - if (ble_npl_time_ms_to_ticks(ms, &ticks) != 0) { - assert(0); - } - ble_npl_callout_reset(&w->work, ticks); -} - -void -k_work_reschedule(struct k_work_delayable *w, uint32_t ms) -{ - uint32_t ticks; - - if (ble_npl_time_ms_to_ticks(ms, &ticks) != 0) { - assert(0); - } - ble_npl_callout_reset(&w->work, ticks); -} - -void -k_work_submit(struct ble_npl_callout *w) -{ - ble_npl_callout_reset(w, 0); -} - -void -k_work_add_arg(struct ble_npl_callout *w, void *arg) -{ - ble_npl_callout_set_arg(w, arg); -} - -void -k_work_add_arg_delayable(struct k_work_delayable *w, void *arg) -{ - k_work_add_arg(&w->work, arg); -} - -ble_npl_time_t -k_work_delayable_remaining_get (struct k_work_delayable *w) -{ - int sr; - ble_npl_time_t t; - - OS_ENTER_CRITICAL(sr); - - t = ble_npl_callout_remaining_ticks(&w->work, ble_npl_time_get()); - - OS_EXIT_CRITICAL(sr); - - return t; -} - -uint32_t -k_ticks_to_ms_floor32(ble_npl_time_t ticks) -{ - return ble_npl_time_ticks_to_ms32(ticks); -} - -int64_t k_uptime_get(void) -{ - /* We should return ms */ - return ble_npl_time_ticks_to_ms32(ble_npl_time_get()); -} - -uint32_t k_uptime_get_32(void) -{ - return k_uptime_get(); -} - -int64_t k_uptime_delta(int64_t *reftime) -{ - int64_t uptime, delta; - - uptime = k_uptime_get(); - delta = uptime - *reftime; - *reftime = uptime; - - return delta; -} - -void k_sleep(int32_t duration) -{ - uint32_t ticks; - - ticks = ble_npl_time_ms_to_ticks32(duration); - - ble_npl_time_delay(ticks); -} - -static uint8_t pub[64]; -static uint8_t priv[32]; -static bool has_pub = false; - -int -bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb) -{ - uint8_t dh[32]; - - if (ble_sm_alg_gen_dhkey((uint8_t *)&remote_pk[0], (uint8_t *)&remote_pk[32], - priv, dh)) { - return -1; - } - - cb(dh); - return 0; -} - -void -bt_conn_get_info(struct ble_hs_conn *conn, - struct ble_gap_conn_desc *desc) -{ - struct ble_hs_conn_addrs addrs; - - ble_hs_conn_addrs(conn, &addrs); - - desc->our_id_addr = addrs.our_id_addr; - desc->peer_id_addr = addrs.peer_id_addr; - desc->our_ota_addr = addrs.our_ota_addr; - desc->peer_ota_addr = addrs.peer_ota_addr; - - desc->conn_handle = conn->bhc_handle; - desc->conn_itvl = conn->bhc_itvl; - desc->conn_latency = conn->bhc_latency; - desc->supervision_timeout = conn->bhc_supervision_timeout; - desc->master_clock_accuracy = conn->bhc_master_clock_accuracy; - desc->sec_state = conn->bhc_sec_state; - - if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) { - desc->role = BLE_GAP_ROLE_MASTER; - } else { - desc->role = BLE_GAP_ROLE_SLAVE; - } -} - -int -bt_rand(void *buf, size_t len) -{ - int rc; - rc = ble_hs_hci_util_rand(buf, len); - if (rc != 0) { - return -1; - } - - return 0; -} - -int -bt_pub_key_gen(struct bt_pub_key_cb *new_cb) -{ - - if (ble_sm_alg_gen_key_pair(pub, priv)) { - assert(0); - return -1; - } - - new_cb->func(pub); - has_pub = true; - - return 0; -} - -uint8_t * -bt_pub_key_get(void) -{ - if (!has_pub) { - return NULL; - } - - return pub; -} - -static int -set_ad(const struct bt_data *ad, size_t ad_len, uint8_t *buf, uint8_t *buf_len) -{ - int i; - - for (i = 0; i < ad_len; i++) { - buf[(*buf_len)++] = ad[i].data_len + 1; - buf[(*buf_len)++] = ad[i].type; - - memcpy(&buf[*buf_len], ad[i].data, - ad[i].data_len); - *buf_len += ad[i].data_len; - } - - return 0; -} - -#if MYNEWT_VAL(BLE_EXT_ADV) -static void -ble_adv_copy_to_ext_param(struct ble_gap_ext_adv_params *ext_param, - const struct ble_gap_adv_params *param) -{ - memset(ext_param, 0, sizeof(*ext_param)); - - ext_param->legacy_pdu = 1; - - if (param->conn_mode != BLE_GAP_CONN_MODE_NON) { - ext_param->connectable = 1; - ext_param->scannable = 1; - } - - ext_param->itvl_max = param->itvl_max; - ext_param->itvl_min = param->itvl_min; - ext_param->channel_map = param->channel_map; - ext_param->high_duty_directed = param->high_duty_cycle; - ext_param->own_addr_type = g_mesh_addr_type; -} - -static int -ble_adv_conf_adv_instance(const struct ble_gap_adv_params *param, int *instance) -{ - struct ble_gap_ext_adv_params ext_params; - struct ble_gap_adv_params *cur_conf; - int err = 0; - - if (param->conn_mode == BLE_GAP_CONN_MODE_NON) { - *instance = BT_MESH_ADV_INST; - cur_conf = &ble_adv_cur_conf[BT_MESH_ADV_IDX]; - } else { -#if MYNEWT_VAL(BLE_MESH_PROXY) - *instance = BT_MESH_ADV_GATT_INST; - cur_conf = &ble_adv_cur_conf[BT_MESH_GATT_IDX]; -#else - assert(0); -#endif - } - - /* Checking interval max as it has to be in place if instance was configured - * before. - */ - if (cur_conf->itvl_max == 0) { - goto configure; - } - - if (memcmp(param, cur_conf, sizeof(*cur_conf)) == 0) { - /* Same parameters - skip reconfiguring */ - goto done; - } - - ble_gap_ext_adv_stop(*instance); - err = ble_gap_ext_adv_remove(*instance); - if (err) { - assert(0); - goto done; - } - -configure: - ble_adv_copy_to_ext_param(&ext_params, param); - - err = ble_gap_ext_adv_configure(*instance, &ext_params, 0, - ble_adv_gap_mesh_cb, NULL); - if (!err) { - memcpy(cur_conf, param, sizeof(*cur_conf)); - } - -done: - return err; -} - -int -bt_le_adv_start(const struct ble_gap_adv_params *param, - const struct bt_data *ad, size_t ad_len, - const struct bt_data *sd, size_t sd_len) -{ - struct os_mbuf *data; - int instance; - int err; - uint8_t buf[BLE_HS_ADV_MAX_SZ]; - uint8_t buf_len = 0; - - err = ble_adv_conf_adv_instance(param, &instance); - if (err) { - return err; - } - - if (ad_len > 0) { - err = set_ad(ad, ad_len, buf, &buf_len); - if (err) { - return err; - } - - /* For now let's use msys pool. We are not putting more then legacy */ - data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0); - if (!data) { - return OS_ENOMEM; - } - - err = os_mbuf_append(data, buf, buf_len); - if (err) { - goto error; - } - - err = ble_gap_ext_adv_set_data(instance, data); - if (err) { - return err; - } - - data = NULL; - } - - if (sd_len > 0) { - buf_len = 0; - - err = set_ad(sd, sd_len, buf, &buf_len); - if (err) { - return err; - } - - /* For now let's use msys pool. We are not putting more then legace*/ - data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_SZ, 0); - if (!data) { - return OS_ENOMEM; - } - - err = os_mbuf_append(data, buf, buf_len); - if (err) { - goto error; - } - - err = ble_gap_ext_adv_rsp_set_data(instance, data); - if (err) { - goto error; - } - } - - /*TODO: We could use duration and max events in the future */ - err = ble_gap_ext_adv_start(instance, 0, 0); - return err; - -error: - if (data) { - os_mbuf_free_chain(data); - } - - return err; -} -#else - -int -bt_le_adv_start(const struct ble_gap_adv_params *param, - const struct bt_data *ad, size_t ad_len, - const struct bt_data *sd, size_t sd_len) -{ - uint8_t buf[BLE_HS_ADV_MAX_SZ]; - uint8_t buf_len = 0; - int err; - - err = set_ad(ad, ad_len, buf, &buf_len); - if (err) { - return err; - } - - err = ble_gap_adv_set_data(buf, buf_len); - if (err != 0) { - return err; - } - - if (sd) { - buf_len = 0; - - err = set_ad(sd, sd_len, buf, &buf_len); - if (err) { - BT_ERR("Advertising failed: err %d", err); - return err; - } - - err = ble_gap_adv_rsp_set_data(buf, buf_len); - if (err != 0) { - BT_ERR("Advertising failed: err %d", err); - return err; - } - } - - err = ble_gap_adv_start(g_mesh_addr_type, NULL, BLE_HS_FOREVER, param, - NULL, NULL); - if (err) { - BT_ERR("Advertising failed: err %d", err); - return err; - } - - return 0; -} -#endif - -int bt_le_adv_stop() -{ - return ble_gap_adv_stop(); -} - -#if MYNEWT_VAL(BLE_MESH_PROXY) -int bt_mesh_proxy_svcs_register(void); -#endif - -void -bt_mesh_register_gatt(void) -{ -#if MYNEWT_VAL(BLE_MESH_PROXY) - bt_mesh_proxy_svcs_register(); -#endif -} - -void net_buf_slist_init(struct net_buf_slist_t *list) -{ - STAILQ_INIT(list); -} - -bool net_buf_slist_is_empty(struct net_buf_slist_t *list) -{ - return STAILQ_EMPTY(list); -} - -struct os_mbuf *net_buf_slist_peek_head(struct net_buf_slist_t *list) -{ - struct os_mbuf_pkthdr *pkthdr; - - /* Get mbuf pointer from packet header pointer */ - pkthdr = STAILQ_FIRST(list); - if (!pkthdr) { - return NULL; - } - - return OS_MBUF_PKTHDR_TO_MBUF(pkthdr); -} - -struct os_mbuf *net_buf_slist_peek_next(struct os_mbuf *buf) -{ - struct os_mbuf_pkthdr *pkthdr; - - /* Get mbuf pointer from packet header pointer */ - pkthdr = OS_MBUF_PKTHDR(buf); - pkthdr = STAILQ_NEXT(pkthdr, omp_next); - if (!pkthdr) { - return NULL; - } - - return OS_MBUF_PKTHDR_TO_MBUF(pkthdr); -} - -struct os_mbuf *net_buf_slist_get(struct net_buf_slist_t *list) -{ - os_sr_t sr; - struct os_mbuf *m; - - m = net_buf_slist_peek_head(list); - if (!m) { - return NULL; - } - - /* Remove from queue */ - OS_ENTER_CRITICAL(sr); - STAILQ_REMOVE_HEAD(list, omp_next); - OS_EXIT_CRITICAL(sr); - return m; -} - -void net_buf_slist_put(struct net_buf_slist_t *list, struct os_mbuf *buf) -{ - struct os_mbuf_pkthdr *pkthdr; - - pkthdr = OS_MBUF_PKTHDR(buf); - STAILQ_INSERT_TAIL(list, pkthdr, omp_next); -} - -void net_buf_slist_remove(struct net_buf_slist_t *list, struct os_mbuf *prev, - struct os_mbuf *cur) -{ - struct os_mbuf_pkthdr *pkthdr, *cur_pkthdr; - - cur_pkthdr = OS_MBUF_PKTHDR(cur); - - STAILQ_FOREACH(pkthdr, list, omp_next) { - if (cur_pkthdr == pkthdr) { - STAILQ_REMOVE(list, cur_pkthdr, os_mbuf_pkthdr, omp_next); - break; - } - } -} - -void net_buf_slist_merge_slist(struct net_buf_slist_t *list, - struct net_buf_slist_t *list_to_append) -{ - if (!STAILQ_EMPTY(list_to_append)) { - *(list)->stqh_last = list_to_append->stqh_first; - (list)->stqh_last = list_to_append->stqh_last; - STAILQ_INIT(list_to_append); - } -} - -/** 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; - - /* blocks must be word aligned */ - 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) -{ - *len = base64_decode(val_str, vp); - return 0; -} - -char *settings_str_from_bytes(const void *vp, int vp_len, - char *buf, int buf_len) -{ - if (BASE64_ENCODE_SIZE(vp_len) > buf_len) { - return NULL; - } - - base64_encode(vp, vp_len, buf, 1); - - return buf; -} - -#endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/health_cli.c b/src/nimble/nimble/host/mesh/src/health_cli.c deleted file mode 100644 index 839f11a30..000000000 --- a/src/nimble/nimble/host/mesh/src/health_cli.c +++ /dev/null @@ -1,529 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG - -#include -#include -#include - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "mesh_priv.h" -#include "adv.h" -#include "net.h" -#include "transport.h" -#include "foundation.h" -#include "nimble/nimble/host/mesh/include/mesh/health_cli.h" - -static int32_t msg_timeout = K_SECONDS(5); - -static struct bt_mesh_health_cli *health_cli; - -struct health_fault_param { - uint16_t cid; - uint8_t *expect_test_id; - uint8_t *test_id; - uint8_t *faults; - size_t *fault_count; -}; - -static int health_fault_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct health_fault_param *param; - uint8_t test_id; - 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, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_HEALTH_FAULT_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - test_id = net_buf_simple_pull_u8(buf); - if (param->expect_test_id && test_id != *param->expect_test_id) { - BT_WARN("Health fault with unexpected Test ID"); - return -ENOENT; - } - - cid = net_buf_simple_pull_le16(buf); - if (cid != param->cid) { - BT_WARN("Health fault with unexpected Company ID"); - return -ENOENT; - } - - if (param->test_id) { - *param->test_id = test_id; - } - - if (buf->om_len > *param->fault_count) { - BT_WARN("Got more faults than there's space for"); - } else { - *param->fault_count = buf->om_len; - } - - memcpy(param->faults, buf->om_data, *param->fault_count); - - bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); - - return 0; -} - -static int health_current_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_health_cli *cli = model->user_data; - uint8_t test_id; - 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, - bt_hex(buf->om_data, buf->om_len)); - - test_id = net_buf_simple_pull_u8(buf); - cid = net_buf_simple_pull_le16(buf); - - BT_DBG("Test ID 0x%02x Company ID 0x%04x Fault Count %u", - test_id, cid, buf->om_len); - - if (!cli->current_status) { - BT_WARN("No Current Status callback available"); - return 0; - } - - cli->current_status(cli, ctx->addr, test_id, cid, buf->om_data, buf->om_len); - - return 0; -} - -struct health_period_param { - uint8_t *divisor; -}; - -static int health_period_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct health_period_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_HEALTH_PERIOD_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - *param->divisor = net_buf_simple_pull_u8(buf); - - bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); - - return 0; -} - -struct health_attention_param { - uint8_t *attention; -}; - -static int health_attention_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct health_attention_param *param; - - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", - ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - if (!bt_mesh_msg_ack_ctx_match(&health_cli->ack_ctx, OP_ATTENTION_STATUS, ctx->addr, - (void **)¶m)) { - return -ENOENT; - } - - if (param->attention) { - *param->attention = net_buf_simple_pull_u8(buf); - } - - bt_mesh_msg_ack_ctx_rx(&health_cli->ack_ctx); - - return 0; -} - -const struct bt_mesh_model_op bt_mesh_health_cli_op[] = { - { OP_HEALTH_FAULT_STATUS, BT_MESH_LEN_MIN(3), health_fault_status }, - { OP_HEALTH_CURRENT_STATUS, BT_MESH_LEN_MIN(3), health_current_status }, - { OP_HEALTH_PERIOD_STATUS, BT_MESH_LEN_EXACT(1), health_period_status }, - { OP_ATTENTION_STATUS, BT_MESH_LEN_EXACT(1), health_attention_status }, - BT_MESH_MODEL_OP_END, -}; - -static int cli_prepare(void *param, uint32_t op, uint16_t addr) -{ - if (!health_cli) { - BT_ERR("No available Health Client context!"); - return -EINVAL; - } - - return bt_mesh_msg_ack_ctx_prepare(&health_cli->ack_ctx, op, addr, param); -} - -int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_GET, 0); - struct bt_mesh_msg_ctx ctx = { - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct health_attention_param param = { - .attention = attention, - }; - int err; - - err = cli_prepare(¶m, OP_ATTENTION_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_ATTENTION_GET); - - err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct health_attention_param param = { - .attention = updated_attention, - }; - int err; - - err = cli_prepare(¶m, OP_ATTENTION_STATUS, addr); - if (err) { - goto done; - } - - if (updated_attention) { - bt_mesh_model_msg_init(msg, OP_ATTENTION_SET); - } else { - bt_mesh_model_msg_init(msg, OP_ATTENTION_SET_UNREL); - } - - net_buf_simple_add_u8(msg, attention); - - err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - if (!updated_attention) { - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct health_period_param param = { - .divisor = divisor, - }; - int err; - - err = cli_prepare(¶m, OP_HEALTH_PERIOD_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_GET); - - err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct health_period_param param = { - .divisor = updated_divisor, - }; - int err; - - err = cli_prepare(¶m, OP_HEALTH_PERIOD_STATUS, addr); - if (err) { - goto done; - } - - if (updated_divisor) { - bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_SET); - } else { - bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_SET_UNREL); - } - - net_buf_simple_add_u8(msg, divisor); - - err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - if (!updated_divisor) { - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct health_fault_param param = { - .cid = cid, - .expect_test_id = &test_id, - .faults = faults, - .fault_count = fault_count, - }; - int err; - - err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS, addr); - if (err) { - goto done; - } - - if (faults) { - bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_TEST); - } else { - bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_TEST_UNREL); - } - - net_buf_simple_add_u8(msg, test_id); - net_buf_simple_add_le16(msg, cid); - - err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - if (!faults) { - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct health_fault_param param = { - .cid = cid, - .test_id = test_id, - .faults = faults, - .fault_count = fault_count, - }; - int err; - - err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS, addr); - if (err) { - goto done; - } - - if (test_id) { - bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_CLEAR); - } else { - bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_CLEAR_UNREL); - } - - net_buf_simple_add_le16(msg, cid); - - err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - if (!test_id) { - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct health_fault_param param = { - .cid = cid, - .test_id = test_id, - .faults = faults, - .fault_count = fault_count, - }; - int err; - - err = cli_prepare(¶m, OP_HEALTH_FAULT_STATUS, addr); - if (err) { - goto done; - } - - bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_GET); - net_buf_simple_add_le16(msg, cid); - - err = bt_mesh_model_send(health_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - bt_mesh_msg_ack_ctx_clear(&health_cli->ack_ctx); - goto done; - } - - err = bt_mesh_msg_ack_ctx_wait(&health_cli->ack_ctx, K_MSEC(msg_timeout)); -done: - os_mbuf_free_chain(msg); - return err; -} - -int32_t bt_mesh_health_cli_timeout_get(void) -{ - return msg_timeout; -} - -void bt_mesh_health_cli_timeout_set(int32_t timeout) -{ - msg_timeout = timeout; -} - -int bt_mesh_health_cli_set(struct bt_mesh_model *model) -{ - if (!model->user_data) { - BT_ERR("No Health Client context for given model"); - return -EINVAL; - } - - health_cli = model->user_data; - msg_timeout = 2 * MSEC_PER_SEC; - - return 0; -} - -static int health_cli_init(struct bt_mesh_model *model) -{ - struct bt_mesh_health_cli *cli = model->user_data; - - BT_DBG("primary %u", bt_mesh_model_in_primary(model)); - - if (!cli) { - BT_ERR("No Health Client context provided"); - return -EINVAL; - } - - cli = model->user_data; - cli->model = model; - msg_timeout = 2 * MSEC_PER_SEC; - - /* Set the default health client pointer */ - if (!health_cli) { - health_cli = cli; - } - - bt_mesh_msg_ack_ctx_init(&health_cli->ack_ctx); - return 0; -} - -const struct bt_mesh_model_cb bt_mesh_health_cli_cb = { - .init = health_cli_init, -}; - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/health_srv.c b/src/nimble/nimble/host/mesh/src/health_srv.c deleted file mode 100644 index 42a862cb5..000000000 --- a/src/nimble/nimble/host/mesh/src/health_srv.c +++ /dev/null @@ -1,479 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG - -#include -#include -#include - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "mesh_priv.h" -#include "adv.h" -#include "net.h" -#include "transport.h" -#include "access.h" -#include "foundation.h" - -#define HEALTH_TEST_STANDARD 0x00 - -/* Health Server context of the primary element */ -struct bt_mesh_health_srv *health_srv; - -static void health_get_registered(struct bt_mesh_model *mod, - uint16_t company_id, - struct os_mbuf *msg) -{ - struct bt_mesh_health_srv *srv = mod->user_data; - uint8_t *test_id; - - BT_DBG("Company ID 0x%04x", company_id); - - bt_mesh_model_msg_init(msg, OP_HEALTH_FAULT_STATUS); - - test_id = net_buf_simple_add(msg, 1); - net_buf_simple_add_le16(msg, company_id); - - if (srv->cb && srv->cb->fault_get_reg) { - uint8_t fault_count = net_buf_simple_tailroom(msg) - 4; - int err; - - err = srv->cb->fault_get_reg(mod, company_id, test_id, - net_buf_simple_tail(msg), - &fault_count); - if (err) { - BT_ERR("Failed to get faults (err %d)", err); - *test_id = HEALTH_TEST_STANDARD; - } else { - net_buf_simple_add(msg, fault_count); - } - } else { - BT_WARN("No callback for getting faults"); - *test_id = HEALTH_TEST_STANDARD; - } -} - -static size_t health_get_current(struct bt_mesh_model *mod, - struct os_mbuf *msg) -{ - struct bt_mesh_health_srv *srv = mod->user_data; - const struct bt_mesh_comp *comp; - uint8_t *test_id, *company_ptr; - uint16_t company_id; - uint8_t fault_count; - - bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS); - - test_id = net_buf_simple_add(msg, 1); - company_ptr = net_buf_simple_add(msg, sizeof(company_id)); - comp = bt_mesh_comp_get(); - - if (srv->cb && srv->cb->fault_get_cur) { - fault_count = net_buf_simple_tailroom(msg); - int err; - - err = srv->cb->fault_get_cur(mod, test_id, &company_id, - net_buf_simple_tail(msg), - &fault_count); - if (err) { - BT_ERR("Failed to get faults (err %d)", err); - sys_put_le16(comp->cid, company_ptr); - *test_id = HEALTH_TEST_STANDARD; - fault_count = 0; - } else { - sys_put_le16(company_id, company_ptr); - net_buf_simple_add(msg, fault_count); - } - } else { - BT_WARN("No callback for getting faults"); - sys_put_le16(comp->cid, company_ptr); - *test_id = HEALTH_TEST_STANDARD; - fault_count = 0; - } - - return fault_count; -} - -static int health_fault_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - uint16_t company_id; - - company_id = net_buf_simple_pull_le16(buf); - - BT_DBG("company_id 0x%04x", company_id); - - health_get_registered(model, company_id, sdu); - - if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) { - BT_ERR("Unable to send Health Current Status response"); - } - - os_mbuf_free_chain(sdu); - - return 0; -} - -static int health_fault_clear_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_health_srv *srv = model->user_data; - uint16_t company_id; - - company_id = net_buf_simple_pull_le16(buf); - - BT_DBG("company_id 0x%04x", company_id); - - if (srv->cb && srv->cb->fault_clear) { - return srv->cb->fault_clear(model, company_id); - } - - return 0; -} - -static int health_fault_clear(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - struct bt_mesh_health_srv *srv = model->user_data; - uint16_t company_id; - - company_id = net_buf_simple_pull_le16(buf); - - BT_DBG("company_id 0x%04x", company_id); - - if (srv->cb && srv->cb->fault_clear) { - int err; - - err = srv->cb->fault_clear(model, company_id); - if (err) { - return err; - } - } - - health_get_registered(model, company_id, sdu); - - if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) { - BT_ERR("Unable to send Health Current Status response"); - } - - os_mbuf_free_chain(sdu); - - return 0; -} - -static int health_fault_test_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_health_srv *srv = model->user_data; - uint16_t company_id; - uint8_t test_id; - - test_id = net_buf_simple_pull_u8(buf); - company_id = net_buf_simple_pull_le16(buf); - - BT_DBG("test 0x%02x company 0x%04x", test_id, company_id); - - if (srv->cb && srv->cb->fault_test) { - return srv->cb->fault_test(model, test_id, company_id); - } - - return 0; -} - -static int health_fault_test(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - struct bt_mesh_health_srv *srv = model->user_data; - uint16_t company_id; - uint8_t test_id; - int err = 0; - - BT_DBG(""); - - test_id = net_buf_simple_pull_u8(buf); - company_id = net_buf_simple_pull_le16(buf); - - BT_DBG("test 0x%02x company 0x%04x", test_id, company_id); - - if (srv->cb && srv->cb->fault_test) { - err = srv->cb->fault_test(model, test_id, company_id); - if (err) { - BT_WARN("Running fault test failed with err %d", err); - - goto done; - } - } - - health_get_registered(model, company_id, sdu); - - if (bt_mesh_model_send(model, ctx, sdu, NULL, NULL)) { - BT_ERR("Unable to send Health Current Status response"); - } - -done: - os_mbuf_free_chain(sdu); - - return err; -} - -static int send_attention_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_STATUS, 1); - struct bt_mesh_health_srv *srv = model->user_data; - uint8_t time; - - time = k_ticks_to_ms_floor32( - k_work_delayable_remaining_get(&srv->attn_timer)) / 1000; - BT_DBG("%u second%s", time, (time == 1) ? "" : "s"); - - bt_mesh_model_msg_init(msg, OP_ATTENTION_STATUS); - - net_buf_simple_add_u8(msg, time); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Attention Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int attention_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG(""); - - return send_attention_status(model, ctx); -} - -static int attention_set_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t time; - - time = net_buf_simple_pull_u8(buf); - - BT_DBG("%u second%s", time, (time == 1) ? "" : "s"); - - bt_mesh_attention(model, time); - - return 0; -} - -static int attention_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - int err; - - BT_DBG(""); - - err = attention_set_unrel(model, ctx, buf); - if (err) { - return err; - } - - return send_attention_status(model, ctx); -} - -static int send_health_period_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) -{ - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_STATUS, 1); - - bt_mesh_model_msg_init(msg, OP_HEALTH_PERIOD_STATUS); - - net_buf_simple_add_u8(msg, model->pub->period_div); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Health Period Status"); - } - - os_mbuf_free_chain(msg); - - return 0; -} - -static int health_period_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG(""); - - return send_health_period_status(model, ctx); -} - -static int health_period_set_unrel(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - uint8_t period; - - period = net_buf_simple_pull_u8(buf); - if (period > 15) { - BT_WARN("Prohibited period value %u", period); - return -EINVAL; - } - - BT_DBG("period %u", period); - - model->pub->period_div = period; - - return 0; -} - -static int health_period_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - int err; - - BT_DBG(""); - - err = health_period_set_unrel(model, ctx, buf); - if (err) { - return err; - } - - return send_health_period_status(model, ctx); -} - -const struct bt_mesh_model_op bt_mesh_health_srv_op[] = { - { OP_HEALTH_FAULT_GET, BT_MESH_LEN_EXACT(2), health_fault_get }, - { OP_HEALTH_FAULT_CLEAR, BT_MESH_LEN_EXACT(2), health_fault_clear }, - { OP_HEALTH_FAULT_CLEAR_UNREL, BT_MESH_LEN_EXACT(2), health_fault_clear_unrel }, - { OP_HEALTH_FAULT_TEST, BT_MESH_LEN_EXACT(3), health_fault_test }, - { OP_HEALTH_FAULT_TEST_UNREL, BT_MESH_LEN_EXACT(3), health_fault_test_unrel }, - { OP_HEALTH_PERIOD_GET, BT_MESH_LEN_EXACT(0), health_period_get }, - { OP_HEALTH_PERIOD_SET, BT_MESH_LEN_EXACT(1), health_period_set }, - { OP_HEALTH_PERIOD_SET_UNREL, BT_MESH_LEN_EXACT(1), health_period_set_unrel }, - { OP_ATTENTION_GET, BT_MESH_LEN_EXACT(0), attention_get }, - { OP_ATTENTION_SET, BT_MESH_LEN_EXACT(1), attention_set }, - { OP_ATTENTION_SET_UNREL, BT_MESH_LEN_EXACT(1), attention_set_unrel }, - BT_MESH_MODEL_OP_END, -}; - -static int health_pub_update(struct bt_mesh_model *mod) -{ - struct bt_mesh_model_pub *pub = mod->pub; - size_t count; - - BT_DBG(""); - - count = health_get_current(mod, pub->msg); - if (count) { - pub->fast_period = 1U; - } else { - pub->fast_period = 0U; - } - - return 0; -} - -int bt_mesh_fault_update(struct bt_mesh_elem *elem) -{ - struct bt_mesh_model *mod; - - mod = bt_mesh_model_find(elem, BT_MESH_MODEL_ID_HEALTH_SRV); - if (!mod) { - return -EINVAL; - } - - /* Let periodic publishing, if enabled, take care of sending the - * Health Current Status. - */ - if (bt_mesh_model_pub_period_get(mod)) { - return 0; - } - - health_pub_update(mod); - - return bt_mesh_model_publish(mod); -} - -static void attention_off(struct ble_npl_event *work) -{ - struct bt_mesh_health_srv *srv = ble_npl_event_get_arg(work); - BT_DBG(""); - - if (srv->cb && srv->cb->attn_off) { - srv->cb->attn_off(srv->model); - } -} - -static int health_srv_init(struct bt_mesh_model *model) -{ - struct bt_mesh_health_srv *srv = model->user_data; - - if (!srv) { - BT_ERR("No Health Server context provided"); - return -EINVAL; - } - - if (!model->pub) { - BT_ERR("Health Server has no publication support"); - return -EINVAL; - } - - model->pub->update = health_pub_update; - - k_work_init_delayable(&srv->attn_timer, attention_off); - k_work_add_arg_delayable(&srv->attn_timer, srv); - - srv->model = model; - - if (bt_mesh_model_in_primary(model)) { - health_srv = srv; - } - - return 0; -} - -const struct bt_mesh_model_cb bt_mesh_health_srv_cb = { - .init = health_srv_init, -}; - -void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time) -{ - struct bt_mesh_health_srv *srv; - - BT_DBG("bt_mesh_attention"); - if (!model) { - srv = health_srv; - if (!srv) { - BT_WARN("No Health Server available"); - return; - } - - model = srv->model; - } else { - srv = model->user_data; - } - - if ((time > 0) && srv->cb && srv->cb->attn_on) { - srv->cb->attn_on(model); - } - k_work_reschedule(&srv->attn_timer, K_SECONDS(time)); -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/heartbeat.c b/src/nimble/nimble/host/mesh/src/heartbeat.c deleted file mode 100644 index 21bb1433e..000000000 --- a/src/nimble/nimble/host/mesh/src/heartbeat.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#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 "nimble/nimble/host/mesh/include/mesh/glue.h" - -/* Heartbeat Publication information for persistent storage. */ -struct hb_pub_val { - uint16_t dst; - uint8_t period; - uint8_t ttl; - uint16_t feat; - uint16_t net_idx:12, - indefinite:1; -}; - -struct bt_mesh_hb_cb hb_cb; - -static struct bt_mesh_hb_pub pub; -static struct bt_mesh_hb_sub sub; -static struct k_work_delayable sub_timer; -static struct k_work_delayable pub_timer; - -static int64_t sub_remaining(void) -{ - if (sub.dst == BT_MESH_ADDR_UNASSIGNED) { - return 0U; - } - - uint32_t rem_ms = k_ticks_to_ms_floor32( - k_work_delayable_remaining_get(&sub_timer)); - return rem_ms / MSEC_PER_SEC; -} - -static void hb_publish_end_cb(int err, void *cb_data) -{ - if (pub.period && pub.count > 1) { - k_work_reschedule(&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 or the subnet is - * removed. - */ - if (!tx.sub || pub.dst == BT_MESH_ADDR_UNASSIGNED) { - return 0; - } - - 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); - - /* Fast exit if disabled or expired */ - if (pub.period == 0U || pub.count == 0U) { - return; - } - - sub = bt_mesh_subnet_get(pub.net_idx); - if (!sub) { - BT_ERR("No matching subnet for idx 0x%02x", pub.net_idx); - pub.dst = BT_MESH_ADDR_UNASSIGNED; - 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_work_delayable_is_pending(&sub_timer)) { - BT_DBG("Heartbeat subscription inactive"); - 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_work_cancel_delayable(&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_settings_store_schedule( - BT_MESH_SETTINGS_HB_PUB_PENDING); - } - - 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 the new configuration disables publishing this flushes - * the work item. - */ - k_work_reschedule(&pub_timer, K_NO_WAIT); - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_settings_store_schedule( - BT_MESH_SETTINGS_HB_PUB_PENDING); - } - - 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 %" PRIu32 "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 = 0U; - } 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; - } else { - /* Clearing the period should stop heartbeat subscription - * without clearing the parameters, so we can still read them. - */ - sub.period = 0U; - } - - /* Start the timer, which notifies immediately if the new - * configuration disables the subscription. - */ - k_work_reschedule(&sub_timer, K_SECONDS(sub.period)); - - return STATUS_SUCCESS; -} - -void bt_mesh_hb_sub_reset_count(void) -{ - sub.count = 0; -} - -void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get) -{ - *get = sub; - 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_work_init_delayable(&pub_timer, hb_publish); - k_work_init_delayable(&sub_timer, sub_end); -} - -void bt_mesh_hb_start(void) -{ - if (pub.count && pub.period) { - BT_DBG("Starting heartbeat publication"); - k_work_reschedule(&pub_timer, K_NO_WAIT); - } -} - -void bt_mesh_hb_suspend(void) -{ - (void)k_work_cancel_delayable(&pub_timer); -} - -void bt_mesh_hb_resume(void) -{ - if (pub.period && pub.count) { - BT_DBG("Starting heartbeat publication"); - k_work_reschedule(&pub_timer, K_NO_WAIT); - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static int hb_pub_set(int argc, char **argv, char *val) -{ - struct bt_mesh_hb_pub pub; - struct hb_pub_val hb_val; - int len, err; - BT_DBG("val %s", val ? val : "(null)"); - len = sizeof(hb_val); - err = settings_bytes_from_str(val, &hb_val, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - if (len != sizeof(hb_val)) { - BT_ERR("Unexpected value length (%d != %zu)", len, - sizeof(hb_val)); - return -EINVAL; - } - pub.dst = hb_val.dst; - pub.period = bt_mesh_hb_pwr2(hb_val.period); - pub.ttl = hb_val.ttl; - pub.feat = hb_val.feat; - pub.net_idx = hb_val.net_idx; - if (hb_val.indefinite) { - pub.count = 0xffff; - } else { - pub.count = 0; - } - (void) bt_mesh_hb_pub_set(&pub); - - BT_DBG("Restored heartbeat publication"); - - return 0; -} - -void bt_mesh_hb_pub_pending_store(void) -{ - struct bt_mesh_hb_pub pub; - char buf[BT_SETTINGS_SIZE(sizeof(struct hb_pub_val))]; - struct hb_pub_val val; - int err; - char *str; - - bt_mesh_hb_pub_get(&pub); - if (pub.dst == BT_MESH_ADDR_UNASSIGNED) { - err = settings_save_one("bt_mesh/HBPub", NULL); - } else { - val.indefinite = (pub.count == 0xffff); - val.dst = pub.dst; - val.period = bt_mesh_hb_log(pub.period); - val.ttl = pub.ttl; - val.feat = pub.feat; - val.net_idx = pub.net_idx; - - str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode configuration as value"); - return; - } - - BT_DBG("Saving configuration as value %s", str); - err = settings_save_one("bt_mesh/HBPub", str); - } - - if (err) { - BT_ERR("Failed to store Heartbeat Publication"); - } else { - BT_DBG("Stored Heartbeat Publication"); - } -} - -static struct conf_handler bt_mesh_hb_pub_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = hb_pub_set, - .ch_commit = NULL, - .ch_export = NULL, -}; -#endif - -void bt_mesh_hb_pub_init(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - int rc; - - rc = conf_register(&bt_mesh_hb_pub_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_hb_pub conf"); -#endif -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/heartbeat.h b/src/nimble/nimble/host/mesh/src/heartbeat.h deleted file mode 100644 index c21afb88f..000000000 --- a/src/nimble/nimble/host/mesh/src/heartbeat.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "nimble/nimble/host/mesh/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); -void bt_mesh_hb_sub_reset_count(void); -void bt_mesh_hb_pub_pending_store(void); -void bt_mesh_hb_pub_init(void); diff --git a/src/nimble/nimble/host/mesh/src/light_model.c b/src/nimble/nimble/host/mesh/src/light_model.c deleted file mode 100644 index 070bbfad9..000000000 --- a/src/nimble/nimble/host/mesh/src/light_model.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/console/console.h" -#include "light_model.h" - - -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, (uint16_t)gen_level_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, uint8_t state) -{ - gen_onoff_state = state; - update_light_state(); - return 0; -} - -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, int16_t level) -{ - gen_level_state = level; - if ((uint16_t)gen_level_state > 0x0000) { - gen_onoff_state = 1; - } - 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, int16_t *lightness) -{ - return light_model_gen_level_get(model, lightness); -} - -int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness) -{ - return light_model_gen_level_set(model, lightness); -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/light_model.h b/src/nimble/nimble/host/mesh/src/light_model.h deleted file mode 100644 index 859ef3ba7..000000000 --- a/src/nimble/nimble/host/mesh/src/light_model.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __BT_MESH_LIGHT_MODEL_H -#define __BT_MESH_LIGHT_MODEL_H - -#include "syscfg/syscfg.h" -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -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/src/nimble/nimble/host/mesh/src/lpn.c b/src/nimble/nimble/host/mesh/src/lpn.c deleted file mode 100644 index dab9e1bf3..000000000 --- a/src/nimble/nimble/host/mesh/src/lpn.c +++ /dev/null @@ -1,1101 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#define MESH_LOG_MODULE BLE_MESH_LOW_POWER_LOG - -#if MYNEWT_VAL(BLE_MESH_LOW_POWER) - -#include - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "mesh_priv.h" -#include "crypto.h" -#include "adv.h" -#include "net.h" -#include "transport.h" -#include "heartbeat.h" -#include "access.h" -#include "beacon.h" -#include "foundation.h" -#include "lpn.h" - -#if MYNEWT_VAL(BLE_MESH_LPN_AUTO) -#define LPN_AUTO_TIMEOUT K_SECONDS(MYNEWT_VAL(BLE_MESH_LPN_AUTO_TIMEOUT)) -#else -#define LPN_AUTO_TIMEOUT 0 -#endif - -#define LPN_RECV_DELAY MYNEWT_VAL(BLE_MESH_LPN_RECV_DELAY) -#define SCAN_LATENCY MIN(MYNEWT_VAL(BLE_MESH_LPN_SCAN_LATENCY), \ - LPN_RECV_DELAY) - -#define FRIEND_REQ_RETRY_TIMEOUT K_SECONDS(MYNEWT_VAL(BLE_MESH_LPN_RETRY_TIMEOUT)) - -#define FRIEND_REQ_WAIT K_MSEC(100) -#define FRIEND_REQ_SCAN K_SECONDS(1) -#define FRIEND_REQ_TIMEOUT (FRIEND_REQ_WAIT + FRIEND_REQ_SCAN) - -#define POLL_RETRY_TIMEOUT K_MSEC(100) - -#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 (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) { (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)(uint16_t friend_addr, bool established); - -#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG -static const char *state2str(int state) -{ - switch (state) { - case BT_MESH_LPN_DISABLED: - return "disabled"; - case BT_MESH_LPN_CLEAR: - return "clear"; - case BT_MESH_LPN_TIMER: - return "timer"; - case BT_MESH_LPN_ENABLED: - return "enabled"; - case BT_MESH_LPN_REQ_WAIT: - return "req wait"; - case BT_MESH_LPN_WAIT_OFFER: - return "wait offer"; - case BT_MESH_LPN_ESTABLISHED: - return "established"; - case BT_MESH_LPN_RECV_DELAY: - return "recv delay"; - case BT_MESH_LPN_WAIT_UPDATE: - return "wait update"; - default: - return "(unknown)"; - } -} -#endif - -static inline void lpn_set_state(int state) -{ -#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG - BT_DBG("%s -> %s", state2str(bt_mesh.lpn.state), state2str(state)); -#endif - bt_mesh.lpn.state = state; -} - -static inline void group_zero(atomic_t *target) -{ -#if CONFIG_BT_MESH_LPN_GROUPS > 32 - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) { - atomic_set(&target[i], 0); - } -#else - atomic_set(target, 0); -#endif -} - -static inline void group_set(atomic_t *target, atomic_t *source) -{ -#if CONFIG_BT_MESH_LPN_GROUPS > 32 - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) { - atomic_or(&target[i], atomic_get(&source[i])); - } -#else - atomic_or(target, atomic_get(source)); -#endif -} - -static inline void group_clear(atomic_t *target, atomic_t *source) -{ -#if CONFIG_BT_MESH_LPN_GROUPS > 32 - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) { - atomic_and(&target[i], ~atomic_get(&source[i])); - } -#else - atomic_and(target, ~atomic_get(source)); -#endif -} - -static void clear_friendship(bool force, bool disable); - -static int32_t poll_timeout(struct bt_mesh_lpn *lpn) -{ - /* If we're waiting for segment acks keep polling at high freq */ - if (bt_mesh_tx_in_progress()) { - return MIN(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1)); - } - - if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) { - lpn->poll_timeout *= 2; - lpn->poll_timeout = MIN(lpn->poll_timeout, - POLL_TIMEOUT_MAX(lpn)); - } - - BT_DBG("Poll Timeout is %ums", (unsigned) lpn->poll_timeout); - - return lpn->poll_timeout; -} - -static void friend_clear_sent(int err, void *user_data) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - - /* Scanning will enable if lpn state still enabled */ - - lpn->req_attempts++; - - if (err) { - BT_ERR("Sending Friend Request failed (err %d)", err); - lpn_set_state(BT_MESH_LPN_ENABLED); - clear_friendship(false, lpn->disable); - return; - } - - lpn_set_state(BT_MESH_LPN_CLEAR); - k_work_reschedule(&lpn->timer, FRIEND_REQ_TIMEOUT); -} - -static const struct bt_mesh_send_cb clear_sent_cb = { - .end = friend_clear_sent, -}; - -static int send_friend_clear(void) -{ - struct bt_mesh_msg_ctx ctx = { - .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.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.lpn_counter), - }; - - BT_DBG(""); - - return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req, - sizeof(req), &clear_sent_cb, NULL); -} - -static void clear_friendship(bool force, bool disable) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - - BT_DBG("force %u disable %u", force, disable); - - if (!force && lpn->established && !lpn->clear_success && - lpn->req_attempts < CLEAR_ATTEMPTS) { - send_friend_clear(); - lpn->disable = disable; - return; - } - - bt_mesh_rx_reset(); - - lpn_set_state(BT_MESH_LPN_DISABLED); - k_work_cancel_delayable(&lpn->timer); - - if (lpn->clear_success) { - lpn->old_friend = BT_MESH_ADDR_UNASSIGNED; - } else { - lpn->old_friend = lpn->frnd; - } - - if (lpn_cb && lpn->frnd != BT_MESH_ADDR_UNASSIGNED) { - lpn_cb(lpn->frnd, false); - } - - lpn->frnd = BT_MESH_ADDR_UNASSIGNED; - lpn->fsn = 0; - lpn->req_attempts = 0; - lpn->recv_win = 0; - lpn->queue_size = 0; - lpn->disable = 0; - lpn->sent_req = 0U; - lpn->established = 0; - lpn->clear_success = 0; - lpn->sub = NULL; - - group_zero(lpn->added); - group_zero(lpn->pending); - group_zero(lpn->to_remove); - - /* Set this to 1 to force group subscription when the next - * Friendship is created, in case lpn->groups doesn't get - * modified meanwhile. - */ - lpn->groups_changed = 1; - - bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER); - - if (!disable) { - lpn_set_state(BT_MESH_LPN_DISABLED); - k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); - return; - } - -} - -static void friend_req_sent(uint16_t duration, int err, void *user_data) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - - if (err) { - BT_ERR("Sending Friend Request failed (err %d)", err); - return; - } - - lpn->adv_duration = duration; - - if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - k_work_reschedule(&lpn->timer, FRIEND_REQ_WAIT); - lpn_set_state(BT_MESH_LPN_REQ_WAIT); - } else { - k_work_reschedule(&lpn->timer, - duration + FRIEND_REQ_TIMEOUT); - lpn_set_state(BT_MESH_LPN_WAIT_OFFER); - } -} - -static const struct bt_mesh_send_cb friend_req_sent_cb = { - .start = friend_req_sent, -}; - -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 = { - .app_idx = BT_MESH_KEY_UNUSED, - .addr = BT_MESH_ADDR_FRIENDS, - .send_ttl = 0, - }; - struct bt_mesh_net_tx tx = { - .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 = sys_cpu_to_be16(lpn->old_friend), - .num_elem = comp->elem_count, - .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), &friend_req_sent_cb, NULL); -} - -static void req_sent(uint16_t duration, int err, void *user_data) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - -#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG - BT_DBG("req 0x%02x duration %u err %d state %s", - lpn->sent_req, duration, err, state2str(lpn->state)); -#endif - - if (err) { - BT_ERR("Sending request failed (err %d)", err); - lpn->sent_req = 0U; - group_zero(lpn->pending); - return; - } - - lpn->req_attempts++; - lpn->adv_duration = duration; - - if (lpn->established || IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - lpn_set_state(BT_MESH_LPN_RECV_DELAY); - /* We start scanning a bit early to elimitate risk of missing - * response data due to HCI and other latencies. - */ - k_work_reschedule(&lpn->timer, - LPN_RECV_DELAY - SCAN_LATENCY); - } else { - lpn_set_state(BT_MESH_LPN_WAIT_UPDATE); - k_work_reschedule(&lpn->timer, - LPN_RECV_DELAY + duration + - lpn->recv_win); - } -} - -static const struct bt_mesh_send_cb req_sent_cb = { - .start = req_sent, -}; - -static int send_friend_poll(void) -{ - struct bt_mesh_msg_ctx ctx = { - .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.lpn.sub, - .ctx = &ctx, - .src = bt_mesh_primary_addr(), - .xmit = POLL_XMIT, - .friend_cred = true, - }; - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - uint8_t fsn = lpn->fsn; - int err; - - BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req); - - if (lpn->sent_req) { - if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) { - lpn->pending_poll = 1; - } - - return 0; - } - - err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1, - &req_sent_cb, NULL); - if (err == 0) { - lpn->pending_poll = 0; - lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL; - } - - return err; -} - -void bt_mesh_lpn_disable(bool force) -{ - if (bt_mesh.lpn.state == BT_MESH_LPN_DISABLED) { - return; - } - - clear_friendship(force, true); -} - -int bt_mesh_lpn_set(bool enable) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - - if (enable) { - if (lpn->state != BT_MESH_LPN_DISABLED) { - return 0; - } - } else { - if (lpn->state == BT_MESH_LPN_DISABLED) { - return 0; - } - } - - if (!bt_mesh_is_provisioned()) { - if (enable) { - lpn_set_state(BT_MESH_LPN_ENABLED); - } else { - lpn_set_state(BT_MESH_LPN_DISABLED); - } - - return 0; - } - - if (enable) { - lpn_set_state(BT_MESH_LPN_ENABLED); - - if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - bt_mesh_scan_disable(); - } - - send_friend_req(lpn); - } else { - if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO) && - lpn->state == BT_MESH_LPN_TIMER) { - k_work_cancel_delayable(&lpn->timer); - lpn_set_state(BT_MESH_LPN_DISABLED); - } else { - bt_mesh_lpn_disable(false); - } - } - - return 0; -} - -static void friend_response_received(struct bt_mesh_lpn *lpn) -{ - BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req); - - if (lpn->sent_req == TRANS_CTL_OP_FRIEND_POLL) { - lpn->fsn++; - } - - bt_mesh_scan_disable(); - lpn_set_state(BT_MESH_LPN_ESTABLISHED); - lpn->req_attempts = 0; - lpn->sent_req = 0U; - - int32_t timeout = poll_timeout(lpn); - - k_work_reschedule(&lpn->timer, K_MSEC(timeout)); -} - -void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - - if (lpn->state == BT_MESH_LPN_TIMER) { - BT_DBG("Restarting establishment timer"); - k_work_reschedule(&lpn->timer, LPN_AUTO_TIMEOUT); - return; - } - - if (lpn->state != BT_MESH_LPN_WAIT_UPDATE) { - return; - } - - /* If the message was a Friend control message, it's possible that a - * Poll was already queued for sending. In this case, we're already in - * a different state. - */ - if (lpn->state != BT_MESH_LPN_WAIT_UPDATE) { - return; - } - - if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) { - BT_WARN("Unexpected message withouth a preceding Poll"); - return; - } - - friend_response_received(lpn); - - BT_DBG("Requesting more messages from Friend"); - - 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; - uint16_t frnd_counter; - int err; - - if (buf->om_len < sizeof(*msg)) { - BT_WARN("Too short Friend Offer"); - return -EINVAL; - } - - if (lpn->state != BT_MESH_LPN_WAIT_OFFER) { - BT_WARN("Ignoring unexpected Friend Offer"); - return 0; - } - - if (!msg->recv_win) { - BT_WARN("Prohibited ReceiveWindow value"); - return -EINVAL; - } - - frnd_counter = sys_be16_to_cpu(msg->frnd_counter); - - BT_DBG("recv_win %u queue_size %u sub_list_size %u rssi %d counter %u", - msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi, - frnd_counter); - - lpn->frnd_counter = frnd_counter; - lpn->frnd = rx->ctx.addr; - - /* 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 */ - - lpn->recv_win = msg->recv_win; - lpn->queue_size = msg->queue_size; - - err = send_friend_poll(); - if (err) { - lpn->sub = NULL; - lpn->frnd = BT_MESH_ADDR_UNASSIGNED; - lpn->recv_win = 0; - lpn->queue_size = 0; - return err; - } - - return 0; -} - -int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data; - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - uint16_t addr, counter; - - if (buf->om_len < sizeof(*msg)) { - BT_WARN("Too short Friend Clear Confirm"); - return -EINVAL; - } - - if (lpn->state != BT_MESH_LPN_CLEAR) { - BT_WARN("Ignoring unexpected Friend Clear Confirm"); - return 0; - } - - addr = sys_be16_to_cpu(msg->lpn_addr); - counter = sys_be16_to_cpu(msg->lpn_counter); - - BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter); - - if (addr != bt_mesh_primary_addr() || counter != lpn->lpn_counter) { - BT_WARN("Invalid parameters in Friend Clear Confirm"); - return 0; - } - - lpn->clear_success = 1; - clear_friendship(false, lpn->disable); - - return 0; -} - -static void lpn_group_add(uint16_t group) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - uint16_t *free_slot = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) { - if (lpn->groups[i] == group) { - atomic_clear_bit(lpn->to_remove, i); - return; - } - - if (!free_slot && lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) { - free_slot = &lpn->groups[i]; - } - } - - if (!free_slot) { - BT_WARN("Friend Subscription List exceeded!"); - return; - } - - *free_slot = group; - lpn->groups_changed = 1; -} - -static void lpn_group_del(uint16_t group) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - int i; - - for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) { - if (lpn->groups[i] == group) { - if (atomic_test_bit(lpn->added, i) || - atomic_test_bit(lpn->pending, i)) { - atomic_set_bit(lpn->to_remove, i); - lpn->groups_changed = 1; - } else { - lpn->groups[i] = BT_MESH_ADDR_UNASSIGNED; - } - } - } -} - -static inline int group_popcount(atomic_t *target) -{ -#if CONFIG_BT_MESH_LPN_GROUPS > 32 - int i, count = 0; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.lpn.added); i++) { - count += popcount(atomic_get(&target[i])); - } -#else - return popcount(atomic_get(target)); -#endif -} - -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 = lpn->sub->net_idx, - .app_idx = BT_MESH_KEY_UNUSED, - .addr = lpn->frnd, - .send_ttl = 0, - }; - struct bt_mesh_net_tx tx = { - .sub = lpn->sub, - .ctx = &ctx, - .src = bt_mesh_primary_addr(), - .xmit = POLL_XMIT, - .friend_cred = true, - }; - struct bt_mesh_ctl_friend_sub req; - size_t i, g; - - BT_DBG("op 0x%02x sent_req 0x%02x", op, lpn->sent_req); - - if (lpn->sent_req) { - return false; - } - - for (i = 0, g = 0; i < ARRAY_SIZE(lpn->groups); i++) { - if (lpn->groups[i] == BT_MESH_ADDR_UNASSIGNED) { - continue; - } - - if (op == TRANS_CTL_OP_FRIEND_SUB_ADD) { - if (atomic_test_bit(lpn->added, i)) { - continue; - } - } else { - if (!atomic_test_bit(lpn->to_remove, i)) { - continue; - } - } - - if (added_count + g >= lpn->queue_size) { - BT_WARN("Friend Queue Size exceeded"); - break; - } - - req.addr_list[g++] = sys_cpu_to_be16(lpn->groups[i]); - atomic_set_bit(lpn->pending, i); - - if (g == ARRAY_SIZE(req.addr_list)) { - break; - } - } - - if (g == 0) { - group_zero(lpn->pending); - return false; - } - - req.xact = lpn->xact_next++; - - if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, - &req_sent_cb, NULL) < 0) { - group_zero(lpn->pending); - return false; - } - - lpn->xact_pending = req.xact; - lpn->sent_req = op; - return true; -} - -static void update_timeout(struct bt_mesh_lpn *lpn) -{ - if (lpn->established) { - BT_WARN("No response from Friend during ReceiveWindow"); - bt_mesh_scan_disable(); - lpn_set_state(BT_MESH_LPN_ESTABLISHED); - k_work_reschedule(&lpn->timer, POLL_RETRY_TIMEOUT); - } else { - if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - bt_mesh_scan_disable(); - } - - if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { - BT_WARN("Retrying first Friend Poll"); - lpn->sent_req = 0U; - if (send_friend_poll() == 0) { - return; - } - } - - BT_ERR("Timed out waiting for first Friend Update"); - clear_friendship(false, false); - } -} - -static void lpn_timeout(struct ble_npl_event *work) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - -#if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG - BT_DBG("state: %s", state2str(lpn->state)); -#endif - - switch (lpn->state) { - case BT_MESH_LPN_DISABLED: - break; - case BT_MESH_LPN_CLEAR: - clear_friendship(false, bt_mesh.lpn.disable); - break; - case BT_MESH_LPN_TIMER: - BT_DBG("Starting to look for Friend nodes"); - lpn_set_state(BT_MESH_LPN_ENABLED); - if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - bt_mesh_scan_disable(); - } - /* fall through */ - case BT_MESH_LPN_ENABLED: - send_friend_req(lpn); - break; - case BT_MESH_LPN_REQ_WAIT: - bt_mesh_scan_enable(); - k_work_reschedule(&lpn->timer, - lpn->adv_duration + FRIEND_REQ_SCAN); - lpn_set_state(BT_MESH_LPN_WAIT_OFFER); - break; - case BT_MESH_LPN_WAIT_OFFER: - BT_WARN("No acceptable Friend Offers received"); - if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - bt_mesh_scan_disable(); - } - lpn->lpn_counter++; - lpn_set_state(BT_MESH_LPN_ENABLED); - lpn->sent_req = 0U; - k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); - break; - case BT_MESH_LPN_ESTABLISHED: - if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { - uint8_t req = lpn->sent_req; - - lpn->sent_req = 0U; - - if (!req || req == TRANS_CTL_OP_FRIEND_POLL) { - send_friend_poll(); - } else { - sub_update(req); - } - - break; - } - - BT_ERR("No response from Friend after %u retries", - lpn->req_attempts); - lpn->req_attempts = 0; - clear_friendship(false, false); - break; - case BT_MESH_LPN_RECV_DELAY: - k_work_reschedule(&lpn->timer, - lpn->adv_duration + SCAN_LATENCY + - lpn->recv_win); - bt_mesh_scan_enable(); - lpn_set_state(BT_MESH_LPN_WAIT_UPDATE); - break; - case BT_MESH_LPN_WAIT_UPDATE: - update_timeout(lpn); - break; - default: - __ASSERT(0, "Unhandled LPN state"); - break; - } -} - -void bt_mesh_lpn_group_add(uint16_t group) -{ - BT_DBG("group 0x%04x", group); - - lpn_group_add(group); - - if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) { - return; - } - - sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD); -} - -void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count) -{ - int i; - - for (i = 0; i < group_count; i++) { - if (groups[i] != BT_MESH_ADDR_UNASSIGNED) { - BT_DBG("group 0x%04x", groups[i]); - lpn_group_del(groups[i]); - } - } - - if (!bt_mesh_lpn_established() || bt_mesh.lpn.sent_req) { - return; - } - - sub_update(TRANS_CTL_OP_FRIEND_SUB_REM); -} - -int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - struct bt_mesh_ctl_friend_sub_confirm *msg = (void *)buf->om_data; - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - - if (buf->om_len < sizeof(*msg)) { - BT_WARN("Too short Friend Subscription Confirm"); - return -EINVAL; - } - - BT_DBG("xact 0x%02x", msg->xact); - - if (!lpn->sent_req) { - BT_WARN("No pending subscription list message"); - return 0; - } - - if (msg->xact != lpn->xact_pending) { - BT_WARN("Transaction mismatch (0x%02x != 0x%02x)", - msg->xact, lpn->xact_pending); - return 0; - } - - if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_ADD) { - group_set(lpn->added, lpn->pending); - group_zero(lpn->pending); - } else if (lpn->sent_req == TRANS_CTL_OP_FRIEND_SUB_REM) { - int i; - - group_clear(lpn->added, lpn->pending); - - for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) { - if (atomic_test_and_clear_bit(lpn->pending, i) && - atomic_test_and_clear_bit(lpn->to_remove, i)) { - lpn->groups[i] = BT_MESH_ADDR_UNASSIGNED; - } - } - } else { - BT_WARN("Unexpected Friend Subscription Confirm"); - return 0; - } - - friend_response_received(lpn); - - if (lpn->groups_changed) { - sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD); - sub_update(TRANS_CTL_OP_FRIEND_SUB_REM); - - if (!lpn->sent_req) { - lpn->groups_changed = 0; - } - } - - if (lpn->pending_poll) { - send_friend_poll(); - } - - return 0; -} - -int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - 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; - uint32_t iv_index; - - if (buf->om_len < sizeof(*msg)) { - BT_WARN("Too short Friend Update"); - return -EINVAL; - } - - if (lpn->sent_req != TRANS_CTL_OP_FRIEND_POLL) { - BT_WARN("Unexpected friend update"); - return 0; - } - - if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !rx->new_key) { - BT_WARN("Ignoring Phase 2 KR Update secured using old key"); - return 0; - } - - 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(msg->flags))) { - bt_mesh_beacon_ivu_initiator(false); - } - - if (!lpn->established) { - /* This is normally checked on the transport layer, however - * in this state we're also still accepting flooding - * credentials so we need to ensure the right ones (Friend - * Credentials) were used for this message. - */ - if (!rx->friend_cred) { - BT_WARN("Friend Update with wrong credentials"); - return -EINVAL; - } - - lpn->established = 1; - - BT_INFO("Friendship established with 0x%04x", lpn->frnd); - - bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER); - - if (lpn_cb) { - lpn_cb(lpn->frnd, true); - } - - /* Set initial poll timeout */ - lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn), - POLL_TIMEOUT_INIT); - } - - friend_response_received(lpn); - - iv_index = sys_be32_to_cpu(msg->iv_index); - - BT_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags, - (unsigned) iv_index, msg->md); - - 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) { - sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD); - sub_update(TRANS_CTL_OP_FRIEND_SUB_REM); - - if (!lpn->sent_req) { - lpn->groups_changed = 0; - } - } - - if (msg->md) { - BT_DBG("Requesting for more messages"); - send_friend_poll(); - } - - return 0; -} - -int bt_mesh_lpn_poll(void) -{ - if (!bt_mesh.lpn.established) { - return -EAGAIN; - } - - BT_DBG("Requesting more messages"); - - return send_friend_poll(); -} - -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(""); - - k_work_init_delayable(&lpn->timer, lpn_timeout); - - if (lpn->state == BT_MESH_LPN_ENABLED) { - if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - bt_mesh_scan_disable(); - } else { - bt_mesh_scan_enable(); - } - - send_friend_req(lpn); - } else { - bt_mesh_scan_enable(); - - if (IS_ENABLED(CONFIG_BT_MESH_LPN_AUTO)) { - BT_DBG("Waiting %u ms for messages", LPN_AUTO_TIMEOUT); - lpn_set_state(BT_MESH_LPN_TIMER); - k_work_reschedule(&lpn->timer, LPN_AUTO_TIMEOUT); - } - } - - return 0; -} - -#endif /* MYNEWT_VAL(BLE_MESH_LOW_POWER) */ diff --git a/src/nimble/nimble/host/mesh/src/lpn.h b/src/nimble/nimble/host/mesh/src/lpn.h deleted file mode 100644 index 3abbc7057..000000000 --- a/src/nimble/nimble/host/mesh/src/lpn.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __LPN_H__ -#define __LPN_H__ - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf); -int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf); -int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf); -int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx, - struct os_mbuf *buf); - -static inline bool bt_mesh_lpn_established(void) -{ -#if (MYNEWT_VAL(BLE_MESH_LOW_POWER)) - return bt_mesh.lpn.established; -#else - return false; -#endif -} - -static inline bool bt_mesh_lpn_match(uint16_t addr) -{ -#if (MYNEWT_VAL(BLE_MESH_LOW_POWER)) - if (bt_mesh_lpn_established()) { - return (addr == bt_mesh.lpn.frnd); - } -#endif - return false; -} - -static inline bool bt_mesh_lpn_waiting_update(void) -{ -#if (MYNEWT_VAL(BLE_MESH_LOW_POWER)) - return (bt_mesh.lpn.state == BT_MESH_LPN_WAIT_UPDATE); -#else - return false; -#endif -} - -void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx); - -void bt_mesh_lpn_group_add(uint16_t group); -void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count); - -void bt_mesh_lpn_disable(bool force); - -int bt_mesh_lpn_init(void); - -#endif diff --git a/src/nimble/nimble/host/mesh/src/mesh.c b/src/nimble/nimble/host/mesh/src/mesh.c deleted file mode 100644 index 305e1fdb0..000000000 --- a/src/nimble/nimble/host/mesh/src/mesh.c +++ /dev/null @@ -1,420 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_LOG - -#include -#include - -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/include/host/ble_uuid.h" - -#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" -#include "transport.h" -#include "access.h" -#include "foundation.h" -#include "proxy.h" -#include "heartbeat.h" -#include "shell.h" -#include "mesh_priv.h" -#include "settings.h" -#include "pb_gatt_srv.h" - - -uint8_t g_mesh_addr_type; -static struct ble_gap_event_listener mesh_event_listener; - -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]) -{ - int err; - - BT_INFO("Primary Element: 0x%04x", addr); - BT_DBG("net_idx 0x%04x flags 0x%02x iv_index 0x%04x", - net_idx, flags, (unsigned) iv_index); - - if (atomic_test_and_set_bit(bt_mesh.flags, BT_MESH_VALID)) { - return -EALREADY; - } - - /* - * FIXME: - * Should net_key and iv_index be over-ridden? - */ - if (IS_ENABLED(CONFIG_BT_MESH_CDB) && - atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID)) { - const struct bt_mesh_comp *comp; - const struct bt_mesh_prov *prov; - struct bt_mesh_cdb_node *node; - - 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_cdb_node_store(node); - } - } - - err = bt_mesh_net_create(net_idx, flags, net_key, iv_index); - if (err) { - atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); - - return err; - } - - bt_mesh.seq = 0; - - bt_mesh_comp_provision(addr); - - memcpy(bt_mesh.dev_key, dev_key, 16); - - 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); - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_net_pending_net_store(); - } - - bt_mesh_start(); - - return 0; -} - -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; - } - - if (bt_mesh_subnet_get(net_idx) == NULL) { - return -EINVAL; - } - - if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) && - IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) { - return bt_mesh_pb_adv_open(uuid, net_idx, addr, - attention_duration); - } - - return -ENOTSUP; -} - -void bt_mesh_reset(void) -{ - if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - return; - } - - bt_mesh.iv_index = 0U; - bt_mesh.ivu_duration = 0; - bt_mesh.seq = 0U; - - memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags)); - - k_work_cancel_delayable(&bt_mesh.ivu_timer); - - bt_mesh_model_reset(); - bt_mesh_cfg_default_set(); - 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_friends_clear(); - } - - if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) { - (void)bt_mesh_proxy_gatt_disable(); - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_net_clear(); - } - - memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key)); - - bt_mesh_scan_disable(); - bt_mesh_beacon_disable(); - - bt_mesh_comp_unprovision(); - - if (IS_ENABLED(CONFIG_BT_MESH_PROV)) { - bt_mesh_prov_reset(); - } -} - -bool bt_mesh_is_provisioned(void) -{ - return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID); -} - - -static int bt_mesh_gap_event(struct ble_gap_event *event, void *arg) -{ - ble_adv_gap_mesh_cb(event, arg); - -#if (MYNEWT_VAL(BLE_MESH_PROXY)) - ble_mesh_proxy_gap_event(event, arg); -#endif - - return 0; -} - -static void model_suspend(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->count = 0; - /* If this fails, the work handler will check the suspend call - * and exit without transmitting. - */ - (void)k_work_cancel_delayable(&mod->pub->timer); - } -} - -int bt_mesh_suspend(void) -{ - int err; - - if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - return -EINVAL; - } - - if (atomic_test_and_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) { - return -EALREADY; - } - - err = bt_mesh_scan_disable(); - if (err) { - atomic_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED); - BT_WARN("Disabling scanning failed (err %d)", err); - return err; - } - - bt_mesh_hb_suspend(); - - if (bt_mesh_beacon_enabled()) { - bt_mesh_beacon_disable(); - } - - bt_mesh_model_foreach(model_suspend, NULL); - - return 0; -} - -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) { - int32_t period_ms = bt_mesh_model_pub_period_get(mod); - - if (period_ms) { - k_work_reschedule(&mod->pub->timer, - K_MSEC(period_ms)); - } - } -} - -int bt_mesh_resume(void) -{ - int err; - - if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - return -EINVAL; - } - - if (!atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_SUSPENDED)) { - return -EALREADY; - } - - err = bt_mesh_scan_enable(); - if (err) { - BT_WARN("Re-enabling scanning failed (err %d)", err); - atomic_set_bit(bt_mesh.flags, BT_MESH_SUSPENDED); - return err; - } - - bt_mesh_hb_resume(); - - if (bt_mesh_beacon_enabled()) { - bt_mesh_beacon_enable(); - } - - bt_mesh_model_foreach(model_resume, NULL); - - return err; -} - -int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, - const struct bt_mesh_comp *comp) -{ - int err; - - g_mesh_addr_type = own_addr_type; - - /* initialize SM alg ECC subsystem (it is used directly from mesh code) */ - na_ble_sm_alg_ecc_init(); - - err = bt_mesh_comp_register(comp); - if (err) { - 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) { - return err; - } -#endif - - bt_mesh_app_key_init(); - bt_mesh_access_init(); - bt_mesh_hb_pub_init(); - bt_mesh_rpl_init(); - bt_mesh_net_key_init(); -#if CONFIG_BT_MESH_LABEL_COUNT > 0 - bt_mesh_va_init(); -#endif -#if CONFIG_BT_MESH_CDB - bt_mesh_cdb_init(); -#endif - bt_mesh_cfg_default_set(); - 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_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) -{ - int err; - - err = bt_mesh_adv_enable(); - if (err) { - BT_ERR("Failed enabling advertiser"); - return err; - } - - if (bt_mesh_beacon_enabled()) { - bt_mesh_beacon_enable(); - } else { - bt_mesh_beacon_disable(); - } - - if (!IS_ENABLED(CONFIG_BT_MESH_PROV) || !bt_mesh_prov_active() || - bt_mesh_prov_link.bearer->type == BT_MESH_PROV_ADV) { - if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - (void)bt_mesh_pb_gatt_disable(); - } - - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - (void)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 /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/mesh_priv.h b/src/nimble/nimble/host/mesh/src/mesh_priv.h deleted file mode 100644 index 213f54377..000000000 --- a/src/nimble/nimble/host/mesh/src/mesh_priv.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef __MESH_PRIV_H -#define __MESH_PRIV_H - -#include -#include - -#define BT_MESH_KEY_PRIMARY 0x0000 -#define BT_MESH_KEY_ANY 0xffff - -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) -#define OP_GEN_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03) -#define OP_GEN_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04) -#define OP_GEN_LEVEL_GET BT_MESH_MODEL_OP_2(0x82, 0x05) -#define OP_GEN_LEVEL_SET BT_MESH_MODEL_OP_2(0x82, 0x06) -#define OP_GEN_LEVEL_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x07) -#define OP_GEN_LEVEL_STATUS BT_MESH_MODEL_OP_2(0x82, 0x08) -#define OP_GEN_DELTA_SET BT_MESH_MODEL_OP_2(0x82, 0x09) -#define OP_GEN_DELTA_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x0a) -#define OP_GEN_MOVE_SET BT_MESH_MODEL_OP_2(0x82, 0x0b) -#define OP_GEN_MOVE_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x0c) -#define OP_LIGHT_LIGHTNESS_GET BT_MESH_MODEL_OP_2(0x82, 0x4b) -#define OP_LIGHT_LIGHTNESS_SET BT_MESH_MODEL_OP_2(0x82, 0x4c) -#define OP_LIGHT_LIGHTNESS_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x4d) -#define OP_LIGHT_LIGHTNESS_STATUS BT_MESH_MODEL_OP_2(0x82, 0x4e) - -bool bt_mesh_is_provisioned(void); - -#endif diff --git a/src/nimble/nimble/host/mesh/src/model_cli.c b/src/nimble/nimble/host/mesh/src/model_cli.c deleted file mode 100644 index 347e898a2..000000000 --- a/src/nimble/nimble/host/mesh/src/model_cli.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) -#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/mesh/include/mesh/model_cli.h" -#include "mesh_priv.h" - -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 uint8_t transaction_id = 0; - -struct gen_onoff_param { - uint8_t *state; -}; - -struct gen_level_param { - int16_t *level; -}; - -static int gen_onoff_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_gen_model_cli *cli = model->user_data; - struct gen_onoff_param *param; - uint8_t state; - - - 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_GEN_ONOFF_STATUS) { - BT_WARN("Unexpected Generic OnOff Status message"); - return -ENOENT; - } - - param = cli->op_param; - - state = net_buf_simple_pull_u8(buf); - if (param->state) { - *param->state = state; - } - - BT_DBG("state: %d", state); - - k_sem_give(&cli->op_sync); - - return 0; -} - -static int gen_level_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_gen_model_cli *cli = model->user_data; - struct gen_level_param *param; - int16_t level; - - - 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_GEN_LEVEL_STATUS) { - BT_WARN("Unexpected Generic LEVEL Status message"); - return -EINVAL; - } - - param = cli->op_param; - - level = net_buf_simple_pull_le16(buf); - if (param->level) { - *param->level = level; - } - - BT_DBG("level: %d", level); - - k_sem_give(&cli->op_sync); - - return 0; -} - -const struct bt_mesh_model_op gen_onoff_cli_op[] = { - { OP_GEN_ONOFF_STATUS, 1, gen_onoff_status }, - BT_MESH_MODEL_OP_END, -}; - -static int onoff_cli_init(struct bt_mesh_model *model) -{ - BT_DBG(""); - - if (!model->user_data) { - BT_ERR("No Generic OnOff Client context provided"); - return -EINVAL; - } - - gen_onoff_cli = model->user_data; - gen_onoff_cli->model = model; - - k_sem_init(&gen_onoff_cli->op_sync, 0, 1); - - return 0; -} - -const struct bt_mesh_model_cb bt_mesh_gen_onoff_cli_cb = { - .init = onoff_cli_init, -}; - -const struct bt_mesh_model_op gen_level_cli_op[] = { - { OP_GEN_LEVEL_STATUS, 2, gen_level_status }, - BT_MESH_MODEL_OP_END, -}; - -static int level_cli_init(struct bt_mesh_model *model) -{ - BT_DBG(""); - - if (!model->user_data) { - BT_ERR("No Generic Level Client context provided"); - return -EINVAL; - } - - gen_level_cli = model->user_data; - gen_level_cli->model = model; - - k_sem_init(&gen_level_cli->op_sync, 0, 1); - - return 0; -} - -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, uint32_t op) -{ - int err; - - BT_DBG(""); - - cli->op_param = param; - cli->op_pending = op; - - err = k_sem_take(&cli->op_sync, msg_timeout); - - cli->op_pending = 0; - cli->op_param = NULL; - - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct gen_onoff_param param = { - .state = state, - }; - int err; - - bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_GET); - - err = bt_mesh_model_send(gen_onoff_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - goto done; - } - - err = cli_wait(gen_onoff_cli, ¶m, OP_GEN_ONOFF_STATUS); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct gen_onoff_param param = { - .state = state, - }; - int err; - - if (state) { - bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET); - } else { - bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_SET_UNACK); - } - - net_buf_simple_add_u8(msg, val); - net_buf_simple_add_u8(msg, transaction_id); - - err = bt_mesh_model_send(gen_onoff_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - goto done; - } - - if (!state) { - goto done; - } - - err = cli_wait(gen_onoff_cli, ¶m, OP_GEN_ONOFF_STATUS); -done: - if (err == 0) { - transaction_id++; - } - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct gen_level_param param = { - .level = level, - }; - int err; - - bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_GET); - - err = bt_mesh_model_send(gen_level_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - goto done; - } - - err = cli_wait(gen_level_cli, ¶m, OP_GEN_LEVEL_STATUS); -done: - os_mbuf_free_chain(msg); - return err; -} - -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 = { - .net_idx = net_idx, - .app_idx = app_idx, - .addr = addr, - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct gen_level_param param = { - .level = state, - }; - int err; - - if (state) { - bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_SET); - } else { - bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_SET_UNACK); - } - - net_buf_simple_add_le16(msg, val); - net_buf_simple_add_u8(msg, transaction_id); - - err = bt_mesh_model_send(gen_level_cli->model, &ctx, msg, NULL, NULL); - if (err) { - BT_ERR("model_send() failed (err %d)", err); - goto done; - } - - if (!state) { - goto done; - } - - err = cli_wait(gen_level_cli, ¶m, OP_GEN_LEVEL_STATUS); -done: - if (err == 0) { - transaction_id++; - } - os_mbuf_free_chain(msg); - return err; -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/model_srv.c b/src/nimble/nimble/host/mesh/src/model_srv.c deleted file mode 100644 index a299919ba..000000000 --- a/src/nimble/nimble/host/mesh/src/model_srv.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_MODEL_LOG - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/mesh/include/mesh/model_srv.h" -#include "mesh_priv.h" - -static struct bt_mesh_gen_onoff_srv *gen_onoff_srv; -static struct bt_mesh_gen_level_srv *gen_level_srv; -static struct bt_mesh_light_lightness_srv *light_lightness_srv; - -static int gen_onoff_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) -{ - int err; - struct bt_mesh_gen_onoff_srv *cb = model->user_data; - struct os_mbuf *msg = NET_BUF_SIMPLE(3); - uint8_t *state; - - bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_STATUS); - state = net_buf_simple_add(msg, 1); - if (cb && cb->get) { - cb->get(model, state); - } - - BT_DBG("state: %d", *state); - - err = bt_mesh_model_send(model, ctx, msg, NULL, NULL); - if (err) { - BT_ERR("Send status failed"); - } - - os_mbuf_free_chain(msg); - - return err; -} - -static int gen_onoff_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG(""); - - return gen_onoff_status(model, ctx); -} - -static int gen_onoff_set_unack(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_gen_onoff_srv *cb = model->user_data; - uint8_t state; - - state = buf->om_data[0]; - - BT_DBG("state: %d", state); - - if (cb && cb->set) { - return cb->set(model, state); - } - - return 0; -} - -static int gen_onoff_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG(""); - - gen_onoff_set_unack(model, ctx, buf); - return gen_onoff_status(model, ctx); -} - -static int gen_level_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) -{ - int err; - struct bt_mesh_gen_level_srv *cb = model->user_data; - struct os_mbuf *msg = NET_BUF_SIMPLE(4); - int16_t *level; - - bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_STATUS); - level = net_buf_simple_add(msg, 2); - if (cb && cb->get) { - cb->get(model, level); - } - - BT_DBG("level: %d", *level); - - err = bt_mesh_model_send(model, ctx, msg, NULL, NULL); - if (err) { - BT_ERR("Send status failed"); - } - - os_mbuf_free_chain(msg); - return err; -} - -static int gen_level_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG(""); - - return gen_level_status(model, ctx); -} - -static int gen_level_set_unack(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) { - struct bt_mesh_gen_level_srv *cb = model->user_data; - int16_t level; - - level = (int16_t) net_buf_simple_pull_le16(buf); - BT_DBG("level: %d", level); - - if (cb && cb->set) { - return cb->set(model, level); - } - - return 0; -} - -static int gen_level_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - gen_level_set_unack(model, ctx, buf); - return gen_level_status(model, ctx); -} - -static int light_lightness_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx) -{ - int err; - struct bt_mesh_light_lightness_srv *cb = model->user_data; - struct os_mbuf *msg = NET_BUF_SIMPLE(4); - int16_t *lightness; - - bt_mesh_model_msg_init(msg, OP_LIGHT_LIGHTNESS_STATUS); - lightness = net_buf_simple_add(msg, 2); - if (cb && cb->get) { - cb->get(model, lightness); - } - - BT_DBG("lightness: %d", *lightness); - - err = bt_mesh_model_send(model, ctx, msg, NULL, NULL); - if (err) { - BT_ERR("Send status failed"); - } - - os_mbuf_free_chain(msg); - return err; -} - -static int light_lightness_get(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - BT_DBG(""); - - return light_lightness_status(model, ctx); -} - -static int light_lightness_set_unack(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) { - struct bt_mesh_light_lightness_srv *cb = model->user_data; - int16_t lightness; - - lightness = (int16_t) net_buf_simple_pull_le16(buf); - BT_DBG("lightness: %d", lightness); - - if (cb && cb->set) { - return cb->set(model, lightness); - } - - return 0; -} - -static int light_lightness_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - light_lightness_set_unack(model, ctx, buf); - return light_lightness_status(model, ctx); -} - -const struct bt_mesh_model_op gen_onoff_srv_op[] = { - { OP_GEN_ONOFF_GET, 0, gen_onoff_get }, - { OP_GEN_ONOFF_SET, 2, gen_onoff_set }, - { OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set_unack }, - BT_MESH_MODEL_OP_END, -}; - -const struct bt_mesh_model_op gen_level_srv_op[] = { - { OP_GEN_LEVEL_GET, 0, gen_level_get }, - { OP_GEN_LEVEL_SET, 3, gen_level_set }, - { OP_GEN_LEVEL_SET_UNACK, 3, gen_level_set_unack }, - BT_MESH_MODEL_OP_END, -}; - -const struct bt_mesh_model_op light_lightness_srv_op[] = { - { OP_LIGHT_LIGHTNESS_GET, 0, light_lightness_get }, - { OP_LIGHT_LIGHTNESS_SET, 3, light_lightness_set }, - { OP_LIGHT_LIGHTNESS_SET_UNACK, 3, light_lightness_set_unack }, - BT_MESH_MODEL_OP_END, -}; - -static int onoff_srv_init(struct bt_mesh_model *model) -{ - struct bt_mesh_gen_onoff_srv *cfg = model->user_data; - - BT_DBG(""); - - if (!cfg) { - BT_ERR("No Generic OnOff Server context provided"); - return -EINVAL; - } - - cfg->model = model; - - gen_onoff_srv = cfg; - - return 0; -} - -const struct bt_mesh_model_cb gen_onoff_srv_cb = { - .init = onoff_srv_init, -}; - -static int level_srv_init(struct bt_mesh_model *model) -{ - struct bt_mesh_gen_level_srv *cfg = model->user_data; - - BT_DBG(""); - - if (!cfg) { - BT_ERR("No Generic Level Server context provided"); - return -EINVAL; - } - - cfg->model = model; - - gen_level_srv = cfg; - - return 0; -} - -const struct bt_mesh_model_cb gen_level_srv_cb = { - .init = level_srv_init, -}; - -static int lightness_srv_init(struct bt_mesh_model *model) -{ - struct bt_mesh_light_lightness_srv *cfg = model->user_data; - - BT_DBG(""); - - if (!cfg) { - BT_ERR("No Light Lightness Server context provided"); - return -EINVAL; - } - - cfg->model = model; - - light_lightness_srv = cfg; - - return 0; -} - -const struct bt_mesh_model_cb light_lightness_srv_cb = { - .init = lightness_srv_init, -}; - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/msg.c b/src/nimble/nimble/host/mesh/src/msg.c deleted file mode 100644 index 80753ac8d..000000000 --- a/src/nimble/nimble/host/mesh/src/msg.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode) -{ - net_buf_simple_init(msg, 0); - - switch (BT_MESH_MODEL_OP_LEN(opcode)) { - case 1: - net_buf_simple_add_u8(msg, opcode); - break; - case 2: - net_buf_simple_add_be16(msg, opcode); - break; - case 3: - net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff)); - /* Using LE for the CID since the model layer is defined as - * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3 - * will declare the opcode in this way. - */ - net_buf_simple_add_le16(msg, opcode & 0xffff); - break; - default: - BT_WARN("Unknown opcode format"); - break; - } -} - -void bt_mesh_msg_ack_ctx_clear(struct bt_mesh_msg_ack_ctx *ack) -{ - ack->op = 0U; - ack->user_data = NULL; - ack->dst = BT_MESH_ADDR_UNASSIGNED; -} - -int bt_mesh_msg_ack_ctx_prepare(struct bt_mesh_msg_ack_ctx *ack, - uint32_t op, uint16_t dst, void *user_data) -{ - if (ack->op) { - BT_WARN("Another synchronous operation pending"); - return -EBUSY; - } - - ack->op = op; - ack->user_data = user_data; - ack->dst = dst; - - return 0; -} - -int bt_mesh_msg_ack_ctx_wait(struct bt_mesh_msg_ack_ctx *ack, int32_t timeout) -{ - int err; - - err = k_sem_take(&ack->sem, timeout); - bt_mesh_msg_ack_ctx_clear(ack); - - if (err == -EAGAIN) { - return -ETIMEDOUT; - } - - return err; -} - -bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, - uint32_t op, uint16_t addr, void **user_data) -{ - if (ack->op != op || (BT_MESH_ADDR_IS_UNICAST(ack->dst) && ack->dst != addr)) { - return false; - } - - if (user_data != NULL) { - *user_data = ack->user_data; - } - - return true; -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/net.c b/src/nimble/nimble/host/mesh/src/net.c deleted file mode 100644 index f9dd1fc88..000000000 --- a/src/nimble/nimble/host/mesh/src/net.c +++ /dev/null @@ -1,1227 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_NET_LOG - -#include -#include -#include - -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" - -#include "crypto.h" -#include "adv.h" -#include "mesh_priv.h" -#include "net.h" -#include "rpl.h" -#include "lpn.h" -#include "friend.h" -#include "proxy.h" -#include "transport.h" -#include "access.h" -#include "foundation.h" -#include "beacon.h" -#include "settings.h" -#include "prov.h" -#include "cfg.h" -#include "nimble/nimble/host/mesh/include/mesh/glue.h" -#include "nimble/nimble/host/mesh/include/mesh/slist.h" - -#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 CONFIG_BT_MESH_IV_UPDATE_SEQ_LIMIT - -#define IVI(pdu) ((pdu)[0] >> 7) -#define NID(pdu) ((pdu)[0] & 0x7f) -#define CTL(pdu) ((pdu)[1] >> 7) -#define TTL(pdu) ((pdu)[1] & 0x7f) -#define SEQ(pdu) (sys_get_be24(&pdu[2])) -#define SRC(pdu) (sys_get_be16(&(pdu)[5])) -#define DST(pdu) (sys_get_be16(&(pdu)[7])) - -/** Define CONFIG_BT_MESH_SEQ_STORE_RATE even if settings are disabled to - * compile the code. - */ -#ifndef CONFIG_BT_SETTINGS -#define CONFIG_BT_MESH_SEQ_STORE_RATE 1 -#endif - -/* Mesh network information for persistent storage. */ -struct net_val { - uint16_t primary_addr; - uint8_t dev_key[16]; -} __packed; - -/* Sequence number information for persistent storage. */ -struct seq_val { - uint8_t val[3]; -} __packed; - -/* IV Index & IV Update information for persistent storage. */ -struct iv_val { - uint32_t iv_index; - uint8_t iv_update:1, - iv_duration:7; -} __packed; - -static struct { - uint32_t src : 15, /* MSb of source is always 0 */ - seq : 17; -} 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), -}; - -/* Mesh Profile Specification 3.10.6 - * The node shall not execute more than one IV Index Recovery within a period of - * 192 hours. - * - * Mark that the IV Index Recovery has been done to prevent two recoveries to be - * done before a normal IV Index update has been completed within 96h+96h. - */ -static bool ivi_was_recovered; - -static struct os_mbuf_pool loopback_os_mbuf_pool; -static struct os_mempool loopback_buf_mempool; -os_membuf_t loopback_mbuf_membuf[ - 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 uint8_t *tail = net_buf_simple_tail(data); - uint32_t val; - int i; - - val = sys_get_be32(tail - 4) ^ sys_get_be32(tail - 8); - - for (i = 0; i < ARRAY_SIZE(dup_cache); i++) { - if (dup_cache[i] == val) { - return true; - } - } - - dup_cache[dup_cache_next++] = val; - dup_cache_next %= ARRAY_SIZE(dup_cache); - - return false; -} - -static bool msg_cache_match(struct os_mbuf *pdu) -{ - uint16_t i; - - for (i = 0; i < ARRAY_SIZE(msg_cache); i++) { - if (msg_cache[i].src == SRC(pdu->om_data) && - msg_cache[i].seq == (SEQ(pdu->om_data) & BIT_MASK(17))) { - return true; - } - } - - return false; -} - -static void msg_cache_add(struct bt_mesh_net_rx *rx) -{ - /* 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); -} - -static void store_iv(bool only_duration) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_IV_PENDING); - - if (!only_duration) { - /* Always update Seq whenever IV changes */ - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); - } -#endif -} - -static void store_seq(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - if (CONFIG_BT_MESH_SEQ_STORE_RATE > 1 && - (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)) { - return; - } - - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); -#endif -} - -int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], - uint32_t iv_index) -{ - int err; - - 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; - - bt_mesh.iv_index = iv_index; - atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, - BT_MESH_IV_UPDATE(flags)); - - /* If IV Update is already in progress, set minimum required hours, - * since the 96-hour minimum requirement doesn't apply in this case straight - * after provisioning. - */ - if (BT_MESH_IV_UPDATE(flags)) { - bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS; - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - BT_DBG("Storing network information persistently"); - bt_mesh_subnet_store(idx); - store_iv(false); - } - - return 0; -} - -#if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST) -void bt_mesh_iv_update_test(bool enable) -{ - atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_TEST, enable); - /* Reset the duration variable - needed for some PTS tests */ - bt_mesh.ivu_duration = 0; -} - -bool bt_mesh_iv_update(void) -{ - if (!bt_mesh_is_provisioned()) { - BT_ERR("Not yet provisioned"); - return false; - } - - if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) { - bt_mesh_net_iv_update(bt_mesh.iv_index, false); - } else { - bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true); - } - - return atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); -} -#endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */ - -bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) -{ - if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) { - /* We're currently in IV Update mode */ - - if (iv_index != bt_mesh.iv_index) { - BT_WARN("IV Index mismatch: 0x%08x != 0x%08x", - (unsigned) iv_index, - (unsigned) bt_mesh.iv_index); - return false; - } - - if (iv_update) { - /* Nothing to do */ - BT_DBG("Already in IV Update in Progress state"); - return false; - } - } else { - /* We're currently in Normal mode */ - - if (iv_index == bt_mesh.iv_index) { - BT_DBG("Same IV Index in normal mode"); - return false; - } - - if (iv_index < bt_mesh.iv_index || - iv_index > bt_mesh.iv_index + 42) { - BT_ERR("IV Index out of sync: 0x%08x != 0x%08x", - (unsigned) iv_index, - (unsigned) bt_mesh.iv_index); - return false; - } - - if ((iv_index > bt_mesh.iv_index + 1) || - (iv_index == bt_mesh.iv_index + 1 && !iv_update)) { - if (ivi_was_recovered) { - BT_ERR("IV Index Recovery before minimum delay"); - return false; - } - /* The Mesh profile specification allows to initiate an - * IV Index Recovery procedure if previous IV update has - * been missed. This allows the node to remain - * functional. - */ - BT_WARN("Performing IV Index Recovery"); - ivi_was_recovered = true; - bt_mesh_rpl_clear(); - bt_mesh.iv_index = iv_index; - bt_mesh.seq = 0; - goto do_update; - } - } - - if (!(IS_ENABLED(CONFIG_BT_MESH_IV_UPDATE_TEST) && - atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_TEST))) { - if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) { - BT_WARN("IV Update before minimum duration"); - return false; - } - } - - /* Defer change to Normal Operation if there are pending acks */ - if (!iv_update && bt_mesh_tx_in_progress()) { - BT_WARN("IV Update deferred because of pending transfer"); - atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_PENDING); - return false; - } - - if (iv_update) { - bt_mesh.iv_index = iv_index; - BT_DBG("IV Update state entered. New index 0x%08x", - (unsigned) bt_mesh.iv_index); - - bt_mesh_rpl_reset(); - ivi_was_recovered = false; - } else { - BT_DBG("Normal mode entered"); - bt_mesh.seq = 0; - } - -do_update: - atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv_update); - bt_mesh.ivu_duration = 0U; - - k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); - - /* Notify other modules */ - if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { - bt_mesh_friend_sec_update(BT_MESH_KEY_ANY); - } - - bt_mesh_subnet_foreach(bt_mesh_beacon_update); - - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) { - bt_mesh_proxy_beacon_send(NULL); - } - - if (MYNEWT_VAL(BLE_MESH_CDB)) { - bt_mesh_cdb_iv_update(iv_index, iv_update); - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - store_iv(false); - } - - return true; -} - -uint32_t bt_mesh_next_seq(void) -{ - uint32_t seq = bt_mesh.seq++; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - store_seq(); - } - - if (!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) && - bt_mesh.seq > IV_UPDATE_SEQ_LIMIT && - 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); - } - - return seq; -} - -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))) { - 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); - os_mbuf_free_chain(buf); - } -} - -static const struct bt_mesh_net_cred *net_tx_cred_get(struct bt_mesh_net_tx *tx) -{ -#if IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) - if (tx->friend_cred && bt_mesh.lpn.frnd) { - 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); - - if (ctl && net_buf_simple_tailroom(buf) < 8) { - BT_ERR("Insufficient MIC space for CTL PDU"); - return -EINVAL; - } else if (net_buf_simple_tailroom(buf) < 4) { - BT_ERR("Insufficient MIC space for PDU"); - return -EINVAL; - } - - BT_DBG("src 0x%04x dst 0x%04x ctl %u seq 0x%06x", - tx->src, tx->ctx->addr, ctl, bt_mesh.seq); - - net_buf_simple_push_be16(buf, tx->ctx->addr); - net_buf_simple_push_be16(buf, tx->src); - - net_buf_simple_push_be24(buf, bt_mesh_next_seq()); - - if (ctl) { - net_buf_simple_push_u8(buf, tx->ctx->send_ttl | 0x80); - } else { - net_buf_simple_push_u8(buf, tx->ctx->send_ttl); - } - - net_buf_simple_push_u8(buf, (nid | (BT_MESH_NET_IVI_TX & 1) << 7)); - - 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, 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, BT_MESH_NET_HDR_LEN); - 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", - tx->src, tx->ctx->addr, buf->om_len, net_buf_headroom(buf), - net_buf_tailroom(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); - - cred = net_tx_cred_get(tx); - err = net_header_encode(tx, cred->nid, buf); - if (err) { - goto done; - } - - BT_DBG("encoded %u bytes: %s", buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - /* Deliver to local network interface if necessary */ - if (bt_mesh_fixed_group_match(tx->ctx->addr) || - bt_mesh_has_addr(tx->ctx->addr)) { - err = loopback(tx, buf->om_data, buf->om_len); - - /* Local unicast messages should not go out to network */ - if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) || - tx->ctx->send_ttl == 1U) { - if (!err) { - send_cb_finalize(cb, cb_data); - } - - goto done; - } - } - /* 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; - } - - BT_MESH_ADV(buf)->cb = cb; - BT_MESH_ADV(buf)->cb_data = cb_data; - - /* Deliver to GATT Proxy Clients if necessary. */ - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_proxy_relay(buf, tx->ctx->addr) && - BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - - err = 0; - goto done; - } - - bt_mesh_adv_send(buf, cb, cb_data); - -done: - net_buf_unref(buf); - return err; -} - -void bt_mesh_net_loopback_clear(uint16_t net_idx) -{ - struct net_buf_slist_t new_list; - struct os_mbuf *buf; - - 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_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); - - 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; - } - - rx->ctx.addr = SRC(out->om_data); - if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr)) { - BT_DBG("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr); - return false; - } - - if (bt_mesh_has_addr(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); - 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 - * if the Relay state is set to enabled. Locally originated packets always - * get sent to the advertising bearer. If the packet came in through GATT, - * then we should only relay it if the GATT Proxy state is enabled. - */ -static bool relay_to_adv(enum bt_mesh_net_if net_if) -{ - switch (net_if) { - case BT_MESH_NET_IF_ADV: - return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED); - case BT_MESH_NET_IF_PROXY: - return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED); - default: - return false; - } -} - -static void bt_mesh_net_relay(struct os_mbuf *sbuf, - struct bt_mesh_net_rx *rx) -{ - const struct bt_mesh_net_cred *cred; - struct os_mbuf *buf; - uint8_t transmit; - - 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; - } - - BT_DBG("TTL %u CTL %u dst 0x%04x", rx->ctx.recv_ttl, rx->ctl, - rx->ctx.recv_dst); - - /* The Relay Retransmit state is only applied to adv-adv relaying. - * Anything else (like GATT to adv, or locally originated packets) - * use the Network Transmit state. - */ - 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(); - } - - buf = bt_mesh_adv_create(BT_MESH_ADV_DATA, transmit, K_NO_WAIT); - if (!buf) { - BT_ERR("Out of relay buffers"); - return; - } - - /* 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); - - 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] |= 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 (net_encrypt(buf, cred, BT_MESH_NET_IVI_RX(rx), false)) { - BT_ERR("Re-encrypting failed"); - goto done; - } - - BT_DBG("encoded %u bytes: %s", buf->om_len, - bt_hex(buf->om_data, buf->om_len)); - - /* When the Friend node relays message for lpn, the message will be - * retransmitted using the managed flooding security credentials and - * the Network PDU shall be retransmitted to all network interfaces. - */ - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - (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) || rx->friend_cred) { - bt_mesh_adv_send(buf, NULL, NULL); - } - -done: - net_buf_unref(buf); -} - -void bt_mesh_net_header_parse(struct os_mbuf *buf, - struct bt_mesh_net_rx *rx) -{ - rx->old_iv = (IVI(buf->om_data) != (bt_mesh.iv_index & 0x01)); - rx->ctl = CTL(buf->om_data); - rx->ctx.recv_ttl = TTL(buf->om_data); - rx->seq = SEQ(buf->om_data); - rx->ctx.addr = SRC(buf->om_data); - rx->ctx.recv_dst = DST(buf->om_data); -} - -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 (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 (in->om_len > BT_MESH_NET_MAX_PDU_LEN) { - BT_WARN("Dropping too long mesh packet (len %u)", in->om_len); - return -EINVAL; - } - - if (net_if == BT_MESH_NET_IF_ADV && check_dup(in)) { - BT_DBG("duplicate packet; dropping %u bytes: %s", in->om_len, - bt_hex(in->om_data, in->om_len)); - return -EINVAL; - } - - BT_DBG("%u bytes: %s", in->om_len, bt_hex(in->om_data, in->om_len)); - - rx->net_if = net_if; - - if (!bt_mesh_net_cred_find(rx, in, out, net_decrypt)) { - BT_DBG("Unable to find matching net for packet"); - return -ENOENT; - } - - /* Initialize AppIdx to a sane value */ - rx->ctx.app_idx = BT_MESH_KEY_UNUSED; - - rx->ctx.recv_ttl = TTL(out->om_data); - - /* Default to responding with TTL 0 for non-routed messages */ - if (rx->ctx.recv_ttl == 0) { - rx->ctx.send_ttl = 0; - } else { - rx->ctx.send_ttl = BT_MESH_TTL_DEFAULT; - } - - 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", 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) { - BT_ERR("Destination address is unassigned; dropping 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(out->om_data, out->om_len)); - - msg_cache_add(rx); - - return 0; -} - -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(BT_MESH_NET_MAX_PDU_LEN); - struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi }; - struct net_buf_simple_state state; - - BT_DBG("rssi %d net_if %u", rssi, net_if); - - if (!bt_mesh_is_provisioned()) { - BT_ERR("Not provisioned; dropping packet"); - goto done; - } - - if (bt_mesh_net_decode(data, net_if, &rx, buf)) { - goto done; - } - - /* Save the state so the buffer can later be relayed */ - net_buf_simple_save(buf, &state); - - rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) || - bt_mesh_has_addr(rx.ctx.recv_dst)); - - if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY)) && - net_if == BT_MESH_NET_IF_PROXY) { - bt_mesh_proxy_addr_add(data, rx.ctx.addr); - - if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_DISABLED && - !rx.local_match) { - BT_INFO("Proxy is disabled; ignoring message"); - goto done; - } - } - - /* The transport layer has indicated that it has rejected the message, - * but would like to see it again if it is received in the future. - * This can happen if a message is received when the device is in - * Low Power mode, but the message was not encrypted with the friend - * credentials. Remove it from the message cache so that we accept - * it again in the future. - */ - if (bt_mesh_trans_recv(buf, &rx) == -EAGAIN) { - BT_WARN("Removing rejected message from Network Message Cache"); - 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; - } - - /* Relay if this was a group/virtual address, or if the destination - * was neither a local element nor an LPN we're Friends for. - */ - if (!BT_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) || - (!rx.local_match && !rx.friend_match)) { - net_buf_simple_restore(buf, &state); - bt_mesh_net_relay(buf, &rx); - } - -done: - os_mbuf_free_chain(buf); -} - -static void ivu_refresh(struct ble_npl_event *work) -{ - if (!bt_mesh_is_provisioned()) { - return; - } - - bt_mesh.ivu_duration = MIN(UINT8_MAX, - bt_mesh.ivu_duration + BT_MESH_IVU_HOURS); - - BT_DBG("%s for %u hour%s", - atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ? - "IVU in Progress" : "IVU Normal mode", - bt_mesh.ivu_duration, bt_mesh.ivu_duration == 1 ? "" : "s"); - - if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) { - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - store_iv(true); - } - - k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); - return; - } - - if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) { - bt_mesh_beacon_ivu_initiator(true); - bt_mesh_net_iv_update(bt_mesh.iv_index, false); - } else if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - store_iv(true); - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static int net_set(int argc, char **argv, char *val) -{ - struct net_val net; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - if (!val) { - bt_mesh_comp_unprovision(); - memset(bt_mesh.dev_key, 0, sizeof(bt_mesh.dev_key)); - return 0; - } - - len = sizeof(net); - err = settings_bytes_from_str(val, &net, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(net)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(net)); - return -EINVAL; - } - - memcpy(bt_mesh.dev_key, net.dev_key, sizeof(bt_mesh.dev_key)); - bt_mesh_comp_provision(net.primary_addr); - - BT_DBG("Provisioned with primary address 0x%04x", net.primary_addr); - BT_DBG("Recovered DevKey %s", bt_hex(bt_mesh.dev_key, 16)); - - return 0; -} - -static int iv_set(int argc, char **argv, char *val) -{ - struct iv_val iv; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - if (!val) { - bt_mesh.iv_index = 0U; - atomic_clear_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); - return 0; - } - - len = sizeof(iv); - err = settings_bytes_from_str(val, &iv, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(iv)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(iv)); - return -EINVAL; - } - - bt_mesh.iv_index = iv.iv_index; - atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, iv.iv_update); - bt_mesh.ivu_duration = iv.iv_duration; - - BT_DBG("IV Index 0x%04x (IV Update Flag %u) duration %u hours", - (unsigned) iv.iv_index, iv.iv_update, iv.iv_duration); - - return 0; -} - -static int seq_set(int argc, char **argv, char *val) -{ - struct seq_val seq; - int len, err; - - BT_DBG("val %s", val ? val : "(null)"); - - if (!val) { - bt_mesh.seq = 0; - return 0; - } - - len = sizeof(seq); - err = settings_bytes_from_str(val, &seq, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(seq)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(seq)); - return -EINVAL; - } - - bt_mesh.seq = sys_get_le24(seq.val); - - if (CONFIG_BT_MESH_SEQ_STORE_RATE > 0) { - /* Make sure we have a large enough sequence number. We - * subtract 1 so that the first transmission causes a write - * to the settings storage. - */ - bt_mesh.seq += (CONFIG_BT_MESH_SEQ_STORE_RATE - - (bt_mesh.seq % CONFIG_BT_MESH_SEQ_STORE_RATE)); - bt_mesh.seq--; - } - - BT_DBG("Sequence Number 0x%06x", bt_mesh.seq); - - return 0; -} - -static struct conf_handler bt_mesh_net_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = net_set, - .ch_commit = NULL, - .ch_export = NULL, -}; - -static struct conf_handler bt_mesh_iv_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = iv_set, - .ch_commit = NULL, - .ch_export = NULL, -}; - -static struct conf_handler bt_mesh_seq_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = seq_set, - .ch_commit = NULL, - .ch_export = NULL, -}; -#endif - -void bt_mesh_net_init(void) -{ - int rc; - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - rc = conf_register(&bt_mesh_net_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_net conf"); - - - rc = conf_register(&bt_mesh_iv_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_iv conf"); - - rc = conf_register(&bt_mesh_seq_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_seq conf"); -#endif - - k_work_init_delayable(&bt_mesh.ivu_timer, ivu_refresh); - - k_work_init(&bt_mesh.local_work, bt_mesh_net_local); - net_buf_slist_init(&bt_mesh.local_queue); - - 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); -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static void clear_iv(void) -{ - int err; - - err = settings_save_one("bt_mesh/IV", NULL); - if (err) { - BT_ERR("Failed to clear IV"); - } else { - BT_DBG("Cleared IV"); - } -} - -static void store_pending_iv(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct iv_val))]; - struct iv_val iv; - char *str; - int err; - - iv.iv_index = bt_mesh.iv_index; - iv.iv_update = atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); - iv.iv_duration = bt_mesh.ivu_duration; - - str = settings_str_from_bytes(&iv, sizeof(iv), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode IV as value"); - return; - } - - BT_DBG("Saving IV as value %s", str); - err = settings_save_one("bt_mesh/IV", str); - if (err) { - BT_ERR("Failed to store IV"); - } else { - BT_DBG("Stored IV"); - } -} - -void bt_mesh_net_pending_iv_store(void) -{ - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - store_pending_iv(); - } else { - clear_iv(); - } -} - -static void clear_net(void) -{ - int err; - - err = settings_save_one("bt_mesh/Net", NULL); - if (err) { - BT_ERR("Failed to clear Network"); - } else { - BT_DBG("Cleared Network"); - } -} - -static void store_pending_net(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct net_val))]; - struct net_val net; - char *str; - int err; - - BT_DBG("addr 0x%04x DevKey %s", bt_mesh_primary_addr(), - bt_hex(bt_mesh.dev_key, 16)); - - net.primary_addr = bt_mesh_primary_addr(); - memcpy(net.dev_key, bt_mesh.dev_key, 16); - - str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Network as value"); - return; - } - - BT_DBG("Saving Network as value %s", str); - err = settings_save_one("bt_mesh/Net", str); - if (err) { - BT_ERR("Failed to store Network"); - } else { - BT_DBG("Stored Network"); - } -} - -void bt_mesh_net_pending_net_store(void) -{ - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - store_pending_net(); - } else { - clear_net(); - } -} - -void bt_mesh_net_pending_seq_store(void) -{ - char buf[BT_SETTINGS_SIZE(sizeof(struct seq_val))]; - char *str; - struct seq_val seq; - int err; - - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - sys_put_le24(bt_mesh.seq, seq.val); - - str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode Network as value"); - return; - } - - BT_DBG("Saving Network as value %s", str); - err = settings_save_one("bt_mesh/Seq", str); - if (err) { - BT_ERR("Failed to stor Seq value"); - } else { - BT_DBG("Stored Seq value"); - } - } else { - err = settings_save_one("bt_mesh/Seq", NULL); - if (err) { - BT_ERR("Failed to clear Seq value"); - } else { - BT_DBG("Cleared Seq value"); - } - } -} - -void bt_mesh_net_clear(void) -{ - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_NET_PENDING); - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_IV_PENDING); - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_CFG_PENDING); - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_SEQ_PENDING); -} -#endif - -void bt_mesh_net_settings_commit(void) -{ - if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) { - k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); - } -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/net.h b/src/nimble/nimble/host/mesh/src/net.h deleted file mode 100644 index e6b89cdaf..000000000 --- a/src/nimble/nimble/host/mesh/src/net.h +++ /dev/null @@ -1,328 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __NET_H__ -#define __NET_H__ - -#include "subnet.h" - -#define BT_MESH_IV_UPDATE(flags) ((flags >> 1) & 0x01) -#define BT_MESH_KEY_REFRESH(flags) (flags & 0x01) - -#include -#include "atomic.h" -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/mesh/include/mesh/glue.h" - -/* How many hours in between updating IVU duration */ -#define BT_MESH_IVU_MIN_HOURS 96 -#define BT_MESH_IVU_HOURS (BT_MESH_IVU_MIN_HOURS / \ - CONFIG_BT_MESH_IVU_DIVIDER) -#define BT_MESH_IVU_TIMEOUT K_HOURS(BT_MESH_IVU_HOURS) - -/* Minimum valid Mesh Network PDU length. The Network headers - * themselves take up 9 bytes. After that there is a minimum of 1 byte - * payload for both CTL=1 and CTL=0 PDUs (smallest OpCode is 1 byte). CTL=1 - * PDUs must use a 64-bit (8 byte) NetMIC, whereas CTL=0 PDUs have at least - * a 32-bit (4 byte) NetMIC and AppMIC giving again a total of 8 bytes. - */ -#define BT_MESH_NET_MIN_PDU_LEN (BT_MESH_NET_HDR_LEN + 1 + 8) -/* Maximum valid Mesh Network PDU length. The longest packet can either be a - * transport control message (CTL=1) of 12 bytes + 8 bytes of NetMIC, or an - * access message (CTL=0) of 16 bytes + 4 bytes of NetMIC. - */ -#define BT_MESH_NET_MAX_PDU_LEN (BT_MESH_NET_HDR_LEN + 16 + 4) - -struct bt_mesh_net_cred; - -struct bt_mesh_node { - uint16_t addr; - uint16_t net_idx; - uint8_t dev_key[16]; - uint8_t num_elem; -}; - -#if MYNEWT_VAL(BLE_MESH_FRIEND) -#define FRIEND_SEG_RX MYNEWT_VAL(BLE_MESH_FRIEND_SEG_RX) -#define FRIEND_SUB_LIST_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_SUB_LIST_SIZE) -#else -#define FRIEND_SEG_RX 0 -#define FRIEND_SUB_LIST_SIZE 0 -#endif - -struct bt_mesh_friend { - uint16_t lpn; - uint8_t recv_delay; - uint8_t fsn:1, - send_last:1, - pending_req:1, - pending_buf:1, - established:1; - int32_t poll_to; - uint8_t num_elem; - uint16_t lpn_counter; - uint16_t counter; - - struct bt_mesh_subnet *subnet; - - struct bt_mesh_net_cred cred[2]; - - uint16_t sub_list[FRIEND_SUB_LIST_SIZE]; - - struct k_work_delayable timer; - - struct bt_mesh_friend_seg { - struct net_buf_slist_t queue; - - /* The target number of segments, i.e. not necessarily - * the current number of segments, in the queue. This is - * used for Friend Queue free space calculations. - */ - uint8_t seg_count; - } seg[FRIEND_SEG_RX]; - - struct os_mbuf *last; - - struct net_buf_slist_t queue; - uint32_t queue_size; - - /* Friend Clear Procedure */ - struct { - uint32_t start; /* Clear Procedure start */ - uint16_t frnd; /* Previous Friend's address */ - uint16_t repeat_sec; /* Repeat timeout in seconds */ - struct k_work_delayable timer; /* Repeat timer */ - } clear; -}; - -#if (MYNEWT_VAL(BLE_MESH_LOW_POWER)) -#define LPN_GROUPS CONFIG_BT_MESH_LPN_GROUPS -#else -#define LPN_GROUPS 0 -#endif - -/* Low Power Node state */ -struct bt_mesh_lpn { - enum __packed { - BT_MESH_LPN_DISABLED, /* LPN feature is disabled */ - BT_MESH_LPN_CLEAR, /* Clear in progress */ - BT_MESH_LPN_TIMER, /* Waiting for auto timer expiry */ - BT_MESH_LPN_ENABLED, /* LPN enabled, but no Friend */ - BT_MESH_LPN_REQ_WAIT, /* Wait before scanning for offers */ - BT_MESH_LPN_WAIT_OFFER, /* Friend Req sent */ - BT_MESH_LPN_ESTABLISHED, /* Friendship established */ - BT_MESH_LPN_RECV_DELAY, /* Poll sent, waiting ReceiveDelay */ - BT_MESH_LPN_WAIT_UPDATE, /* Waiting for Update or message */ - } state; - - /* Transaction Number (used for subscription list) */ - 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. - */ - uint16_t frnd; - - /* Value from the friend offer */ - uint8_t recv_win; - - uint8_t req_attempts; /* Number of Request attempts */ - - int32_t poll_timeout; - - 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 */ - established:1, /* Friendship established */ - clear_success:1; /* Friend Clear Confirm received */ - - /* Friend Queue Size */ - uint8_t queue_size; - - /* FriendCounter */ - uint16_t frnd_counter; - - /* LPNCounter */ - uint16_t lpn_counter; - - /* Previous Friend of this LPN */ - uint16_t old_friend; - - /* Duration reported for last advertising packet */ - uint16_t adv_duration; - - /* Next LPN related action timer */ - struct k_work_delayable timer; - - /* Subscribed 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); - ATOMIC_DEFINE(pending, LPN_GROUPS); - ATOMIC_DEFINE(to_remove, LPN_GROUPS); -}; - -/* bt_mesh_net.flags */ -enum { - BT_MESH_VALID, /* We have been provisioned */ - BT_MESH_SUSPENDED, /* Network is temporarily suspended */ - BT_MESH_IVU_IN_PROGRESS, /* IV Update in Progress */ - BT_MESH_IVU_INITIATOR, /* IV Update initiated by us */ - BT_MESH_IVU_TEST, /* IV Update test mode */ - BT_MESH_IVU_PENDING, /* Update blocked by SDU in progress */ - - /* 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 { - uint32_t iv_index; /* Current IV Index */ - uint32_t seq; /* Next outgoing sequence number (24 bits) */ - - ATOMIC_DEFINE(flags, BT_MESH_FLAG_COUNT); - - /* Local network interface */ - struct ble_npl_callout local_work; - struct net_buf_slist_t local_queue; - -#if MYNEWT_VAL(BLE_MESH_FRIEND) - /* Friend state, unique for each LPN that we're Friends for */ - struct bt_mesh_friend frnd[MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT)]; -#endif - -#if (MYNEWT_VAL(BLE_MESH_LOW_POWER)) - struct bt_mesh_lpn lpn; /* Low Power Node state */ -#endif - - /* Number of hours in current IV Update state */ - 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_work_delayable ivu_timer; - - uint8_t dev_key[16]; -}; - -/* Network interface */ -enum bt_mesh_net_if { - BT_MESH_NET_IF_ADV, - BT_MESH_NET_IF_LOCAL, - BT_MESH_NET_IF_PROXY, - BT_MESH_NET_IF_PROXY_CFG, -}; - -/* Decoding context for Network/Transport data */ -struct bt_mesh_net_rx { - struct bt_mesh_subnet *sub; - struct bt_mesh_msg_ctx ctx; - 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 */ - 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; - uint16_t src; - uint8_t xmit; - uint8_t friend_cred:1, - aszmic:1, - aid:6; -}; - -extern struct bt_mesh_net bt_mesh; - -#define BT_MESH_NET_IVI_TX (bt_mesh.iv_index - \ - atomic_test_bit(bt_mesh.flags, \ - BT_MESH_IVU_IN_PROGRESS)) -#define BT_MESH_NET_IVI_RX(rx) (bt_mesh.iv_index - (rx)->old_iv) - -#define BT_MESH_NET_HDR_LEN 9 - -static inline void *net_buf_user_data(const struct os_mbuf *buf) -{ - /* In Zephyr at the end of net_buf (which is ported as os_mbuf) is place - * for user_data, which is array of octets, just like os_mbuf's om_data. Let's just - * use last octets (starting at start of om_data + total size of data mbuf can hold - - * intended user_data size) of om_data as Zephyr's user_data. - */ - return (void *)(buf->om_data + buf->om_omp->omp_databuf_len - MYNEWT_VAL(BLE_MESH_NET_BUF_USER_DATA_SIZE)); -} - -int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], - uint32_t iv_index); - -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); - -void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi, - enum bt_mesh_net_if net_if); - -void bt_mesh_net_loopback_clear(uint16_t net_idx); - -uint32_t bt_mesh_next_seq(void); - -void bt_mesh_net_init(void); -void bt_mesh_net_header_parse(struct os_mbuf *buf, - struct bt_mesh_net_rx *rx); -void bt_mesh_net_pending_net_store(void); -void bt_mesh_net_pending_iv_store(void); -void bt_mesh_net_pending_seq_store(void); -void bt_mesh_net_clear(void); -void bt_mesh_net_settings_commit(void); - -static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - if (!cb) { - return; - } - - if (cb->start) { - cb->start(0, 0, cb_data); - } - - if (cb->end) { - cb->end(0, cb_data); - } -} - -#endif diff --git a/src/nimble/nimble/host/mesh/src/pb_adv.c b/src/nimble/nimble/host/mesh/src/pb_adv.c deleted file mode 100644 index 8b7833e34..000000000 --- a/src/nimble/nimble/host/mesh/src/pb_adv.c +++ /dev/null @@ -1,922 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2020 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_PROV_LOG - -#include -#include -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include -#include "testing.h" -#include "net.h" -#include "prov.h" -#include "adv.h" -#include "crypto.h" -#include "beacon.h" -#include "nimble/nimble/host/mesh/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 RX_BUFFER_MAX 65 - -#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_OFFSET(_seg) (20 + ((_seg - 1) * 23)) -#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[XACT_SEG_OFFSET(_seg)]) -#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 -/* PDU acks: */ -#define RETRANSMITS_ACK 2 -/* Link close retransmits: */ -#define RETRANSMITS_LINK_CLOSE 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_work_delayable retransmit; - } tx; - - /* Protocol timeout */ - struct k_work_delayable 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 prov_link_close(enum prov_bearer_link_status status); -static void close_link(enum prov_bearer_link_status status); - -static void buf_sent(int err, void *user_data) -{ - BT_DBG("buf_send"); - - if (atomic_test_and_clear_bit(link.flags, ADV_LINK_CLOSING)) { - close_link(PROV_BEARER_LINK_STATUS_SUCCESS); - return; - } -} - -static void buf_start(uint16_t duration, int err, void *user_data) -{ - if (err) { - buf_sent(err, user_data); - } -} - -static struct bt_mesh_send_cb buf_sent_cb = { - .start = buf_start, - .end = buf_sent, -}; - -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(""); - - /* If this fails, the work handler will not find any buffers to send, - * and return without rescheduling. The work handler also checks the - * LINK_ACTIVE flag, so if this call is part of reset_adv_link, it'll - * exit early. - */ - (void)k_work_cancel_delayable(&link.tx.retransmit); - - free_segments(); -} - -static void reset_adv_link(void) -{ - BT_DBG(""); - prov_clear_tx(); - - /* If this fails, the work handler will exit early on the LINK_ACTIVE - * check. - */ - (void)k_work_cancel_delayable(&link.prot_timer); - - if (atomic_test_bit(link.flags, ADV_PROVISIONER)) { - /* Clear everything except the retransmit and protocol timer - * 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(RX_BUFFER_MAX); - } - 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_work_reschedule(&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) -{ - if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { - return; - } - - BT_DBG(""); - - link.rx.seg = 0U; - prov_link_close(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; - } - - if (XACT_SEG_OFFSET(seg) + buf->om_len > RX_BUFFER_MAX) { - BT_WARN("Rx buffer overflow. Malformed generic prov frame?"); - 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; - - 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)); - - bt_mesh_adv_send(buf, NULL, NULL); - } - - k_work_reschedule(&link.tx.retransmit, RETRANSMIT_TIMEOUT); -} - -static void prov_retransmit(struct ble_npl_event *work) -{ - BT_DBG(""); - - if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { - BT_WARN("Link not active"); - return; - } - - if (k_uptime_get() - link.tx.start > TRANSACTION_TIMEOUT) { - BT_WARN("Giving up transaction"); - prov_link_close(PROV_BEARER_LINK_STATUS_FAIL); - return; - } - - send_reliable(); -} - -static struct os_mbuf *ctl_buf_create(uint8_t op, const void *data, uint8_t data_len, - uint8_t retransmits) -{ - struct os_mbuf *buf; - - BT_DBG("op 0x%02x data_len %u", op, data_len); - - buf = adv_buf_create(retransmits); - if (!buf) { - return NULL; - } - - 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); - return buf; -} - -static int bearer_ctl_send(struct os_mbuf *buf) -{ - if (!buf) { - return -ENOMEM; - } - prov_clear_tx(); - k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); - - link.tx.start = k_uptime_get(); - link.tx.buf[0] = buf; - send_reliable(); - - return 0; - } - -static int bearer_ctl_send_unacked(struct os_mbuf *buf) -{ - if (!buf) { - return -ENOMEM; - } - - prov_clear_tx(); - k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); - - bt_mesh_adv_send(buf, &buf_sent_cb, NULL); - net_buf_unref(buf); - return 0; -} - -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_work_reschedule(&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; - link.tx.start = k_uptime_get(); - - 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) -{ - int err; - - 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("Ignoring bearer open: link already active"); - return; - } - - BT_DBG("Resending link ack"); - /* Ignore errors, message will be attempted again if we keep receiving link open: */ - (void)bearer_ctl_send_unacked(ctl_buf_create(LINK_ACK, NULL, 0, RETRANSMITS_ACK)); - return; - } - - 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); - - err = bearer_ctl_send_unacked(ctl_buf_create(LINK_ACK, NULL, 0, RETRANSMITS_ACK)); - if (err) { - reset_adv_link(); - return; - } - - link.cb->link_opened(&pb_adv, link.cb_data); -} - -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) -{ - int err; - - BT_DBG("uuid %s", bt_hex(uuid, 16)); - - err = bt_mesh_adv_enable(); - if (err) { - BT_ERR("Failed enabling advertiser"); - return err; - } - - if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACTIVE)) { - return -EBUSY; - } - - 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); - - return bearer_ctl_send(ctl_buf_create(LINK_OPEN, uuid, 16, RETRANSMITS_RELIABLE)); -} - -static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data) -{ - int err; - - err = bt_mesh_adv_enable(); - if (err) { - BT_ERR("Failed enabling advertiser"); - return err; - } - - if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { - return -EBUSY; - } - - 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 invitations */ - 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; - } - - /* Ignore errors, the link will time out eventually if this doesn't get sent */ - bearer_ctl_send_unacked(ctl_buf_create(LINK_CLOSE, &status, 1, RETRANSMITS_LINK_CLOSE)); -} - -void pb_adv_init(void) -{ - k_work_init_delayable(&link.prot_timer, protocol_timeout); - k_work_init_delayable(&link.tx.retransmit, prov_retransmit); - - if (!rx_buf) { - rx_buf = NET_BUF_SIMPLE(RX_BUFFER_MAX); - } - 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) */ diff --git a/src/nimble/nimble/host/mesh/src/pb_gatt.c b/src/nimble/nimble/host/mesh/src/pb_gatt.c deleted file mode 100644 index 78ad968c5..000000000 --- a/src/nimble/nimble/host/mesh/src/pb_gatt.c +++ /dev/null @@ -1,174 +0,0 @@ -/* 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/nimble/host/mesh/include/mesh/mesh.h" -#include "prov.h" -#include "net.h" -#include "proxy.h" -#include "adv.h" -#include "syscfg/syscfg.h" -#include "pb_gatt_srv.h" - -#if MYNEWT_VAL(BLE_MESH_PB_GATT) -struct prov_bearer_send_cb { - prov_bearer_send_complete_t cb; - void *cb_data; -}; - -struct prov_link { - uint16_t conn_handle; - const struct prov_bearer_cb *cb; - void *cb_data; - struct prov_bearer_send_cb comp; - struct { - uint8_t id; /* Transaction ID */ - uint8_t prev_id; /* Previous Transaction ID */ - uint8_t seg; /* Bit-field of unreceived segments */ - uint8_t last_seg; /* Last segment (to check length) */ - uint8_t fcs; /* Expected FCS value */ - } rx; - struct k_work_delayable prot_timer; -}; - -static struct prov_link link; - -static void reset_state(void) -{ - link.conn_handle = BLE_HS_CONN_HANDLE_NONE; - - /* If this fails, the protocol timeout handler will exit early. */ - (void)k_work_cancel_delayable(&link.prot_timer); -} - -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) -{ - if (!link.conn_handle) { - /* Already disconnected */ - return; - } - - 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_work_reschedule(&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_work_reschedule(&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) -{ - (void)bt_mesh_pb_gatt_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; - } - - link.comp.cb = cb; - link.comp.cb_data = cb_data; - - k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT); - - return bt_mesh_pb_gatt_send(link.conn_handle, buf); -} - -static void clear_tx(void) -{ - /* No action */ -} - -void pb_gatt_init(void) -{ - k_work_init_delayable(&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 diff --git a/src/nimble/nimble/host/mesh/src/pb_gatt_srv.c b/src/nimble/nimble/host/mesh/src/pb_gatt_srv.c deleted file mode 100644 index 3d3ee940e..000000000 --- a/src/nimble/nimble/host/mesh/src/pb_gatt_srv.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2021 Lingao Meng - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define MESH_LOG_MODULE BLE_MESH_PROV_LOG - -#include "mesh_priv.h" -#include "adv.h" -#include "net.h" -#include "rpl.h" -#include "transport.h" -#include "prov.h" -#include "beacon.h" -#include "foundation.h" -#include "access.h" -#include "proxy.h" -#include "proxy_msg.h" -#include "pb_gatt_srv.h" -#include "syscfg/syscfg.h" -#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" -#include "nimble/nimble/host/src/ble_hs_priv.h" - -#if defined(CONFIG_BT_MESH_PB_GATT_USE_DEVICE_NAME) -#define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME -#else -#define ADV_OPT_USE_NAME 0 -#endif - -#define ADV_OPT_PROV \ -.conn_mode = (BLE_GAP_CONN_MODE_UND), \ -.disc_mode = (BLE_GAP_DISC_MODE_GEN), - -#if MYNEWT_VAL(BLE_MESH_PB_GATT) -/** @def BT_UUID_MESH_PROV - * @brief Mesh Provisioning Service - */ -ble_uuid16_t BT_UUID_MESH_PROV = BLE_UUID16_INIT(0x1827); -#define BT_UUID_MESH_PROV_VAL 0x1827 -/** @def BT_UUID_MESH_PROXY - * @brief Mesh Proxy Service - */ -ble_uuid16_t BT_UUID_MESH_PROXY = BLE_UUID16_INIT(0x1828); -#define BT_UUID_MESH_PROXY_VAL 0x1828 -/** @def BT_UUID_GATT_CCC - * @brief GATT Client Characteristic Configuration - */ -ble_uuid16_t BT_UUID_GATT_CCC = BLE_UUID16_INIT(0x2902); -#define BT_UUID_GATT_CCC_VAL 0x2902 -/** @def BT_UUID_MESH_PROV_DATA_IN - * @brief Mesh Provisioning Data In - */ -ble_uuid16_t BT_UUID_MESH_PROV_DATA_IN = BLE_UUID16_INIT(0x2adb); -#define BT_UUID_MESH_PROV_DATA_IN_VAL 0x2adb -/** @def BT_UUID_MESH_PROV_DATA_OUT - * @brief Mesh Provisioning Data Out - */ -ble_uuid16_t BT_UUID_MESH_PROV_DATA_OUT = BLE_UUID16_INIT(0x2adc); -#define BT_UUID_MESH_PROV_DATA_OUT_VAL 0x2adc -/** @def BT_UUID_MESH_PROXY_DATA_IN - * @brief Mesh Proxy Data In - */ -ble_uuid16_t BT_UUID_MESH_PROXY_DATA_IN = BLE_UUID16_INIT(0x2add); -#define BT_UUID_MESH_PROXY_DATA_IN_VAL 0x2add -/** @def BT_UUID_MESH_PROXY_DATA_OUT - * @brief Mesh Proxy Data Out - */ -ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); -#define BT_UUID_MESH_PROXY_DATA_OUT_VAL 0x2ade -#define BT_UUID_16_ENCODE(w16) \ - (((w16) >> 0) & 0xFF), \ - (((w16) >> 8) & 0xFF) - -static bool prov_fast_adv; - -struct svc_handles svc_handles; -static atomic_t pending_notifications; - -static int gatt_send(uint16_t conn_handle, - const void *data, uint16_t len); - -static struct bt_mesh_proxy_role *cli; - -static void proxy_msg_recv(struct bt_mesh_proxy_role *role) -{ - switch (role->msg_type) { - case BT_MESH_PROXY_PROV: - BT_DBG("Mesh Provisioning PDU"); - bt_mesh_pb_gatt_recv(role->conn_handle, role->buf); - break; - default: - BT_WARN("Unhandled Message Type 0x%02x", role->msg_type); - break; - } -} - -static bool service_registered; - -static int gatt_recv_proxy(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - const uint8_t *data = ctxt->om->om_data; - uint16_t len = ctxt->om->om_len; - struct bt_mesh_proxy_client *client = find_client(conn_handle); - - if (len < 1) { - BT_WARN("Too small Proxy PDU"); - return -EINVAL; - } - - if (PDU_TYPE(data) == BT_MESH_PROXY_PROV) { - BT_WARN("Proxy PDU type doesn't match GATT service"); - return -EINVAL; - } - - return bt_mesh_proxy_msg_recv(client->cli, data, len); -} - -static int gatt_recv_prov(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - const uint8_t *data = ctxt->om->om_data; - uint16_t len = ctxt->om->om_len; - - if (conn_handle != cli->conn_handle) { - BT_WARN("conn_handle != cli->conn_handle"); - return -ENOTCONN; - } - - if (len < 1) { - BT_WARN("Too small Proxy PDU"); - return -EINVAL; - } - - if (PDU_TYPE(data) != BT_MESH_PROXY_PROV) { - BT_WARN("Proxy PDU type doesn't match GATT service"); - return -EINVAL; - } - - return bt_mesh_proxy_msg_recv(cli, data, len); -} - -void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err) -{ - struct ble_gap_conn_desc info; - struct ble_hs_conn *conn; - - conn = ble_hs_conn_find(conn_handle); - bt_conn_get_info(conn, &info); - if (info.role != BLE_GAP_ROLE_SLAVE || - !service_registered || bt_mesh_is_provisioned()) { - return; - } - - cli = bt_mesh_proxy_role_setup(conn_handle, gatt_send, proxy_msg_recv); - - BT_DBG("conn %p err 0x%02x", (void *)conn, err); -} - -void gatt_disconnected_pb_gatt(struct ble_gap_conn_desc conn, uint8_t reason) -{ - if (conn.role != BLE_GAP_ROLE_SLAVE || - !service_registered) { - return; - } - - if (cli) { - bt_mesh_proxy_role_cleanup(cli); - cli = NULL; - } - - BT_DBG("conn_handle %d reason 0x%02x", conn.conn_handle, reason); - - bt_mesh_pb_gatt_close(conn.conn_handle); - - if (bt_mesh_is_provisioned()) { - (void)bt_mesh_pb_gatt_disable(); - } -} - -int prov_ccc_write(uint16_t conn_handle, uint8_t type) -{ - if (cli->conn_handle != conn_handle) { - BT_ERR("No PB-GATT Client found"); - return -ENOTCONN; - } - - if (type != BLE_GAP_EVENT_SUBSCRIBE) { - BT_WARN("Client wrote instead enabling notify"); - return BT_GATT_ERR(EINVAL); - } - - bt_mesh_pb_gatt_open(conn_handle); - - return 0; -} - -/* Mesh Provisioning Service Declaration */ - -static int -dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - /* - * We should never never enter this callback - it's attached to notify-only - * characteristic which are notified directly from mbuf. And we can't pass - * NULL as access_cb because gatts will assert on init... - */ - BLE_HS_DBG_ASSERT(0); - return 0; -} - -static const struct ble_gatt_svc_def svc_defs [] = { - { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), - .access_cb = gatt_recv_proxy, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - .access_cb = gatt_recv_prov, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, { - 0, /* No more services. */ - }, -}; - -void resolve_svc_handles(void) -{ - int rc; - - /* Either all handles are already resolved, or none of them */ - if (svc_handles.prov_data_out_h) { - return; - } - - /* - * We assert if attribute is not found since at this stage all attributes - * shall be already registered and thus shall be found. - */ - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - &svc_handles.proxy_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - NULL, &svc_handles.proxy_data_out_h); - assert(rc == 0); - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - &svc_handles.prov_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - NULL, &svc_handles.prov_data_in_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - NULL, &svc_handles.prov_data_out_h); - assert(rc == 0); -} - - -int bt_mesh_proxy_svcs_register(void) -{ - int rc; - - rc = ble_gatts_count_cfg(svc_defs); - assert(rc == 0); - - rc = ble_gatts_add_svcs(svc_defs); - assert(rc == 0); - - return 0; -} - -int bt_mesh_pb_gatt_enable(void) -{ - int rc; - uint16_t handle; - BT_DBG(""); - - if (bt_mesh_is_provisioned()) { - return -ENOTSUP; - } - - if (service_registered) { - return -EBUSY; - } - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 1); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - - service_registered = true; - prov_fast_adv = true; - - return 0; -} - -int bt_mesh_pb_gatt_disable(void) -{ - uint16_t handle; - int rc; - - BT_DBG(""); - - if (!service_registered) { - return -EALREADY; - } - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 0); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - service_registered = false; - - bt_mesh_adv_update(); - - return 0; -} - -static uint8_t prov_svc_data[20] = { - BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL), -}; - -static const struct bt_data prov_ad[] = { - BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, - BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)), - BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), -}; - -int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf) -{ - if (!cli || cli->conn_handle != conn_handle) { - BT_ERR("No PB-GATT Client found"); - return -ENOTCONN; - } - - return bt_mesh_proxy_msg_send(cli, BT_MESH_PROXY_PROV, buf); -} - -static size_t gatt_prov_adv_create(struct bt_data prov_sd[1]) -{ - const struct bt_mesh_prov *prov = bt_mesh_prov_get(); - size_t uri_len; - - memcpy(prov_svc_data + 2, prov->uuid, 16); - sys_put_be16(prov->oob_info, prov_svc_data + 18); - - if (!prov->uri) { - return 0; - } - - uri_len = strlen(prov->uri); - if (uri_len > 29) { - /* There's no way to shorten an URI */ - BT_WARN("Too long URI to fit advertising packet"); - return 0; - } - - prov_sd[0].type = BT_DATA_URI; - prov_sd[0].data_len = uri_len; - prov_sd[0].data = (const uint8_t *)prov->uri; - - return 1; -} - -static int gatt_send(uint16_t conn_handle, - const void *data, uint16_t len) -{ - struct os_mbuf *om; - int err = 0; - - BT_DBG("%u bytes: %s", len, bt_hex(data, len)); - om = ble_hs_mbuf_from_flat(data, len); - assert(om); - err = ble_gatts_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); - notify_complete(); - - if (!err) { - atomic_inc(&pending_notifications); - } - - return err; -} - -int bt_mesh_pb_gatt_adv_start(void) -{ - BT_DBG(""); - - if (!service_registered || bt_mesh_is_provisioned()) { - return -ENOTSUP; - } - - struct ble_gap_adv_params fast_adv_param = { - ADV_OPT_PROV - ADV_FAST_INT - }; -#if ADV_OPT_USE_NAME - const char *name = CONFIG_BT_DEVICE_NAME; - size_t name_len = strlen(name); - struct bt_data prov_sd = { - .type = BT_DATA_NAME_COMPLETE, - .data_len = name_len, - .data = (void *)name - }; -#else - struct bt_data *prov_sd = NULL; -#endif - - size_t prov_sd_len; - int err; - - prov_sd_len = gatt_prov_adv_create(prov_sd); - - if (!prov_fast_adv) { - struct ble_gap_adv_params slow_adv_param = { - ADV_OPT_PROV - ADV_SLOW_INT - }; - - return bt_mesh_adv_start(&slow_adv_param, K_FOREVER, prov_ad, - ARRAY_SIZE(prov_ad), prov_sd, prov_sd_len); - } - - /* Advertise 60 seconds using fast interval */ - err = bt_mesh_adv_start(&fast_adv_param, (60 * MSEC_PER_SEC), - prov_ad, ARRAY_SIZE(prov_ad), - prov_sd, prov_sd_len); - if (!err) { - prov_fast_adv = false; - } - - return err; -} -#endif diff --git a/src/nimble/nimble/host/mesh/src/pb_gatt_srv.h b/src/nimble/nimble/host/mesh/src/pb_gatt_srv.h deleted file mode 100644 index d14339263..000000000 --- a/src/nimble/nimble/host/mesh/src/pb_gatt_srv.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2021 Lingao Meng - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __PB_GATT_SRV_H__ -#define __PB_GATT_SRV_H__ - -int bt_mesh_pb_gatt_send(uint16_t conn_handle, struct os_mbuf *buf); - -int bt_mesh_pb_gatt_enable(void); -int bt_mesh_pb_gatt_disable(void); - -int prov_ccc_write(uint16_t conn_handle, uint8_t type); -void gatt_disconnected_pb_gatt(struct ble_gap_conn_desc conn, uint8_t err); -void gatt_connected_pb_gatt(uint16_t conn_handle, uint8_t err); -void resolve_svc_handles(void); - -int bt_mesh_pb_gatt_adv_start(void); - -extern struct svc_handles { - uint16_t proxy_h; - uint16_t proxy_data_out_h; - uint16_t prov_h; - uint16_t prov_data_in_h; - uint16_t prov_data_out_h; -} svc_handles; - -#endif /* __PB_GATT_SRV_H__ */ diff --git a/src/nimble/nimble/host/mesh/src/prov.c b/src/nimble/nimble/host/mesh/src/prov.c deleted file mode 100644 index 13abc5778..000000000 --- a/src/nimble/nimble/host/mesh/src/prov.c +++ /dev/null @@ -1,463 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_PROV_LOG - -#include - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "mesh_priv.h" - -#include "crypto.h" -#include "atomic.h" -#include "net.h" -#include "access.h" -#include "foundation.h" -#include "prov.h" -#include "testing.h" - -struct bt_mesh_prov_link bt_mesh_prov_link; -const struct bt_mesh_prov *bt_mesh_prov; - -/* Verify specification defined length: */ -BUILD_ASSERT(sizeof(bt_mesh_prov_link.conf_inputs) == 145, - "Confirmation inputs shall be 145 bytes"); - -static void pub_key_ready(const uint8_t *pkey) -{ - if (!pkey) { - BT_WARN("Public key not available"); - return; - } - BT_DBG("Local public key ready"); -} - -int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[BT_PUB_KEY_LEN])) -{ - 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, auth); - - pub_key_cb.func = func ? func : pub_key_ready; - - /* Disable Attention Timer if it was set */ - if (bt_mesh_prov_link.conf_inputs.invite[0]) { - bt_mesh_attention(NULL, 0); - } - - 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; -} - -static bt_mesh_output_action_t output_action(uint8_t action) -{ - switch (action) { - case OUTPUT_OOB_BLINK: - return BT_MESH_BLINK; - case OUTPUT_OOB_BEEP: - return BT_MESH_BEEP; - case OUTPUT_OOB_VIBRATE: - return BT_MESH_VIBRATE; - case OUTPUT_OOB_NUMBER: - return BT_MESH_DISPLAY_NUMBER; - case OUTPUT_OOB_STRING: - return BT_MESH_DISPLAY_STRING; - default: - return BT_MESH_NO_OUTPUT; - } -} - -static bt_mesh_input_action_t input_action(uint8_t action) -{ - switch (action) { - case INPUT_OOB_PUSH: - return BT_MESH_PUSH; - case INPUT_OOB_TWIST: - return BT_MESH_TWIST; - case INPUT_OOB_NUMBER: - return BT_MESH_ENTER_NUMBER; - case INPUT_OOB_STRING: - return BT_MESH_ENTER_STRING; - default: - return BT_MESH_NO_INPUT; - } -} - -static int check_output_auth(bt_mesh_output_action_t output, uint8_t size) -{ - if (!output) { - return -EINVAL; - } - - if (!(bt_mesh_prov->output_actions & output)) { - return -EINVAL; - } - - if (size > bt_mesh_prov->output_size) { - return -EINVAL; - } - - return 0; -} - -static int check_input_auth(bt_mesh_input_action_t input, uint8_t size) -{ - if (!input) { - return -EINVAL; - } - - if (!(bt_mesh_prov->input_actions & input)) { - return -EINVAL; - } - - if (size > bt_mesh_prov->input_size) { - return -EINVAL; - } - - return 0; -} - -static void get_auth_string(char *str, uint8_t size) -{ - uint64_t value; - - bt_rand(&value, sizeof(value)); - - static const char characters[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - for (int i = 0; i < size; i++) { - /* pull base-36 digits: */ - int idx = value % 36; - - value = value / 36; - str[i] = characters[idx]; - } - - str[size] = '\0'; - - memcpy(bt_mesh_prov_link.auth, str, size); - memset(bt_mesh_prov_link.auth + size, 0, - sizeof(bt_mesh_prov_link.auth) - size); -} - -static uint32_t get_auth_number(bt_mesh_output_action_t output, - bt_mesh_input_action_t input, uint8_t size) - { - const uint32_t divider[PROV_IO_OOB_SIZE_MAX] = { 10, 100, 1000, 10000, - 100000, 1000000, 10000000, 100000000 }; - uint32_t num = 0; - - bt_rand(&num, sizeof(num)); - - if (output == BT_MESH_BLINK || - output == BT_MESH_BEEP || - output == BT_MESH_VIBRATE || - input == BT_MESH_PUSH || - input == BT_MESH_TWIST) { - /* According to the Bluetooth Mesh Profile - * Specification Section 5.4.2.4, blink, beep - * vibrate, push and twist should be a random integer - * between 0 and 10^size, *exclusive*: - */ - num = (num % (divider[size - 1] - 1)) + 1; - } else { - num %= divider[size - 1]; - } - - sys_put_be32(num, &bt_mesh_prov_link.auth[12]); - memset(bt_mesh_prov_link.auth, 0, 12); - - return num; - } - -int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8_t size) -{ - bt_mesh_output_action_t output; - bt_mesh_input_action_t input; - int err; - - switch (method) { - case AUTH_METHOD_NO_OOB: - if (action || size) { - return -EINVAL; - } - - (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; - } - - atomic_set_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY); - - return 0; - - case AUTH_METHOD_OUTPUT: - output = output_action(action); - if (is_provisioner) { - if (output == BT_MESH_DISPLAY_STRING) { - input = BT_MESH_ENTER_STRING; - atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING); - } else { - input = BT_MESH_ENTER_NUMBER; - atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER); - } - - return bt_mesh_prov->input(input, size); - } - - err = check_output_auth(output, size); - if (err) { - return err; - } - - if (output == BT_MESH_DISPLAY_STRING) { - char str[9]; - - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - get_auth_string(str, size); - return bt_mesh_prov->output_string(str); - } - - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - return bt_mesh_prov->output_number(output, - get_auth_number(output, BT_MESH_NO_INPUT, size)); - case AUTH_METHOD_INPUT: - input = input_action(action); - if (!is_provisioner) { - err = check_input_auth(input, size); - if (err) { - return err; - } - - if (input == BT_MESH_ENTER_STRING) { - atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING); - } else { - atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER); - } - - return bt_mesh_prov->input(input, size); - } - - if (input == BT_MESH_ENTER_STRING) { - char str[9]; - - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - get_auth_string(str, size); - return bt_mesh_prov->output_string(str); - } - - atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); - output = BT_MESH_DISPLAY_NUMBER; - return bt_mesh_prov->output_number(output, - get_auth_number(BT_MESH_NO_OUTPUT, input, size)); - - default: - return -EINVAL; - } -} - -int bt_mesh_input_number(uint32_t num) -{ - BT_DBG("%u", (unsigned) num); - - if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_NUMBER)) { - return -EINVAL; - } - - sys_put_be32(num, &bt_mesh_prov_link.auth[12]); - - bt_mesh_prov_link.role->input_complete(); - - return 0; -} - -int bt_mesh_input_string(const char *str) -{ - BT_DBG("%s", str); - - if (strlen(str) > PROV_IO_OOB_SIZE_MAX || - strlen(str) > bt_mesh_prov_link.oob_size) { - return -ENOTSUP; - } - - if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_STRING)) { - return -EINVAL; - } - - strcpy((char *)bt_mesh_prov_link.auth, str); - - bt_mesh_prov_link.role->input_complete(); - - return 0; -} - -const struct bt_mesh_prov *bt_mesh_prov_get(void) -{ - return bt_mesh_prov; -} - -bool bt_mesh_prov_active(void) -{ - return atomic_test_bit(bt_mesh_prov_link.flags, LINK_ACTIVE); -} - -static void prov_recv(const struct prov_bearer *bearer, void *cb_data, - struct os_mbuf *buf) -{ - static const uint8_t op_len[10] = { - [PROV_INVITE] = PDU_LEN_INVITE, - [PROV_CAPABILITIES] = PDU_LEN_CAPABILITIES, - [PROV_START] = PDU_LEN_START, - [PROV_PUB_KEY] = PDU_LEN_PUB_KEY, - [PROV_INPUT_COMPLETE] = PDU_LEN_INPUT_COMPLETE, - [PROV_CONFIRM] = PDU_LEN_CONFIRM, - [PROV_RANDOM] = PDU_LEN_RANDOM, - [PROV_DATA] = PDU_LEN_DATA, - [PROV_COMPLETE] = PDU_LEN_COMPLETE, - [PROV_FAILED] = PDU_LEN_FAILED, - }; - - uint8_t type = buf->om_data[0]; - 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_PDU); - return; - } - - 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; - } - - 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; - } - - 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) -{ - if (!prov_info) { - BT_ERR("No provisioning context provided"); - return -EINVAL; - } - - bt_mesh_prov = prov_info; - - if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) { - pb_adv_init(); - } - if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - pb_gatt_init(); - } - - return bt_mesh_prov_reset_state(NULL); -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/prov.h b/src/nimble/nimble/host/mesh/src/prov.h deleted file mode 100644 index 5b7b4b876..000000000 --- a/src/nimble/nimble/host/mesh/src/prov.h +++ /dev/null @@ -1,177 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __PROV_H__ -#define __PROV_H__ - -#include "prov_bearer.h" -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/src/ble_hs_conn_priv.h" - -#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 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_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 PDU_LEN_INVITE 1 -#define PDU_LEN_CAPABILITIES 11 -#define PDU_LEN_START 5 -#define PDU_LEN_PUB_KEY 64 -#define PDU_LEN_INPUT_COMPLETE 0 -#define PDU_LEN_CONFIRM 16 -#define PDU_LEN_RANDOM 16 -#define PDU_LEN_DATA 33 -#define PDU_LEN_COMPLETE 0 -#define PDU_LEN_FAILED 1 - -#define PDU_OP_LEN 1 - -#define PROV_ALG_P256 0x00 - -#define PROV_IO_OOB_SIZE_MAX 8 /* in bytes */ - -#define PROV_BUF(len) \ - NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + PDU_OP_LEN + 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 */ - WAIT_DH_KEY, /* Wait for DH Key */ - - 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[BT_DH_KEY_LEN]; /* Calculated DHKey */ - uint8_t expect; /* Next expected PDU */ - uint8_t conf[16]; /* Local/Remote Confirmation */ - uint8_t rand[16]; /* Local Random */ - - uint8_t conf_salt[16]; /* ConfirmationSalt */ - uint8_t conf_key[16]; /* ConfirmationKey */ - /* ConfirmationInput fields: */ - struct { - uint8_t invite[PDU_LEN_INVITE]; - uint8_t capabilities[PDU_LEN_CAPABILITIES]; - uint8_t start[PDU_LEN_START]; - uint8_t pub_key_provisioner[PDU_LEN_PUB_KEY]; /* big-endian */ - uint8_t pub_key_device[PDU_LEN_PUB_KEY]; /* big-endian */ - } conf_inputs; - uint8_t prov_salt[16]; /* Provisioning Salt */ -}; - -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[BT_PUB_KEY_LEN])); - -bool bt_mesh_prov_active(void); - -int bt_mesh_prov_auth(bool is_provisioner, uint8_t method, uint8_t action, uint8_t size); - -int bt_mesh_pb_gatt_open(uint16_t conn_handle); -int bt_mesh_pb_gatt_close(uint16_t conn_handle); -int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf); - -const struct bt_mesh_prov *bt_mesh_prov_get(void); - -void bt_mesh_prov_reset_link(void); - -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/src/nimble/nimble/host/mesh/src/prov_bearer.h b/src/nimble/nimble/host/mesh/src/prov_bearer.h deleted file mode 100644 index 3e5268314..000000000 --- a/src/nimble/nimble/host/mesh/src/prov_bearer.h +++ /dev/null @@ -1,116 +0,0 @@ -/* 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/src/nimble/nimble/host/mesh/src/prov_device.c b/src/nimble/nimble/host/mesh/src/prov_device.c deleted file mode 100644 index 3bd6b9b93..000000000 --- a/src/nimble/nimble/host/mesh/src/prov_device.c +++ /dev/null @@ -1,641 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2020 Lingao Meng - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_PROV_LOG - -#include "testing.h" -#include "crypto.h" -#include "adv.h" -#include "nimble/nimble/host/mesh/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" -#include "pb_gatt_srv.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(PDU_LEN_FAILED); - - 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(PDU_LEN_CAPABILITIES); - - BT_DBG("Attention Duration: %u seconds", data[0]); - - if (data[0]) { - bt_mesh_attention(NULL, data[0]); - } - - memcpy(bt_mesh_prov_link.conf_inputs.invite, data, PDU_LEN_INVITE); - - 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 */ - net_buf_simple_add_u8(buf, - bt_mesh_prov->public_key_be == NULL ? PUB_KEY_NO_OOB : PUB_KEY_OOB); - - /* Static OOB Type */ - net_buf_simple_add_u8(buf, bt_mesh_prov->static_val ? BIT(0) : 0x00); - - /* 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.capabilities, &buf->om_data[1], PDU_LEN_CAPABILITIES); - - 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_OOB || - (data[1] == PUB_KEY_OOB && - (!MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) || !bt_mesh_prov->public_key_be))) { - BT_ERR("Invalid public key type: 0x%02x", data[1]); - prov_fail(PROV_ERR_NVAL_FMT); - return; - } - - atomic_set_bit_to(bt_mesh_prov_link.flags, OOB_PUB_KEY, data[1] == PUB_KEY_OOB); - - memcpy(bt_mesh_prov_link.conf_inputs.start, data, PDU_LEN_START); - - bt_mesh_prov_link.expect = PROV_PUB_KEY; - bt_mesh_prov_link.oob_method = data[2]; - bt_mesh_prov_link.oob_action = data[3]; - bt_mesh_prov_link.oob_size = data[4]; - - if (bt_mesh_prov_auth(false, data[2], data[3], data[4]) < 0) { - BT_ERR("Invalid authentication method: 0x%02x; " - "action: 0x%02x; size: 0x%02x", data[2], data[3], - data[4]); - 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(PDU_LEN_CONFIRM); - - uint8_t *inputs = (uint8_t *)&bt_mesh_prov_link.conf_inputs; - - BT_DBG("ConfInputs[0] %s", bt_hex(inputs, 64)); - BT_DBG("ConfInputs[64] %s", bt_hex(&inputs[64], 64)); - BT_DBG("ConfInputs[128] %s", bt_hex(&inputs[128], 17)); - - if (bt_mesh_prov_conf_salt(inputs, bt_mesh_prov_link.conf_salt)) { - BT_ERR("Unable to generate confirmation salt"); - prov_fail(PROV_ERR_UNEXP_ERR); - return; - } - - 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(PDU_LEN_INPUT_COMPLETE); - - 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 start_auth(void) -{ - if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) || - atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING)) { - bt_mesh_prov_link.expect = PROV_NO_PDU; /* Wait for input */ - } else { - bt_mesh_prov_link.expect = PROV_CONFIRM; - } -} - -static void send_pub_key(void) -{ - struct os_mbuf *buf = PROV_BUF(PDU_LEN_PUB_KEY); - 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_mesh_prov_buf_init(buf, PROV_PUB_KEY); - - /* Swap X and Y halves independently to big-endian */ - sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), key, BT_PUB_KEY_COORD_LEN); - sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), &key[BT_PUB_KEY_COORD_LEN], 32); - - BT_DBG("Local Public Key: %s", bt_hex(buf->om_data + 1, BT_PUB_KEY_LEN)); - - /* PublicKeyDevice */ - memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, &buf->om_data[1], PDU_LEN_PUB_KEY); - - if (bt_mesh_prov_send(buf, public_key_sent)) { - BT_ERR("Failed to send Public Key"); - return; - } - - start_auth(); -} - -static void dh_key_gen_complete(void) -{ - BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, BT_DH_KEY_LEN)); - - if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY) && - atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { - send_confirm(); - } else if (!atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { - send_pub_key(); - } -} - -static void prov_dh_key_cb(const uint8_t dhkey[BT_DH_KEY_LEN]) -{ - 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, BT_DH_KEY_LEN); - - dh_key_gen_complete(); -} - -static void prov_dh_key_gen(void) -{ - const uint8_t *remote_pk; - uint8_t remote_pk_le[BT_PUB_KEY_LEN]; - - remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner; -#if !CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS - if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && - atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { - if (uECC_valid_public_key(remote_pk, uECC_secp256r1())) { - BT_ERR("Public key is not valid"); - } else if (uECC_shared_secret(remote_pk, bt_mesh_prov->private_key_be, - bt_mesh_prov_link.dhkey, - uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { - BT_ERR("DHKey generation failed"); - } else { - dh_key_gen_complete(); - return; - } - - prov_fail(PROV_ERR_UNEXP_ERR); - return; - } -#endif - - /* 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, BT_PUB_KEY_COORD_LEN); - sys_memcpy_swap(&remote_pk_le[BT_PUB_KEY_COORD_LEN], &remote_pk[BT_PUB_KEY_COORD_LEN], - BT_PUB_KEY_COORD_LEN); - - if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) { - BT_ERR("Failed to generate DHKey"); - prov_fail(PROV_ERR_UNEXP_ERR); - } -} - -static void prov_pub_key(const uint8_t *data) -{ - BT_DBG("Remote Public Key: %s", bt_hex(data, BT_PUB_KEY_LEN)); - - /* PublicKeyProvisioner */ - memcpy(bt_mesh_prov_link.conf_inputs.pub_key_provisioner, data, PDU_LEN_PUB_KEY); - - if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && - atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { - if (!bt_mesh_prov->public_key_be || !bt_mesh_prov->private_key_be) { - BT_ERR("Public or private key is not ready"); - prov_fail(PROV_ERR_UNEXP_ERR); - return; - } - - /* No swap needed since user provides public key in big-endian */ - memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, bt_mesh_prov->public_key_be, - PDU_LEN_PUB_KEY); - - atomic_set_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY); - - start_auth(); - } else if (!bt_pub_key_get()) { - /* Clear retransmit timer */ - bt_mesh_prov_link.bearer->clear_tx(); - atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY); - 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(PDU_LEN_RANDOM); - - 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(); - - if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY)) { - 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(PDU_LEN_COMPLETE); - 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) || - atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { - send_input_complete(); - } else { - atomic_set_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE); - } -} - -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 (bt_mesh_prov_active()) { - return -EBUSY; - } - - 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)) { - (void)bt_mesh_pb_gatt_disable(); - } - - return 0; -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/provisioner.c b/src/nimble/nimble/host/mesh/src/provisioner.c deleted file mode 100644 index 6572017d6..000000000 --- a/src/nimble/nimble/host/mesh/src/provisioner.c +++ /dev/null @@ -1,756 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2020 Lingao Meng - * Copyright (c) 2021 Manulytica Limited - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_PROV_LOG - -#include "testing.h" - -#include "crypto.h" -#include "adv.h" -#include "nimble/nimble/host/mesh/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(PDU_LEN_INVITE); - - BT_DBG(""); - - bt_mesh_prov_buf_init(inv, PROV_INVITE); - net_buf_simple_add_u8(inv, prov_device.attention_duration); - - memcpy(bt_mesh_prov_link.conf_inputs.invite, &prov_device.attention_duration, - PDU_LEN_INVITE); - - if (bt_mesh_prov_send(inv, NULL)) { - BT_ERR("Failed to send invite"); - 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(""); - struct os_mbuf *start = PROV_BUF(PDU_LEN_START); - - bool oob_pub_key = bt_mesh_prov_link.conf_inputs.capabilities[3] == PUB_KEY_OOB; - - bt_mesh_prov_buf_init(start, PROV_START); - net_buf_simple_add_u8(start, PROV_ALG_P256); - - memcpy(bt_mesh_prov_link.conf_inputs.start, &start->om_data[1], PDU_LEN_START); - - if (atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY) && oob_pub_key) { - net_buf_simple_add_u8(start, PUB_KEY_OOB); - atomic_set_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY); - } else { - net_buf_simple_add_u8(start, PUB_KEY_NO_OOB); - } - - 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.invite, &start->om_data[1], PDU_LEN_INVITE); - - if (bt_mesh_prov_auth(true, bt_mesh_prov_link.oob_method, - bt_mesh_prov_link.oob_action, bt_mesh_prov_link.oob_size) < 0) { - BT_ERR("Invalid authentication method: 0x%02x; " - "action: 0x%02x; size: 0x%02x", bt_mesh_prov_link.oob_method, - bt_mesh_prov_link.oob_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%04x) " - "not supported by the device (0x%02x)", - (uint16_t)BIT(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%04x) " - "not supported by the device (0x%02x)", - (uint16_t)BIT(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) - (sys_get_be16(&data[6])); - caps.input_size = data[8]; - caps.input_actions = (bt_mesh_input_action_t) - (sys_get_be16(&data[9])); - BT_DBG("Output OOB Action: 0x%04x", caps.output_actions); - BT_DBG("Input OOB Size: %u", caps.input_size); - BT_DBG("Input OOB Action: 0x%04x", caps.input_actions); - - 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.capabilities, data, PDU_LEN_CAPABILITIES); - - 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(PDU_LEN_CONFIRM); - uint8_t *inputs = (uint8_t *)&bt_mesh_prov_link.conf_inputs; - - BT_DBG("ConfInputs[0] %s", bt_hex(inputs, 64)); - BT_DBG("ConfInputs[64] %s", bt_hex(&inputs[64], 64)); - BT_DBG("ConfInputs[128] %s", bt_hex(&inputs[128], 17)); - - if (bt_mesh_prov_conf_salt(inputs, bt_mesh_prov_link.conf_salt)) { - BT_ERR("Unable to generate confirmation salt"); - prov_fail(PROV_ERR_UNEXP_ERR); - return; - } - - 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, - bt_mesh_prov_link.conf)) { - BT_ERR("Unable to generate confirmation value"); - prov_fail(PROV_ERR_UNEXP_ERR); - return; - } - - net_buf_simple_add_mem(cfm, bt_mesh_prov_link.conf, 16); - - if (bt_mesh_prov_send(cfm, NULL)) { - BT_ERR("Failed to send Provisioning Confirm"); - return; - } - - 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; - } -} - -static void send_pub_key(void) -{ - struct os_mbuf *buf = PROV_BUF(PDU_LEN_PUB_KEY); - 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, BT_PUB_KEY_LEN)); - - bt_mesh_prov_buf_init(buf, PROV_PUB_KEY); - - /* Swap X and Y halves independently to big-endian */ - sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), key, BT_PUB_KEY_COORD_LEN); - sys_memcpy_swap(net_buf_simple_add(buf, BT_PUB_KEY_COORD_LEN), &key[BT_PUB_KEY_COORD_LEN], - BT_PUB_KEY_COORD_LEN); - - /* PublicKeyProvisioner */ - memcpy(bt_mesh_prov_link.conf_inputs.pub_key_provisioner, &buf->om_data[1], PDU_LEN_PUB_KEY); - - if (bt_mesh_prov_send(buf, public_key_sent)) { - BT_ERR("Failed to send Public Key"); - return; - } - - bt_mesh_prov_link.expect = PROV_PUB_KEY; -} - -static void prov_dh_key_cb(const uint8_t dhkey[BT_DH_KEY_LEN]) -{ - 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, BT_DH_KEY_LEN); - - BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, BT_DH_KEY_LEN)); - - if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING) || - atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) || - 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[BT_PUB_KEY_LEN]; - const uint8_t *remote_pk; - const uint8_t *local_pk; - - local_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner; - remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_device; - - /* Copy remote key in little-endian for bt_dh_key_gen(). - * X and Y halves are swapped independently. The bt_dh_key_gen() - * will also take care of validating the remote public key. - */ - sys_memcpy_swap(remote_pk_le, remote_pk, BT_PUB_KEY_COORD_LEN); - sys_memcpy_swap(&remote_pk_le[BT_PUB_KEY_COORD_LEN], &remote_pk[BT_PUB_KEY_COORD_LEN], - BT_PUB_KEY_COORD_LEN); - - if (!memcmp(local_pk, remote_pk, BT_PUB_KEY_LEN)) { - BT_ERR("Public keys are identical"); - prov_fail(PROV_ERR_NVAL_FMT); - return; - } - - if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) { - BT_ERR("Failed to generate DHKey"); - prov_fail(PROV_ERR_UNEXP_ERR); - } - - 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, BT_PUB_KEY_LEN)); - - atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY); - - /* PublicKeyDevice */ - memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, data, BT_PUB_KEY_LEN); - 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(PDU_LEN_DATA); -#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[SUBNET_KEY_TX_IDX(sub)].net_key, 16); - net_buf_simple_add_be16(pdu, prov_device.node->net_idx); - net_buf_simple_add_u8(pdu, bt_mesh_cdb_subnet_flags(sub)); - net_buf_simple_add_be32(pdu, bt_mesh_cdb.iv_index); -#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_cdb_node_store(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(PDU_LEN_RANDOM); - - 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)); - - if (!memcmp(data, bt_mesh_prov_link.conf, 16)) { - BT_ERR("Confirm value is identical to ours, rejecting."); - prov_fail(PROV_ERR_CFM_FAILED); - return; - } - - memcpy(bt_mesh_prov_link.conf, data, 16); - - send_random(); -} - -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 > PROV_IO_OOB_SIZE_MAX) { - 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 > PROV_IO_OOB_SIZE_MAX) { - 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[BT_PUB_KEY_LEN]) -{ - 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.pub_key_device, public_key, PDU_LEN_PUB_KEY); - - 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/src/nimble/nimble/host/mesh/src/provisioner.h b/src/nimble/nimble/host/mesh/src/provisioner.h deleted file mode 100644 index 315bde299..000000000 --- a/src/nimble/nimble/host/mesh/src/provisioner.h +++ /dev/null @@ -1,10 +0,0 @@ -/* 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); diff --git a/src/nimble/nimble/host/mesh/src/proxy.c b/src/nimble/nimble/host/mesh/src/proxy.c deleted file mode 100644 index 863c8e5de..000000000 --- a/src/nimble/nimble/host/mesh/src/proxy.c +++ /dev/null @@ -1,1576 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#define MESH_LOG_MODULE BLE_MESH_PROXY_LOG - -#if MYNEWT_VAL(BLE_MESH_PROXY) - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/include/host/ble_att.h" -#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" -#include "nimble/nimble/host/src/ble_hs_priv.h" - -#include "mesh_priv.h" -#include "adv.h" -#include "net.h" -#include "rpl.h" -#include "prov.h" -#include "beacon.h" -#include "foundation.h" -#include "access.h" -#include "proxy.h" - -#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." - */ -#define PROXY_SAR_TIMEOUT K_SECONDS(20) - -#define SAR_COMPLETE 0x00 -#define SAR_FIRST 0x01 -#define SAR_CONT 0x02 -#define SAR_LAST 0x03 - -#define CFG_FILTER_SET 0x00 -#define CFG_FILTER_ADD 0x01 -#define CFG_FILTER_REMOVE 0x02 -#define CFG_FILTER_STATUS 0x03 - -/** @def BT_UUID_MESH_PROV - * @brief Mesh Provisioning Service - */ -ble_uuid16_t BT_UUID_MESH_PROV = BLE_UUID16_INIT(0x1827); -#define BT_UUID_MESH_PROV_VAL 0x1827 -/** @def BT_UUID_MESH_PROXY - * @brief Mesh Proxy Service - */ -ble_uuid16_t BT_UUID_MESH_PROXY = BLE_UUID16_INIT(0x1828); -#define BT_UUID_MESH_PROXY_VAL 0x1828 -/** @def BT_UUID_GATT_CCC - * @brief GATT Client Characteristic Configuration - */ -ble_uuid16_t BT_UUID_GATT_CCC = BLE_UUID16_INIT(0x2902); -#define BT_UUID_GATT_CCC_VAL 0x2902 -/** @def BT_UUID_MESH_PROV_DATA_IN - * @brief Mesh Provisioning Data In - */ -ble_uuid16_t BT_UUID_MESH_PROV_DATA_IN = BLE_UUID16_INIT(0x2adb); -#define BT_UUID_MESH_PROV_DATA_IN_VAL 0x2adb -/** @def BT_UUID_MESH_PROV_DATA_OUT - * @brief Mesh Provisioning Data Out - */ -ble_uuid16_t BT_UUID_MESH_PROV_DATA_OUT = BLE_UUID16_INIT(0x2adc); -#define BT_UUID_MESH_PROV_DATA_OUT_VAL 0x2adc -/** @def BT_UUID_MESH_PROXY_DATA_IN - * @brief Mesh Proxy Data In - */ -ble_uuid16_t BT_UUID_MESH_PROXY_DATA_IN = BLE_UUID16_INIT(0x2add); -#define BT_UUID_MESH_PROXY_DATA_IN_VAL 0x2add -/** @def BT_UUID_MESH_PROXY_DATA_OUT - * @brief Mesh Proxy Data Out - */ -ble_uuid16_t BT_UUID_MESH_PROXY_DATA_OUT = BLE_UUID16_INIT(0x2ade); -#define BT_UUID_MESH_PROXY_DATA_OUT_VAL 0x2ade - -#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) - -#define CLIENT_BUF_SIZE 68 - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - -static const struct ble_gap_adv_params slow_adv_param = { - .conn_mode = (BLE_GAP_CONN_MODE_UND), - .disc_mode = (BLE_GAP_DISC_MODE_GEN), - .itvl_min = BT_GAP_ADV_SLOW_INT_MIN, - .itvl_max = BT_GAP_ADV_SLOW_INT_MAX, -}; - -static const struct ble_gap_adv_params fast_adv_param = { - .conn_mode = (BLE_GAP_CONN_MODE_UND), - .disc_mode = (BLE_GAP_DISC_MODE_GEN), - .itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, - .itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, -}; - -static bool proxy_adv_enabled; - -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) -static void proxy_send_beacons(struct ble_npl_event *work); -#endif - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -static bool prov_fast_adv; -#endif - -static struct bt_mesh_proxy_client { - uint16_t conn_handle; - uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)]; - enum __packed { - NONE, - WHITELIST, - BLACKLIST, - PROV, - } filter_type; - uint8_t msg_type; -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - struct ble_npl_callout send_beacons; -#endif - struct k_delayed_work sar_timer; - struct os_mbuf *buf; -} clients[MYNEWT_VAL(BLE_MAX_CONNECTIONS)] = { - [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, - MESH_GATT_PROV, - MESH_GATT_PROXY, -} gatt_svc = MESH_GATT_NONE; - -static struct { - uint16_t proxy_h; - uint16_t proxy_data_out_h; - uint16_t prov_h; - uint16_t prov_data_in_h; - uint16_t prov_data_out_h; -} svc_handles; - -static void resolve_svc_handles(void) -{ - int rc; - - /* Either all handles are already resolved, or none of them */ - if (svc_handles.prov_data_out_h) { - return; - } - - /* - * We assert if attribute is not found since at this stage all attributes - * shall be already registered and thus shall be found. - */ - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - &svc_handles.proxy_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - NULL, &svc_handles.proxy_data_out_h); - assert(rc == 0); - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - &svc_handles.prov_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - NULL, &svc_handles.prov_data_in_h); - assert(rc == 0); - - rc = ble_gatts_find_chr(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - NULL, &svc_handles.prov_data_out_h); - assert(rc == 0); -} - -static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle == conn_handle) { - return &clients[i]; - } - } - - return NULL; -} - -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) -/* Next subnet in queue to be advertised */ -static struct bt_mesh_subnet *beacon_sub; - -static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, - struct os_mbuf *msg); - -static int filter_set(struct bt_mesh_proxy_client *client, - struct os_mbuf *buf) -{ - uint8_t type; - - if (buf->om_len < 1) { - BT_WARN("Too short Filter Set message"); - return -EINVAL; - } - - type = net_buf_simple_pull_u8(buf); - BT_DBG("type 0x%02x", type); - - switch (type) { - case 0x00: - memset(client->filter, 0, sizeof(client->filter)); - client->filter_type = WHITELIST; - break; - case 0x01: - memset(client->filter, 0, sizeof(client->filter)); - client->filter_type = BLACKLIST; - break; - default: - BT_WARN("Prohibited Filter Type 0x%02x", type); - return -EINVAL; - } - - return 0; -} - -static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr) -{ - int i; - - BT_DBG("addr 0x%04x", addr); - - if (addr == BT_MESH_ADDR_UNASSIGNED) { - return; - } - - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - return; - } - } - - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == BT_MESH_ADDR_UNASSIGNED) { - client->filter[i] = addr; - return; - } - } -} - -static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr) -{ - int i; - - BT_DBG("addr 0x%04x", addr); - - if (addr == BT_MESH_ADDR_UNASSIGNED) { - return; - } - - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - client->filter[i] = BT_MESH_ADDR_UNASSIGNED; - return; - } - } -} - -static void send_filter_status(struct bt_mesh_proxy_client *client, - struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - struct bt_mesh_net_tx tx = { - .sub = rx->sub, - .ctx = &rx->ctx, - .src = bt_mesh_primary_addr(), - }; - uint16_t filter_size; - int i, err; - - /* Configuration messages always have dst unassigned */ - tx.ctx->addr = BT_MESH_ADDR_UNASSIGNED; - - net_buf_simple_init(buf, 10); - - net_buf_simple_add_u8(buf, CFG_FILTER_STATUS); - - if (client->filter_type == WHITELIST) { - net_buf_simple_add_u8(buf, 0x00); - } else { - net_buf_simple_add_u8(buf, 0x01); - } - - for (filter_size = 0, i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] != BT_MESH_ADDR_UNASSIGNED) { - filter_size++; - } - } - - net_buf_simple_add_be16(buf, filter_size); - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - err = bt_mesh_net_encode(&tx, buf, true); - if (err) { - BT_ERR("Encoding Proxy cfg message failed (err %d)", err); - return; - } - - err = proxy_segment_and_send(client->conn_handle, BT_MESH_PROXY_CONFIG, buf); - if (err) { - BT_ERR("Failed to send proxy cfg message (err %d)", err); - } -} - -static void proxy_cfg(struct bt_mesh_proxy_client *client) -{ - struct os_mbuf *buf = NET_BUF_SIMPLE(29); - struct bt_mesh_net_rx rx; - uint8_t opcode; - int err; - - err = bt_mesh_net_decode(client->buf, BT_MESH_NET_IF_PROXY_CFG, - &rx, buf); - if (err) { - BT_ERR("Failed to decode Proxy Configuration (err %d)", err); - goto done; - } - - rx.local_match = 1U; - - if (bt_mesh_rpl_check(&rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", - rx.ctx.addr, rx.ctx.recv_dst, rx.seq); - goto done; - } - - /* Remove network headers */ - net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN); - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_len < 1) { - BT_WARN("Too short proxy configuration PDU"); - goto done; - } - - opcode = net_buf_simple_pull_u8(buf); - switch (opcode) { - case CFG_FILTER_SET: - filter_set(client, buf); - send_filter_status(client, &rx, buf); - break; - case CFG_FILTER_ADD: - while (buf->om_len >= 2) { - uint16_t addr; - - addr = net_buf_simple_pull_be16(buf); - filter_add(client, addr); - } - send_filter_status(client, &rx, buf); - break; - case CFG_FILTER_REMOVE: - while (buf->om_len >= 2) { - uint16_t addr; - - addr = net_buf_simple_pull_be16(buf); - filter_remove(client, addr); - } - send_filter_status(client, &rx, buf); - break; - default: - BT_WARN("Unhandled configuration OpCode 0x%02x", opcode); - break; - } - -done: - os_mbuf_free_chain(buf); -} - -static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub) -{ - struct os_mbuf *buf = NET_BUF_SIMPLE(23); - int rc; - - net_buf_simple_init(buf, 1); - bt_mesh_beacon_create(sub, buf); - - rc = proxy_segment_and_send(conn_handle, BT_MESH_PROXY_BEACON, buf); - os_mbuf_free_chain(buf); - 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; - - client = ble_npl_event_get_arg(work); - - (void)bt_mesh_subnet_find(send_beacon_cb, client); -} - -static void proxy_sar_timeout(struct ble_npl_event *work) -{ - struct bt_mesh_proxy_client *client; - int rc; - - BT_WARN("Proxy SAR timeout"); - - client = ble_npl_event_get_arg(work); - assert(client != NULL); - - if ((client->conn_handle != BLE_HS_CONN_HANDLE_NONE)) { - rc = ble_gap_terminate(client->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); - } -} - -void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub) -{ - int i; - - if (!sub) { - /* NULL means we send on all subnets */ - bt_mesh_subnet_foreach(bt_mesh_proxy_beacon_send); - return; - } - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle != BLE_HS_CONN_HANDLE_NONE) { - beacon_send(clients[i].conn_handle, sub); - } - } -} - -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 */ - beacon_sub = sub; -} - -void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub) -{ - sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED; - sub->node_id_start = 0; -} - -int bt_mesh_proxy_identity_enable(void) -{ - BT_DBG(""); - - if (!bt_mesh_is_provisioned()) { - return -EAGAIN; - } - - if (bt_mesh_subnet_foreach(node_id_start)) { - bt_mesh_adv_update(); - } - - return 0; -} - -#endif /* GATT_PROXY */ - -static void proxy_complete_pdu(struct bt_mesh_proxy_client *client) -{ - switch (client->msg_type) { -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - case BT_MESH_PROXY_NET_PDU: - BT_INFO("Mesh Network PDU"); - bt_mesh_net_recv(client->buf, 0, BT_MESH_NET_IF_PROXY); - break; - case BT_MESH_PROXY_BEACON: - BT_INFO("Mesh Beacon PDU"); - bt_mesh_beacon_recv(client->buf); - break; - case BT_MESH_PROXY_CONFIG: - BT_INFO("Mesh Configuration PDU"); - proxy_cfg(client); - break; -#endif -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - case BT_MESH_PROXY_PROV: - BT_INFO("Mesh Provisioning PDU"); - bt_mesh_pb_gatt_recv(client->conn_handle, client->buf); - break; -#endif - default: - BT_WARN("Unhandled Message Type 0x%02x", client->msg_type); - break; - } - - net_buf_simple_init(client->buf, 0); -} - -static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - struct bt_mesh_proxy_client *client = find_client(conn_handle); - const uint8_t *data = ctxt->om->om_data; - uint16_t len = ctxt->om->om_len; - - client = find_client(conn_handle); - - if (!client) { - return -ENOTCONN; - } - - if (len < 1) { - BT_WARN("Too small Proxy PDU"); - return -EINVAL; - } - - if ((attr_handle == svc_handles.prov_data_in_h) != - (PDU_TYPE(data) == BT_MESH_PROXY_PROV)) { - BT_WARN("Proxy PDU type doesn't match GATT service"); - return -EINVAL; - } - - if (len - 1 > net_buf_simple_tailroom(client->buf)) { - BT_WARN("Too big proxy PDU"); - return -EINVAL; - } - - switch (PDU_SAR(data)) { - case SAR_COMPLETE: - if (client->buf->om_len) { - BT_WARN("Complete PDU while a pending incomplete one"); - return -EINVAL; - } - - client->msg_type = PDU_TYPE(data); - net_buf_simple_add_mem(client->buf, data + 1, len - 1); - proxy_complete_pdu(client); - break; - - case SAR_FIRST: - if (client->buf->om_len) { - BT_WARN("First PDU while a pending incomplete one"); - return -EINVAL; - } - - k_delayed_work_submit(&client->sar_timer, PROXY_SAR_TIMEOUT); - client->msg_type = PDU_TYPE(data); - net_buf_simple_add_mem(client->buf, data + 1, len - 1); - break; - - case SAR_CONT: - if (!client->buf->om_len) { - BT_WARN("Continuation with no prior data"); - return -EINVAL; - } - - if (client->msg_type != PDU_TYPE(data)) { - BT_WARN("Unexpected message type in continuation"); - return -EINVAL; - } - - k_delayed_work_submit(&client->sar_timer, PROXY_SAR_TIMEOUT); - net_buf_simple_add_mem(client->buf, data + 1, len - 1); - break; - - case SAR_LAST: - if (!client->buf->om_len) { - BT_WARN("Last SAR PDU with no prior data"); - return -EINVAL; - } - - if (client->msg_type != PDU_TYPE(data)) { - BT_WARN("Unexpected message type in last SAR PDU"); - return -EINVAL; - } - - k_delayed_work_cancel(&client->sar_timer); - net_buf_simple_add_mem(client->buf, data + 1, len - 1); - proxy_complete_pdu(client); - break; - } - - return len; -} - -static int conn_count; - -static void proxy_connected(uint16_t conn_handle) -{ - struct bt_mesh_proxy_client *client; - int i; - - BT_INFO("conn_handle %d", conn_handle); - - conn_count++; - - /* Since we use ADV_OPT_ONE_TIME */ - proxy_adv_enabled = false; - - /* Try to re-enable advertising in case it's possible */ - if (conn_count < CONFIG_BT_MAX_CONN) { - bt_mesh_adv_update(); - } - - for (client = NULL, i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle == BLE_HS_CONN_HANDLE_NONE) { - client = &clients[i]; - break; - } - } - - if (!client) { - BT_ERR("No free Proxy Client objects"); - return; - } - - client->conn_handle = conn_handle; - client->filter_type = NONE; - memset(client->filter, 0, sizeof(client->filter)); - net_buf_simple_init(client->buf, 0); -} - -static void proxy_disconnected(uint16_t conn_handle, int reason) -{ - int i; - - 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]; - - if (client->conn_handle == conn_handle) { - if ((MYNEWT_VAL(BLE_MESH_PB_GATT)) && - client->filter_type == PROV) { - bt_mesh_pb_gatt_close(conn_handle); - } - - k_delayed_work_cancel(&client->sar_timer); - client->conn_handle = BLE_HS_CONN_HANDLE_NONE; - break; - } - } - - bt_mesh_adv_update(); -} - -struct os_mbuf *bt_mesh_proxy_get_buf(void) -{ - struct os_mbuf *buf = clients[0].buf; - - if (buf != NULL) { - net_buf_simple_init(buf, 0); - } - - return buf; -} - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -static void prov_ccc_write(uint16_t conn_handle) -{ - struct bt_mesh_proxy_client *client; - - BT_DBG("conn_handle %d", conn_handle); - - /* If a connection exists there must be a client */ - client = find_client(conn_handle); - __ASSERT(client, "No client for connection"); - - if (client->filter_type == NONE) { - client->filter_type = PROV; - bt_mesh_pb_gatt_open(conn_handle); - } -} - -int bt_mesh_proxy_prov_enable(void) -{ - uint16_t handle; - int rc; - int i; - - BT_DBG(""); - - if (gatt_svc == MESH_GATT_PROV) { - return -EALREADY; - } - - if (gatt_svc != MESH_GATT_NONE) { - return -EBUSY; - } - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 1); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - - gatt_svc = MESH_GATT_PROV; - prov_fast_adv = true; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle != BLE_HS_CONN_HANDLE_NONE) { - clients[i].filter_type = PROV; - } - } - - - return 0; -} - -int bt_mesh_proxy_prov_disable(bool disconnect) -{ - uint16_t handle; - int rc; - int i; - - BT_DBG(""); - - if (gatt_svc == MESH_GATT_NONE) { - return -EALREADY; - } - - if (gatt_svc != MESH_GATT_PROV) { - return -EBUSY; - } - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 0); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.prov_h, 0xffff); - - gatt_svc = MESH_GATT_NONE; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; - - if ((client->conn_handle == BLE_HS_CONN_HANDLE_NONE) - || (client->filter_type != PROV)) { - continue; - } - - if (disconnect) { - rc = ble_gap_terminate(client->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); - } else { - bt_mesh_pb_gatt_close(client->conn_handle); - client->filter_type = NONE; - } - } - - bt_mesh_adv_update(); - - return 0; -} -#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */ - -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) -static void proxy_ccc_write(uint16_t conn_handle) -{ - struct bt_mesh_proxy_client *client; - - BT_DBG("conn_handle %d", conn_handle); - - client = find_client(conn_handle); - __ASSERT(client, "No client for connection"); - - if (client->filter_type == NONE) { - client->filter_type = WHITELIST; - k_work_add_arg(&client->send_beacons, client); - k_work_submit(&client->send_beacons); - } -} - -int bt_mesh_proxy_gatt_enable(void) -{ - uint16_t handle; - int rc; - int i; - - BT_DBG(""); - - if (gatt_svc == MESH_GATT_PROXY) { - return -EALREADY; - } - - if (gatt_svc != MESH_GATT_NONE) { - return -EBUSY; - } - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 1); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff); - - gatt_svc = MESH_GATT_PROXY; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle != BLE_HS_CONN_HANDLE_NONE) { - clients[i].filter_type = WHITELIST; - } - } - - return 0; -} - -void bt_mesh_proxy_gatt_disconnect(void) -{ - int rc; - int i; - - BT_DBG(""); - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; - - if ((client->conn_handle != BLE_HS_CONN_HANDLE_NONE) && - (client->filter_type == WHITELIST || - client->filter_type == BLACKLIST)) { - client->filter_type = NONE; - rc = ble_gap_terminate(client->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); - } - } -} - -int bt_mesh_proxy_gatt_disable(void) -{ - uint16_t handle; - int rc; - - BT_DBG(""); - - if (gatt_svc == MESH_GATT_NONE) { - return -EALREADY; - } - - if (gatt_svc != MESH_GATT_PROXY) { - return -EBUSY; - } - - bt_mesh_proxy_gatt_disconnect(); - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 0); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff); - - gatt_svc = MESH_GATT_NONE; - - return 0; -} - -void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr) -{ - struct bt_mesh_proxy_client *client = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - client = &clients[i]; - if (client->buf == buf) { - break; - } - } - - assert(client); - - BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); - - if (client->filter_type == WHITELIST) { - filter_add(client, addr); - } else if (client->filter_type == BLACKLIST) { - filter_remove(client, addr); - } -} - -static bool client_filter_match(struct bt_mesh_proxy_client *client, - uint16_t addr) -{ - int i; - - BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); - - if (client->filter_type == BLACKLIST) { - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - return false; - } - } - - return true; - } - - if (addr == BT_MESH_ADDR_ALL_NODES) { - return true; - } - - if (client->filter_type == WHITELIST) { - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - return true; - } - } - } - - return false; -} - -bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) -{ - bool relayed = false; - int i; - - BT_DBG("%u bytes to dst 0x%04x", buf->om_len, dst); - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; - struct os_mbuf *msg; - - if (client->conn_handle == BLE_HS_CONN_HANDLE_NONE) { - continue; - } - - if (!client_filter_match(client, dst)) { - continue; - } - - /* Proxy PDU sending modifies the original buffer, - * so we need to make a copy. - */ - msg = NET_BUF_SIMPLE(32); - net_buf_simple_init(msg, 1); - net_buf_simple_add_mem(msg, buf->om_data, buf->om_len); - - bt_mesh_proxy_send(client->conn_handle, BT_MESH_PROXY_NET_PDU, msg); - os_mbuf_free_chain(msg); - relayed = true; - } - - return relayed; -} - -#endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */ - -static void notify_complete(void) -{ - sys_snode_t *n; - - if (atomic_dec(&pending_notifications) > 1) { - return; - } - - BT_DBG(""); - - while ((n = sys_slist_get(&idle_waiters))) { - CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb(); - } -} - -static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len) -{ - struct os_mbuf *om; - int err = 0; - - BT_DBG("%u bytes: %s", len, bt_hex(data, len)); - -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - if (gatt_svc == MESH_GATT_PROXY) { - om = ble_hs_mbuf_from_flat(data, len); - assert(om); - err = ble_gatts_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); - notify_complete(); - } -#endif - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - if (gatt_svc == MESH_GATT_PROV) { - om = ble_hs_mbuf_from_flat(data, len); - assert(om); - err = ble_gatts_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); - notify_complete(); - } -#endif - - if (!err) { - atomic_inc(&pending_notifications); - } - - return err; -} - -static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, - struct os_mbuf *msg) -{ - 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)); - - /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */ - mtu = ble_att_mtu(conn_handle) - 3; - if (mtu > msg->om_len) { - net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); - return proxy_send(conn_handle, msg->om_data, msg->om_len); - } - - net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); - proxy_send(conn_handle, msg->om_data, mtu); - net_buf_simple_pull_mem(msg, mtu); - - while (msg->om_len) { - if (msg->om_len + 1 < mtu) { - net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); - proxy_send(conn_handle, msg->om_data, msg->om_len); - break; - } - - net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); - proxy_send(conn_handle, msg->om_data, mtu); - net_buf_simple_pull_mem(msg, mtu); - } - - return 0; -} - -int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, - struct os_mbuf *msg) -{ - struct bt_mesh_proxy_client *client = find_client(conn_handle); - - if (!client) { - BT_ERR("No Proxy Client found"); - return -ENOTCONN; - } - - if ((client->filter_type == PROV) != (type == BT_MESH_PROXY_PROV)) { - BT_ERR("Invalid PDU type for Proxy Client"); - return -EINVAL; - } - - return proxy_segment_and_send(conn_handle, type, msg); -} - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -static uint8_t prov_svc_data[20] = { - BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL), -}; - -static const struct bt_data prov_ad[] = { - BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, - BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)), - BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), -}; -#endif /* PB_GATT */ - -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - -#define ID_TYPE_NET 0x00 -#define ID_TYPE_NODE 0x01 - -#define NODE_ID_LEN 19 -#define NET_ID_LEN 11 - -#define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BT_MESH_NODE_ID_TIMEOUT) - -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, - 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, - 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) -{ - uint8_t tmp[16]; - int err; - - BT_DBG(""); - - proxy_svc_data[2] = ID_TYPE_NODE; - - err = bt_rand(proxy_svc_data + 11, 8); - if (err) { - return err; - } - - memset(tmp, 0, 6); - memcpy(tmp + 6, proxy_svc_data + 11, 8); - sys_put_be16(bt_mesh_primary_addr(), tmp + 14); - - err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp, - tmp); - if (err) { - return err; - } - - memcpy(proxy_svc_data + 3, tmp + 8, 8); - - err = bt_le_adv_start(&fast_adv_param, node_id_ad, - ARRAY_SIZE(node_id_ad), NULL, 0); - if (err) { - BT_WARN("Failed to advertise using Node ID (err %d)", err); - return err; - } - - proxy_adv_enabled = true; - - return 0; -} - -static int net_id_adv(struct bt_mesh_subnet *sub) -{ - int err; - - BT_DBG(""); - - proxy_svc_data[2] = ID_TYPE_NET; - - BT_DBG("Advertising with NetId %s", - bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8)); - - memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8); - - err = bt_le_adv_start(&slow_adv_param, net_id_ad, - ARRAY_SIZE(net_id_ad), NULL, 0); - if (err) { - BT_WARN("Failed to advertise using Network ID (err %d)", err); - return err; - } - - proxy_adv_enabled = true; - - return 0; -} - -static bool advertise_subnet(struct bt_mesh_subnet *sub) -{ - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - return false; - } - - return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING || - bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED); -} - -static struct bt_mesh_subnet *next_sub(void) -{ - struct bt_mesh_subnet *sub = NULL; - - 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_cb(struct bt_mesh_subnet *sub, void *cb_data) -{ - int *count = cb_data; - - 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 int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) -{ - int32_t remaining = K_FOREVER; - int subnet_count; - - BT_DBG(""); - - if (conn_count == CONFIG_BT_MAX_CONN) { - 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 -ENOENT; - } - - if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) { - uint32_t active = k_uptime_get_32() - sub->node_id_start; - - if (active < NODE_ID_TIMEOUT) { - remaining = NODE_ID_TIMEOUT - active; - BT_DBG("Node ID active for %u ms, %d ms remaining", - (unsigned) active, (int) remaining); - node_id_adv(sub); - } else { - bt_mesh_proxy_identity_stop(sub); - BT_DBG("Node ID stopped"); - } - } - - if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) { - net_id_adv(sub); - } - - subnet_count = sub_count(); - BT_DBG("sub_count %u", subnet_count); - if (subnet_count > 1) { - 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 - * 6 slices, but make sure that a slice is at least one - * second long (to avoid excessive rotation). - */ - max_timeout = NODE_ID_TIMEOUT / max(subnet_count, 6); - max_timeout = max(max_timeout, K_SECONDS(1)); - - if (remaining > max_timeout || remaining < 0) { - remaining = max_timeout; - } - } - - 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 */ - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -static size_t gatt_prov_adv_create(struct bt_data prov_sd[2]) -{ - const struct bt_mesh_prov *prov = bt_mesh_prov_get(); - const char *name = CONFIG_BT_DEVICE_NAME; - size_t name_len = strlen(name); - size_t prov_sd_len = 0; - size_t sd_space = 31; - - memcpy(prov_svc_data + 2, prov->uuid, 16); - sys_put_be16(prov->oob_info, prov_svc_data + 18); - - if (prov->uri) { - size_t uri_len = strlen(prov->uri); - - if (uri_len > 29) { - /* There's no way to shorten an URI */ - BT_WARN("Too long URI to fit advertising packet"); - } else { - prov_sd[0].type = BT_DATA_URI; - prov_sd[0].data_len = uri_len; - prov_sd[0].data = (void *)prov->uri; - sd_space -= 2 + uri_len; - prov_sd_len++; - } - } - - if (sd_space > 2 && name_len > 0) { - sd_space -= 2; - - if (sd_space < name_len) { - prov_sd[prov_sd_len].type = BT_DATA_NAME_SHORTENED; - prov_sd[prov_sd_len].data_len = sd_space; - } else { - prov_sd[prov_sd_len].type = BT_DATA_NAME_COMPLETE; - prov_sd[prov_sd_len].data_len = name_len; - } - - prov_sd[prov_sd_len].data = (void *)name; - prov_sd_len++; - } - - return prov_sd_len; -} -#endif /* PB_GATT */ - -int32_t bt_mesh_proxy_adv_start(void) -{ - BT_DBG(""); - - if (gatt_svc == MESH_GATT_NONE) { - return K_FOREVER; - } - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - if (!bt_mesh_is_provisioned()) { - const struct ble_gap_adv_params *param; - struct bt_data prov_sd[2]; - size_t prov_sd_len; - - if (prov_fast_adv) { - param = &fast_adv_param; - } else { - param = &slow_adv_param; - } - - prov_sd_len = gatt_prov_adv_create(prov_sd); - - if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad), - prov_sd, prov_sd_len) == 0) { - proxy_adv_enabled = true; - - /* Advertise 60 seconds using fast interval */ - if (prov_fast_adv) { - prov_fast_adv = false; - return K_SECONDS(60); - } - } - } -#endif /* PB_GATT */ - -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - if (bt_mesh_is_provisioned()) { - return gatt_proxy_advertise(next_sub()); - } -#endif /* GATT_PROXY */ - - return K_FOREVER; -} - -void bt_mesh_proxy_adv_stop(void) -{ - int err; - - BT_DBG("adv_enabled %u", proxy_adv_enabled); - - if (!proxy_adv_enabled) { - return; - } - - err = bt_le_adv_stop(true); - if (err) { - BT_ERR("Failed to stop advertising (err %d)", err); - } else { - proxy_adv_enabled = false; - } -} - -#if defined(CONFIG_BT_MESH_GATT_PROXY) -static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) -{ - if (evt == BT_MESH_KEY_DELETED) { - if (sub == beacon_sub) { - beacon_sub = NULL; - } - } else { - bt_mesh_proxy_beacon_send(sub); - } -} -#endif - -static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) -{ -#if MYNEWT_VAL(BLE_EXT_ADV) - /* When EXT ADV is enabled then mesh proxy is connected - * when proxy advertising instance is completed. - * Therefore no need to handle BLE_GAP_EVENT_CONNECT - */ - if (event->type == BLE_GAP_EVENT_ADV_COMPLETE) { - /* Reason 0 means advertising has been completed because - * connection has been established - */ - if (event->adv_complete.reason != 0) { - return; - } - - if (event->adv_complete.instance != BT_MESH_ADV_GATT_INST) { - return; - } - - proxy_connected(event->adv_complete.conn_handle); - } -#else - if (event->type == BLE_GAP_EVENT_CONNECT) { - proxy_connected(event->connect.conn_handle); - } -#endif -} - -int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) -{ - if ((event->type == BLE_GAP_EVENT_CONNECT) || - (event->type == BLE_GAP_EVENT_ADV_COMPLETE)) { - ble_mesh_handle_connect(event, arg); - } else if (event->type == BLE_GAP_EVENT_DISCONNECT) { - proxy_disconnected(event->disconnect.conn.conn_handle, - event->disconnect.reason); - } else if (event->type == BLE_GAP_EVENT_SUBSCRIBE) { - if (event->subscribe.attr_handle == svc_handles.proxy_data_out_h) { -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - proxy_ccc_write(event->subscribe.conn_handle); -#endif - } else if (event->subscribe.attr_handle == - svc_handles.prov_data_out_h) { -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - prov_ccc_write(event->subscribe.conn_handle); -#endif - } - } - - return 0; -} - -static int -dummy_access_cb(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - /* - * We should never never enter this callback - it's attached to notify-only - * characteristic which are notified directly from mbuf. And we can't pass - * NULL as access_cb because gatts will assert on init... - */ - BLE_HS_DBG_ASSERT(0); - return 0; -} - -static const struct ble_gatt_svc_def svc_defs [] = { - { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_IN_VAL), - .access_cb = proxy_recv, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, { - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), - .characteristics = (struct ble_gatt_chr_def[]) { { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_IN_VAL), - .access_cb = proxy_recv, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - .uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_DATA_OUT_VAL), - .access_cb = dummy_access_cb, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, { - 0, /* No more services. */ - }, -}; - -int bt_mesh_proxy_svcs_register(void) -{ - int rc; - - rc = ble_gatts_count_cfg(svc_defs); - assert(rc == 0); - - rc = ble_gatts_add_svcs(svc_defs); - assert(rc == 0); - - return 0; -} - -int bt_mesh_proxy_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); -#endif - clients[i].buf = NET_BUF_SIMPLE(CLIENT_BUF_SIZE); - clients[i].conn_handle = BLE_HS_CONN_HANDLE_NONE; - - k_delayed_work_init(&clients[i].sar_timer, proxy_sar_timeout); - k_delayed_work_add_arg(&clients[i].sar_timer, &clients[i]); - } - - resolve_svc_handles(); - - ble_gatts_svc_set_visibility(svc_handles.proxy_h, 0); - ble_gatts_svc_set_visibility(svc_handles.prov_h, 0); - - return 0; -} - -void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb) -{ - if (!atomic_get(&pending_notifications)) { - cb->cb(); - return; - } - - sys_slist_append(&idle_waiters, &cb->n); -} - -#endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ diff --git a/src/nimble/nimble/host/mesh/src/proxy.h b/src/nimble/nimble/host/mesh/src/proxy.h deleted file mode 100644 index 0f86e1c79..000000000 --- a/src/nimble/nimble/host/mesh/src/proxy.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __PROXY_H__ -#define __PROXY_H__ - -#include "nimble/nimble/host/mesh/include/mesh/slist.h" - -#if CONFIG_BT_MESH_DEBUG_USE_ID_ADDR -#define ADV_OPT_USE_IDENTITY BT_LE_ADV_OPT_USE_IDENTITY -#else -#define ADV_OPT_USE_IDENTITY 0 -#endif - -#define ADV_SLOW_INT \ -.itvl_min = BT_GAP_ADV_SLOW_INT_MIN, \ -.itvl_max = BT_GAP_ADV_SLOW_INT_MAX, - -#define ADV_FAST_INT \ -.itvl_min = BT_GAP_ADV_FAST_INT_MIN_2, \ -.itvl_max = BT_GAP_ADV_FAST_INT_MAX_2, - -struct bt_mesh_proxy_idle_cb { - sys_snode_t n; - void (*cb)(void); -}; - -void notify_complete(void); -int bt_mesh_proxy_gatt_enable(void); -int bt_mesh_proxy_gatt_disable(void); -void bt_mesh_proxy_gatt_disconnect(void); - -void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub); - -int bt_mesh_proxy_adv_start(void); - -void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub); -void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub); - -bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst); -void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr); - -int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg); -int bt_mesh_proxy_init(void); - -#endif /* __PROXY_H__ */ diff --git a/src/nimble/nimble/host/mesh/src/proxy_msg.c b/src/nimble/nimble/host/mesh/src/proxy_msg.c deleted file mode 100644 index 5df9aa311..000000000 --- a/src/nimble/nimble/host/mesh/src/proxy_msg.c +++ /dev/null @@ -1,235 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2021 Lingao Meng - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#define MESH_LOG_MODULE BLE_MESH_PROXY_LOG - -#if MYNEWT_VAL(BLE_MESH_PROXY) - -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/include/host/ble_att.h" -#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" -#include "nimble/nimble/host/src/ble_hs_priv.h" - -#include "mesh_priv.h" -#include "adv.h" -#include "net.h" -#include "rpl.h" -#include "prov.h" -#include "beacon.h" -#include "foundation.h" -#include "access.h" -#include "proxy.h" -#include "proxy_msg.h" - -#define PDU_SAR(data) (data[0] >> 6) - -#define BT_UUID_16_ENCODE(w16) \ - (((w16) >> 0) & 0xFF), \ - (((w16) >> 8) & 0xFF) -/* Mesh Profile 1.0 Section 6.6: - * "The timeout for the SAR transfer is 20 seconds. When the timeout - * expires, the Proxy Server shall disconnect." - */ -#define PROXY_SAR_TIMEOUT K_SECONDS(20) - -#define SAR_COMPLETE 0x00 -#define SAR_FIRST 0x01 -#define SAR_CONT 0x02 -#define SAR_LAST 0x03 - -#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) - -static uint8_t bufs[CONFIG_BT_MAX_CONN * CONFIG_BT_MESH_PROXY_MSG_LEN]; - -static struct bt_mesh_proxy_role roles[CONFIG_BT_MAX_CONN]; - -static void proxy_sar_timeout(struct ble_npl_event *work) -{ - struct bt_mesh_proxy_role *role; - int rc; - role = ble_npl_event_get_arg(work); - - - BT_WARN("Proxy SAR timeout"); - - if (role->conn_handle) { - rc = ble_gap_terminate(role->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); - } -} - -int bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, - const void *buf, uint16_t len) -{ - const uint8_t *data = buf; - - switch (PDU_SAR(data)) { - case SAR_COMPLETE: - if (role->buf->om_len) { - BT_WARN("Complete PDU while a pending incomplete one"); - return -EINVAL; - } - - role->msg_type = PDU_TYPE(data); - net_buf_simple_add_mem(role->buf, data + 1, len - 1); - role->cb.recv(role); - net_buf_simple_reset(role->buf); - break; - - case SAR_FIRST: - if (role->buf->om_len) { - BT_WARN("First PDU while a pending incomplete one"); - return -EINVAL; - } - - k_work_reschedule(&role->sar_timer, PROXY_SAR_TIMEOUT); - role->msg_type = PDU_TYPE(data); - net_buf_simple_add_mem(role->buf, data + 1, len - 1); - break; - - case SAR_CONT: - if (!role->buf->om_len) { - BT_WARN("Continuation with no prior data"); - return -EINVAL; - } - - if (role->msg_type != PDU_TYPE(data)) { - BT_WARN("Unexpected message type in continuation"); - return -EINVAL; - } - - k_work_reschedule(&role->sar_timer, PROXY_SAR_TIMEOUT); - net_buf_simple_add_mem(role->buf, data + 1, len - 1); - break; - - case SAR_LAST: - if (!role->buf->om_len) { - BT_WARN("Last SAR PDU with no prior data"); - return -EINVAL; - } - - if (role->msg_type != PDU_TYPE(data)) { - BT_WARN("Unexpected message type in last SAR PDU"); - return -EINVAL; - } - - /* If this fails, the work handler exits early, as there's no - * active SAR buffer. - */ - (void)k_work_cancel_delayable(&role->sar_timer); - net_buf_simple_add_mem(role->buf, data + 1, len - 1); - role->cb.recv(role); - net_buf_simple_reset(role->buf); - break; - } - - return len; -} - -int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, - struct os_mbuf *msg) -{ - int err; - uint16_t mtu; - uint16_t conn_handle = role->conn_handle; - - BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len, - bt_hex(msg->om_data, msg->om_len)); - - /* ATT_MTU - OpCode (1 byte) - Handle (2 bytes) */ - mtu = ble_att_mtu(conn_handle) - 3; - if (mtu > msg->om_len) { - net_buf_simple_push_u8(msg, PDU_HDR(SAR_COMPLETE, type)); - return role->cb.send(conn_handle, msg->om_data, msg->om_len); - } - - net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); - err = role->cb.send(conn_handle, msg->om_data, mtu); - if (err) { - return err; - } - net_buf_simple_pull_mem(msg, mtu); - - while (msg->om_len) { - if (msg->om_len + 1 < mtu) { - net_buf_simple_push_u8(msg, PDU_HDR(SAR_LAST, type)); - err = role->cb.send(conn_handle, msg->om_data, msg->om_len); - if (err) { - return err; - } - break; - } - - net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); - err = role->cb.send(conn_handle, msg->om_data, mtu); - if (err) { - return err; - } - net_buf_simple_pull_mem(msg, mtu); - } - - return 0; -} - -static void proxy_msg_init(struct bt_mesh_proxy_role *role) -{ - - /* Check if buf has been allocated, in this way, we no longer need - * to repeat the operation. - */ - if (role->buf != NULL) { - net_buf_simple_reset(role->buf); - return; - } - - role->buf = NET_BUF_SIMPLE(CONFIG_BT_MESH_PROXY_MSG_LEN); - net_buf_simple_init_with_data(role->buf, - &bufs[role->conn_handle * - CONFIG_BT_MESH_PROXY_MSG_LEN], - CONFIG_BT_MESH_PROXY_MSG_LEN); - - net_buf_simple_reset(role->buf); - - k_work_init_delayable(&role->sar_timer, proxy_sar_timeout); - k_work_add_arg_delayable(&role->sar_timer, role); -} - -struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(uint16_t conn_handle, - proxy_send_cb_t send, - proxy_recv_cb_t recv) -{ - struct bt_mesh_proxy_role *role; - - role = &roles[conn_handle]; - - role->conn_handle = conn_handle; - proxy_msg_init(role); - - role->cb.recv = recv; - role->cb.send = send; - - return role; -} - -void bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role *role) -{ - - /* If this fails, the work handler exits early, as - * there's no active connection. - */ - (void)k_work_cancel_delayable(&role->sar_timer); - - role->conn_handle = BLE_HS_CONN_HANDLE_NONE; - - bt_mesh_adv_update(); -} - -#endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ diff --git a/src/nimble/nimble/host/mesh/src/proxy_msg.h b/src/nimble/nimble/host/mesh/src/proxy_msg.h deleted file mode 100644 index dabe7e80c..000000000 --- a/src/nimble/nimble/host/mesh/src/proxy_msg.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2021 Lingao Meng - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_MSG_H_ -#define ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_MSG_H_ - -#define PDU_TYPE(data) (data[0] & BIT_MASK(6)) -#define CFG_FILTER_SET 0x00 -#define CFG_FILTER_ADD 0x01 -#define CFG_FILTER_REMOVE 0x02 -#define CFG_FILTER_STATUS 0x03 - -#define BT_MESH_PROXY_NET_PDU 0x00 -#define BT_MESH_PROXY_BEACON 0x01 -#define BT_MESH_PROXY_CONFIG 0x02 -#define BT_MESH_PROXY_PROV 0x03 - -#define PDU_HDR(sar, type) (sar << 6 | (type & BIT_MASK(6))) - -struct bt_mesh_proxy_role; - -typedef int (*proxy_send_cb_t)(uint16_t conn_handle, - const void *data, uint16_t len); - -typedef void (*proxy_recv_cb_t)(struct bt_mesh_proxy_role *role); - -struct bt_mesh_proxy_role { - uint16_t conn_handle; - uint8_t msg_type; - - struct { - proxy_send_cb_t send; - proxy_recv_cb_t recv; - } cb; - - struct k_work_delayable sar_timer; - struct os_mbuf *buf; -}; - -struct bt_mesh_proxy_client { - struct bt_mesh_proxy_role *cli; - uint16_t conn_handle; - uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)]; - enum __packed { - NONE, - ACCEPT, - REJECT, - } filter_type; - struct ble_npl_callout send_beacons; -}; - -int bt_mesh_proxy_msg_recv(struct bt_mesh_proxy_role *role, - const void *buf, uint16_t len); -int bt_mesh_proxy_msg_send(struct bt_mesh_proxy_role *role, uint8_t type, struct os_mbuf *msg); -void bt_mesh_proxy_msg_init(struct bt_mesh_proxy_role *role); -void bt_mesh_proxy_role_cleanup(struct bt_mesh_proxy_role *role); -struct bt_mesh_proxy_role *bt_mesh_proxy_role_setup(uint16_t conn_handle, - proxy_send_cb_t send, - proxy_recv_cb_t recv); -struct bt_mesh_proxy_client *find_client(uint16_t conn_handle); -#endif /* ZEPHYR_SUBSYS_BLUETOOTH_MESH_PROXY_MSG_H_ */ diff --git a/src/nimble/nimble/host/mesh/src/proxy_srv.c b/src/nimble/nimble/host/mesh/src/proxy_srv.c deleted file mode 100644 index 1b3788964..000000000 --- a/src/nimble/nimble/host/mesh/src/proxy_srv.c +++ /dev/null @@ -1,1020 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2021 Lingao Meng - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_PROXY_LOG - -#include "nimble/nimble/host/mesh/include/mesh/slist.h" -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/src/ble_hs_priv.h" -#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" - -#include "mesh_priv.h" -#include "adv.h" -#include "net.h" -#include "rpl.h" -#include "transport.h" -#include "prov.h" -#include "beacon.h" -#include "foundation.h" -#include "access.h" -#include "proxy.h" -#include "proxy_msg.h" -#include "pb_gatt_srv.h" - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#if defined(CONFIG_BT_MESH_PROXY_USE_DEVICE_NAME) -#define ADV_OPT_USE_NAME BT_LE_ADV_OPT_USE_NAME -#else -#define ADV_OPT_USE_NAME 0 -#endif - -#define ADV_OPT_PROXY \ -.conn_mode = (BLE_GAP_CONN_MODE_UND), \ -.disc_mode = (BLE_GAP_DISC_MODE_GEN), - - -#define BT_UUID_MESH_PROXY_VAL 0x1828 -#define CLIENT_BUF_SIZE 66 - -#define BT_UUID_16_ENCODE(w16) \ - (((w16) >> 0) & 0xFF), \ - (((w16) >> 8) & 0xFF) - -static sys_slist_t idle_waiters; -static atomic_t pending_notifications; - -static void proxy_send_beacons(struct ble_npl_event *work); - -static int proxy_send(uint16_t conn_handle, - const void *data, uint16_t len); - - -static struct bt_mesh_proxy_client clients[CONFIG_BT_MAX_CONN]; - -static bool service_registered; - -static int conn_count; - -struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle == conn_handle) { - return &clients[i]; - } - } - return NULL; -} - -static struct bt_mesh_proxy_client *get_client(uint16_t conn_handle) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].conn_handle == 0xffff) { - clients[i].conn_handle = conn_handle; - return &clients[i]; - } - } - return NULL; -} - -/* Next subnet in queue to be advertised */ -static struct bt_mesh_subnet *beacon_sub; - -static int filter_set(struct bt_mesh_proxy_client *client, - struct os_mbuf *buf) -{ - uint8_t type; - - if (buf->om_len < 1) { - BT_WARN("Too short Filter Set message"); - return -EINVAL; - } - - type = net_buf_simple_pull_u8(buf); - BT_DBG("type 0x%02x", type); - - switch (type) { - case 0x00: - (void)memset(client->filter, 0, sizeof(client->filter)); - client->filter_type = ACCEPT; - break; - case 0x01: - (void)memset(client->filter, 0, sizeof(client->filter)); - client->filter_type = REJECT; - break; - default: - BT_WARN("Prohibited Filter Type 0x%02x", type); - return -EINVAL; - } - - return 0; -} - -static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr) -{ - int i; - - BT_DBG("addr 0x%04x", addr); - - if (addr == BT_MESH_ADDR_UNASSIGNED) { - return; - } - - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - return; - } - } - - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == BT_MESH_ADDR_UNASSIGNED) { - client->filter[i] = addr; - return; - } - } -} - -static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr) -{ - int i; - - BT_DBG("addr 0x%04x", addr); - - if (addr == BT_MESH_ADDR_UNASSIGNED) { - return; - } - - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - client->filter[i] = BT_MESH_ADDR_UNASSIGNED; - return; - } - } -} - -static void send_filter_status(struct bt_mesh_proxy_client *client, - struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - struct bt_mesh_net_tx tx = { - .sub = rx->sub, - .ctx = &rx->ctx, - .src = bt_mesh_primary_addr(), - }; - uint16_t filter_size; - int i, err; - - /* Configuration messages always have dst unassigned */ - tx.ctx->addr = BT_MESH_ADDR_UNASSIGNED; - - net_buf_simple_init(buf, 10); - - net_buf_simple_add_u8(buf, CFG_FILTER_STATUS); - - if (client->filter_type == ACCEPT) { - net_buf_simple_add_u8(buf, 0x00); - } else { - net_buf_simple_add_u8(buf, 0x01); - } - - for (filter_size = 0U, i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] != BT_MESH_ADDR_UNASSIGNED) { - filter_size++; - } - } - - net_buf_simple_add_be16(buf, filter_size); - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - err = bt_mesh_net_encode(&tx, buf, true); - if (err) { - BT_ERR("Encoding Proxy cfg message failed (err %d)", err); - return; - } - - err = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_CONFIG, buf); - if (err) { - BT_ERR("Failed to send proxy cfg message (err %d)", err); - } -} - -static void proxy_filter_recv(uint16_t conn_handle, - struct bt_mesh_net_rx *rx, struct os_mbuf *buf) -{ - struct bt_mesh_proxy_client *client; - uint8_t opcode; - - client = find_client(conn_handle); - - opcode = net_buf_simple_pull_u8(buf); - switch (opcode) { - case CFG_FILTER_SET: - filter_set(client, buf); - send_filter_status(client, rx, buf); - break; - case CFG_FILTER_ADD: - while (buf->om_len >= 2) { - uint16_t addr; - - addr = net_buf_simple_pull_be16(buf); - filter_add(client, addr); - } - send_filter_status(client, rx, buf); - break; - case CFG_FILTER_REMOVE: - while (buf->om_len >= 2) { - uint16_t addr; - - addr = net_buf_simple_pull_be16(buf); - filter_remove(client, addr); - } - send_filter_status(client, rx, buf); - break; - default: - BT_WARN("Unhandled configuration OpCode 0x%02x", opcode); - break; - } -} - -static void proxy_cfg(struct bt_mesh_proxy_role *role) -{ - struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_NET_MAX_PDU_LEN); - struct bt_mesh_net_rx rx; - int err; - - err = bt_mesh_net_decode(role->buf, BT_MESH_NET_IF_PROXY_CFG, - &rx, buf); - if (err) { - BT_ERR("Failed to decode Proxy Configuration (err %d)", err); - return; - } - - rx.local_match = 1U; - - if (bt_mesh_rpl_check(&rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06" PRIx32, - rx.ctx.addr, rx.ctx.recv_dst, rx.seq); - return; - } - - /* Remove network headers */ - net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN); - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (buf->om_len < 1) { - BT_WARN("Too short proxy configuration PDU"); - return; - } - - proxy_filter_recv(role->conn_handle, &rx, buf); -} - -static void proxy_msg_recv(struct bt_mesh_proxy_role *role) -{ - switch (role->msg_type) { - case BT_MESH_PROXY_NET_PDU: - BT_DBG("Mesh Network PDU"); - bt_mesh_net_recv(role->buf, 0, BT_MESH_NET_IF_PROXY); - break; - case BT_MESH_PROXY_BEACON: - BT_DBG("Mesh Beacon PDU"); - bt_mesh_beacon_recv(role->buf); - break; - case BT_MESH_PROXY_CONFIG: - BT_DBG("Mesh Configuration PDU"); - proxy_cfg(role); - break; - default: - BT_WARN("Unhandled Message Type 0x%02x", role->msg_type); - break; - } -} - -static int beacon_send(struct bt_mesh_proxy_client *client, struct bt_mesh_subnet *sub) -{ - struct os_mbuf *buf = NET_BUF_SIMPLE(23); - int rc; - - net_buf_simple_init(buf, 1); - bt_mesh_beacon_create(sub, buf); - - rc = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_BEACON, buf); - os_mbuf_free_chain(buf); - 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, sub); -} - -static void proxy_send_beacons(struct ble_npl_event *work) -{ - struct bt_mesh_proxy_client *client; - - client = ble_npl_event_get_arg(work); - - (void)bt_mesh_subnet_find(send_beacon_cb, client); -} - -void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub) -{ - int i; - - if (!sub) { - /* NULL means we send on all subnets */ - bt_mesh_subnet_foreach(bt_mesh_proxy_beacon_send); - return; - } - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].cli) { - beacon_send(&clients[i], 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 */ - beacon_sub = sub; -} - -void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub) - { - sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED; - sub->node_id_start = 0U; -} - -int bt_mesh_proxy_identity_enable(void) -{ - BT_DBG(""); - - if (!bt_mesh_is_provisioned()) { - return -EAGAIN; - } - - if (bt_mesh_subnet_foreach(node_id_start)) { - bt_mesh_adv_update(); - } - - return 0; -} - -#define ID_TYPE_NET 0x00 -#define ID_TYPE_NODE 0x01 - -#define NODE_ID_LEN 19 -#define NET_ID_LEN 11 - -#define NODE_ID_TIMEOUT (CONFIG_BT_MESH_NODE_ID_TIMEOUT * MSEC_PER_SEC) - -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, - 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, - 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, int32_t duration) -{ - struct ble_gap_adv_params fast_adv_param = { - ADV_OPT_PROXY - ADV_FAST_INT - }; -#if ADV_OPT_USE_NAME - const char *name = CONFIG_BT_DEVICE_NAME; - size_t name_len = strlen(name); - struct bt_data sd = { - .type = BT_DATA_NAME_COMPLETE, - .data_len = name_len, - .data = (void *)name - }; -#else - struct bt_data *sd = NULL; -#endif - uint8_t tmp[16]; - int err; - - BT_DBG(""); - - proxy_svc_data[2] = ID_TYPE_NODE; - - err = bt_rand(proxy_svc_data + 11, 8); - if (err) { - return err; - } - - (void)memset(tmp, 0, 6); - memcpy(tmp + 6, proxy_svc_data + 11, 8); - sys_put_be16(bt_mesh_primary_addr(), tmp + 14); - - err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp, - tmp); - if (err) { - return err; - } - - memcpy(proxy_svc_data + 3, tmp + 8, 8); - - err = bt_mesh_adv_start(&fast_adv_param, duration, node_id_ad, - ARRAY_SIZE(node_id_ad), sd, 0); - if (err) { - BT_WARN("Failed to advertise using Node ID (err %d)", err); - return err; - } - - return 0; -} - -static int net_id_adv(struct bt_mesh_subnet *sub, int32_t duration) -{ - struct ble_gap_adv_params slow_adv_param = { - ADV_OPT_PROXY - ADV_SLOW_INT - }; -#if ADV_OPT_USE_NAME - const char *name = CONFIG_BT_DEVICE_NAME; - size_t name_len = strlen(name); - struct bt_data sd = { - .type = BT_DATA_NAME_COMPLETE, - .data_len = name_len, - .data = (void *)name - }; -#else - struct bt_data *sd = NULL; -#endif - int err; - - BT_DBG(""); - - proxy_svc_data[2] = ID_TYPE_NET; - - BT_DBG("Advertising with NetId %s", - bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8)); - - memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8); - - err = bt_mesh_adv_start(&slow_adv_param, duration, net_id_ad, - ARRAY_SIZE(net_id_ad), sd, 0); - if (err) { - BT_WARN("Failed to advertise using Network ID (err %d)", err); - return err; - } - - return 0; -} - -static bool advertise_subnet(struct bt_mesh_subnet *sub) -{ - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - return false; - } - - return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING || - bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED); -} - -static struct bt_mesh_subnet *next_sub(void) -{ - struct bt_mesh_subnet *sub = NULL; - - 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_cb(struct bt_mesh_subnet *sub, void *cb_data) -{ - int *count = cb_data; - - 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 int gatt_proxy_advertise(struct bt_mesh_subnet *sub) -{ - int32_t remaining = K_FOREVER; - int subnet_count; - int err = -EBUSY; - - BT_DBG(""); - - if (conn_count == CONFIG_BT_MAX_CONN) { - 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 -ENOENT; - } - - subnet_count = sub_count(); - BT_DBG("sub_count %u", subnet_count); - if (subnet_count > 1) { - 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 - * 6 slices, but make sure that a slice is at least one - * second long (to avoid excessive rotation). - */ - max_timeout = NODE_ID_TIMEOUT / MAX(subnet_count, 6); - max_timeout = MAX(max_timeout, K_SECONDS(1)); - - if (remaining > max_timeout || remaining < 0) { - remaining = max_timeout; - } - } - - if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) { - uint32_t active = k_uptime_get_32() - sub->node_id_start; - - if (active < NODE_ID_TIMEOUT) { - remaining = NODE_ID_TIMEOUT - active; - BT_DBG("Node ID active for %u ms, %d ms remaining", - active, remaining); - err = node_id_adv(sub, remaining); - } else { - bt_mesh_proxy_identity_stop(sub); - BT_DBG("Node ID stopped"); - } - } - - if (sub->node_id == BT_MESH_NODE_IDENTITY_STOPPED) { - err = net_id_adv(sub, remaining); - } - - BT_DBG("Advertising %d ms for net_idx 0x%04x", - (int) remaining, sub->net_idx); - - beacon_sub = bt_mesh_subnet_next(beacon_sub); - - return err; -} - -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); - } -} - -static void proxy_ccc_write(uint16_t conn_handle) -{ - struct bt_mesh_proxy_client *client; - - BT_DBG("conn_handle %d", conn_handle); - - client = find_client(conn_handle); - - if (client->filter_type == NONE) { - client->filter_type = ACCEPT; - k_work_add_arg(&client->send_beacons, client); - k_work_submit(&client->send_beacons); - } -} - -int bt_mesh_proxy_gatt_enable(void) -{ - uint16_t handle; - int rc; - int i; - - BT_DBG(""); - - if (!bt_mesh_is_provisioned()) { - return -ENOTSUP; - } - - if (service_registered) { - return -EBUSY; - } - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 1); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff); - - service_registered = true; - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i].cli) { - clients[i].filter_type = ACCEPT; - } - } - return 0; -} - -void bt_mesh_proxy_gatt_disconnect(void) -{ - int rc; - int i; - - BT_DBG(""); - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; - - if ((client->cli) && - (client->filter_type == ACCEPT || - client->filter_type == REJECT)) { - client->filter_type = NONE; - rc = ble_gap_terminate(client->cli->conn_handle, - BLE_ERR_REM_USER_CONN_TERM); - assert(rc == 0); - } - } -} - -int bt_mesh_proxy_gatt_disable(void) -{ - uint16_t handle; - int rc; - BT_DBG(""); - - if (!service_registered) { - return -EALREADY; - } - - bt_mesh_proxy_gatt_disconnect(); - - rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); - assert(rc == 0); - ble_gatts_svc_set_visibility(handle, 0); - /* FIXME: figure out end handle */ - ble_svc_gatt_changed(svc_handles.proxy_h, 0xffff); - service_registered = false; - - return 0; -} - -void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr) -{ - struct bt_mesh_proxy_client *client; - struct bt_mesh_proxy_role *cli = - CONTAINER_OF(buf, struct bt_mesh_proxy_role, buf); - - client = find_client(cli->conn_handle); - - BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); - - if (client->filter_type == ACCEPT) { - filter_add(client, addr); - } else if (client->filter_type == REJECT) { - filter_remove(client, addr); - } -} - -static bool client_filter_match(struct bt_mesh_proxy_client *client, - uint16_t addr) -{ - int i; - - BT_DBG("filter_type %u addr 0x%04x", client->filter_type, addr); - - if (client->filter_type == REJECT) { - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - return false; - } - } - - return true; - } - - if (addr == BT_MESH_ADDR_ALL_NODES) { - return true; - } - - if (client->filter_type == ACCEPT) { - for (i = 0; i < ARRAY_SIZE(client->filter); i++) { - if (client->filter[i] == addr) { - return true; - } - } - } - - return false; -} - -bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) -{ - const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb; - void *cb_data = BT_MESH_ADV(buf)->cb_data; - bool relayed = false; - int i, err; - - BT_DBG("%u bytes to dst 0x%04x", buf->om_len, dst); - - for (i = 0; i < ARRAY_SIZE(clients); i++) { - struct bt_mesh_proxy_client *client = &clients[i]; - struct os_mbuf *msg; - - if (!client->cli) { - continue; - } - - if (!client_filter_match(client, dst)) { - continue; - } - - /* Proxy PDU sending modifies the original buffer, - * so we need to make a copy. - */ - msg = NET_BUF_SIMPLE(32); - net_buf_simple_init(msg, 1); - net_buf_simple_add_mem(msg, buf->om_data, buf->om_len); - - err = bt_mesh_proxy_msg_send(client->cli, BT_MESH_PROXY_NET_PDU, - msg); - - adv_send_start(0, err, cb, cb_data); - if (err) { - BT_ERR("Failed to send proxy message (err %d)", err); - - /* If segment_and_send() fails the buf_send_end() callback will - * not be called, so we need to clear the user data (net_buf, - * which is just opaque data to segment_and send) reference given - * to segment_and_send() here. - */ - net_buf_unref(buf); - continue; - } - os_mbuf_free_chain(msg); - relayed = true; - } - - return relayed; -} - -static void gatt_connected(uint16_t conn_handle) -{ - struct bt_mesh_proxy_client *client; - struct ble_gap_conn_desc info; - struct ble_hs_conn *conn; - - conn = ble_hs_conn_find(conn_handle); - bt_conn_get_info(conn, &info); - if (info.role != BLE_GAP_ROLE_SLAVE || - !service_registered) { - return; - } - BT_DBG("conn %d", conn_handle); - - conn_count++; - - client = get_client(conn_handle); - assert(client); - - client->filter_type = NONE; - (void)memset(client->filter, 0, sizeof(client->filter)); - - client->cli = bt_mesh_proxy_role_setup(conn_handle, proxy_send, - proxy_msg_recv); - - /* Try to re-enable advertising in case it's possible */ - if (conn_count < CONFIG_BT_MAX_CONN) { - bt_mesh_adv_update(); - } -} - -static void gatt_disconnected(struct ble_gap_conn_desc conn, uint8_t reason) -{ - struct bt_mesh_proxy_client *client; - - if (conn.role != BLE_GAP_ROLE_SLAVE) { - return; - } - - if (!service_registered && bt_mesh_is_provisioned()) { - (void)bt_mesh_proxy_gatt_enable(); - return; - } - - conn_count--; - client = find_client(conn.conn_handle); - if (client->cli) { - bt_mesh_proxy_role_cleanup(client->cli); - client->cli = NULL; - } - - client->conn_handle = 0xffff; -} - -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)); - - om = ble_hs_mbuf_from_flat(data, len); - assert(om); - err = ble_gatts_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); - notify_complete(); - - if (!err) { - atomic_inc(&pending_notifications); - } - - return err; -} - -int bt_mesh_proxy_adv_start(void) -{ - BT_DBG(""); - - if (!service_registered || !bt_mesh_is_provisioned()) { - return -ENOTSUP; - } - - return gatt_proxy_advertise(next_sub()); -} - - -static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) -{ -#if MYNEWT_VAL(BLE_EXT_ADV) - /* When EXT ADV is enabled then mesh proxy is connected - * when proxy advertising instance is completed. - * Therefore no need to handle BLE_GAP_EVENT_CONNECT - */ - if (event->type == BLE_GAP_EVENT_ADV_COMPLETE) { - /* Reason 0 means advertising has been completed because - * connection has been established - */ - if (event->adv_complete.reason != 0) { - return; - } - -#if MYNEWT_VAL(BLE_MESH_PROXY) - if (event->adv_complete.instance != BT_MESH_ADV_GATT_INST) { - return; - } -#endif - - gatt_connected(event->adv_complete.conn_handle); -#if MYNEWT_VAL(BLE_MESH_PB_GATT) - gatt_connected_pb_gatt(event->adv_complete.conn_handle, - event->adv_complete.reason); -#endif - } -#else - if (event->type == BLE_GAP_EVENT_CONNECT) { - gatt_connected(event->connect.conn_handle); -#if MYNEWT_VAL(BLE_MESH_PB_GATT) - gatt_connected_pb_gatt(event->connect.conn_handle, event->connect.status); -#endif - } -#endif -} - -int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg) -{ - if ((event->type == BLE_GAP_EVENT_CONNECT) || - (event->type == BLE_GAP_EVENT_ADV_COMPLETE)) { - ble_mesh_handle_connect(event, arg); - } else if (event->type == BLE_GAP_EVENT_DISCONNECT) { - gatt_disconnected(event->disconnect.conn, - event->disconnect.reason); -#if MYNEWT_VAL(BLE_MESH_PB_GATT) - gatt_disconnected_pb_gatt(event->disconnect.conn, - event->disconnect.reason); -#endif - } else if (event->type == BLE_GAP_EVENT_SUBSCRIBE) { - if (event->subscribe.attr_handle == svc_handles.proxy_data_out_h) { -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - proxy_ccc_write(event->subscribe.conn_handle); -#endif - } else if (event->subscribe.attr_handle == - svc_handles.prov_data_out_h) { -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - prov_ccc_write(event->subscribe.conn_handle, event->type); -#endif - } - } - - return 0; -} - -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); -#endif - clients[i].conn_handle = 0xffff; - } - - resolve_svc_handles(); - - ble_gatts_svc_set_visibility(svc_handles.proxy_h, 0); - ble_gatts_svc_set_visibility(svc_handles.prov_h, 0); - - return 0; -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/rpl.c b/src/nimble/nimble/host/mesh/src/rpl.c deleted file mode 100644 index 86ae6bd36..000000000 --- a/src/nimble/nimble/host/mesh/src/rpl.c +++ /dev/null @@ -1,385 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2020 Lingao Meng - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_RPL_LOG - -#include "nimble/porting/nimble/include/log/log.h" -#include - -#include "mesh_priv.h" -#include "adv.h" -#include "net.h" -#include "rpl.h" -#include "settings.h" - -/* Replay Protection List information for persistent storage. */ -struct rpl_val { - uint32_t seq:24, - old_iv:1; -}; - -static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)]; -static ATOMIC_DEFINE(store, MYNEWT_VAL(BLE_MESH_CRPL)); - -static inline int rpl_idx(const struct bt_mesh_rpl *rpl) -{ - return rpl - &replay_list[0]; -} - -static void clear_rpl(struct bt_mesh_rpl *rpl) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - int err; - char path[18]; - - if (!rpl->src) { - return; - } - - snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear RPL"); - } else { - BT_DBG("Cleared RPL"); - } - - (void)memset(rpl, 0, sizeof(*rpl)); - atomic_clear_bit(store, rpl_idx(rpl)); -#endif -} - -static void schedule_rpl_store(struct bt_mesh_rpl *entry, bool force) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - atomic_set_bit(store, rpl_idx(entry)); - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); - if (force -#ifdef CONFIG_BT_MESH_RPL_STORE_TIMEOUT - || CONFIG_BT_MESH_RPL_STORE_TIMEOUT >= 0 -#endif - ) { - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); - } -#endif -} - -static void schedule_rpl_clear(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_RPL_PENDING); -#endif -} - -void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, - struct bt_mesh_net_rx *rx) -{ - /* If this is the first message on the new IV index, we should reset it - * to zero to avoid invalid combinations of IV index and seg. - */ - if (rpl->old_iv && !rx->old_iv) { - rpl->seg = 0; - } - - rpl->src = rx->ctx.addr; - rpl->seq = rx->seq; - rpl->old_iv = rx->old_iv; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - schedule_rpl_store(rpl, false); - } -} - -/* 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)) { - schedule_rpl_clear(); - } else { - (void)memset(replay_list, 0, sizeof(replay_list)); - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static 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; -} - -static 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; -} -#endif - -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) { - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - clear_rpl(rpl); - } else { - (void)memset(rpl, 0, sizeof(*rpl)); - } - } else { - rpl->old_iv = true; - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - schedule_rpl_store(rpl, true); - } - } - } - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static int rpl_set(int argc, char **argv, char *val) -{ - struct bt_mesh_rpl *entry; - struct rpl_val rpl; - int len, err; - uint16_t src; - - if (argc < 1) { - BT_ERR("Invalid argc (%d)", argc); - return -ENOENT; - } - - BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); - - src = strtol(argv[0], NULL, 16); - entry = bt_mesh_rpl_find(src); - - if (!val) { - if (entry) { - memset(entry, 0, sizeof(*entry)); - } else { - BT_WARN("Unable to find RPL entry for 0x%04x", src); - } - - return 0; - } - - if (!entry) { - entry = bt_mesh_rpl_alloc(src); - if (!entry) { - BT_ERR("Unable to allocate RPL entry for 0x%04x", src); - return -ENOMEM; - } - } - - len = sizeof(rpl); - err = settings_bytes_from_str(val, &rpl, &len); - if (err) { - BT_ERR("Failed to decode value %s (err %d)", val, err); - return err; - } - - if (len != sizeof(rpl)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(rpl)); - return -EINVAL; - } - - entry->seq = rpl.seq; - entry->old_iv = rpl.old_iv; - - BT_DBG("RPL entry for 0x%04x: Seq 0x%06x old_iv %u", entry->src, - (unsigned) entry->seq, entry->old_iv); - return 0; -} -#endif - -static void store_rpl(struct bt_mesh_rpl *entry) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - char buf[BT_SETTINGS_SIZE(sizeof(struct rpl_val))]; - struct rpl_val rpl; - char path[18]; - char *str; - int err; - - if (!entry->src) { - return; - } - - BT_DBG("src 0x%04x seq 0x%06x old_iv %u", entry->src, - (unsigned) entry->seq, entry->old_iv); - - rpl.seq = entry->seq; - rpl.old_iv = entry->old_iv; - - str = settings_str_from_bytes(&rpl, sizeof(rpl), buf, sizeof(buf)); - if (!str) { - BT_ERR("Unable to encode RPL as value"); - return; - } - - snprintk(path, sizeof(path), "bt_mesh/RPL/%x", entry->src); - - BT_DBG("Saving RPL %s as value %s", path, str); - err = settings_save_one(path, str); - if (err) { - BT_ERR("Failed to store RPL"); - } else { - BT_DBG("Stored RPL"); - } -#endif -} - -static void store_pending_rpl(struct bt_mesh_rpl *rpl) -{ - BT_DBG(""); - - if (atomic_test_and_clear_bit(store, rpl_idx(rpl))) { - store_rpl(rpl); - } -} - -void bt_mesh_rpl_pending_store(uint16_t addr) -{ - int i; - - if (!IS_ENABLED(CONFIG_BT_SETTINGS) || - (!BT_MESH_ADDR_IS_UNICAST(addr) && - addr != BT_MESH_ADDR_ALL_NODES)) { - return; - } - - if (addr == BT_MESH_ADDR_ALL_NODES) { - bt_mesh_settings_store_cancel(BT_MESH_SETTINGS_RPL_PENDING); - } - - for (i = 0; i < ARRAY_SIZE(replay_list); i++) { - if (addr != BT_MESH_ADDR_ALL_NODES && - addr != replay_list[i].src) { - continue; - } - - if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - store_pending_rpl(&replay_list[i]); - } else { - clear_rpl(&replay_list[i]); - } - - if (addr != BT_MESH_ADDR_ALL_NODES) { - break; - } - } -} - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) -static struct conf_handler bt_mesh_rpl_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = rpl_set, - .ch_commit = NULL, - .ch_export = NULL, -}; -#endif - -void bt_mesh_rpl_init(void) -{ -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - int rc; - - rc = conf_register(&bt_mesh_rpl_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_rpl conf"); -#endif -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/rpl.h b/src/nimble/nimble/host/mesh/src/rpl.h deleted file mode 100644 index 9d110d9da..000000000 --- a/src/nimble/nimble/host/mesh/src/rpl.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Bluetooth Mesh */ - -/* - * Copyright (c) 2017 Intel Corporation - * Copyright (c) 2020 Lingao Meng - * - * SPDX-License-Identifier: Apache-2.0 - */ - -struct bt_mesh_rpl { - uint64_t src:15, - old_iv:1, - seq:24, - /** Sequence authentication value for the previous segmented - * message received from this address. - * - * This value is used to manage the parallel RPL of the - * SeqAuth values in transport. - */ - seg:24; -}; - -typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl, - 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); -void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, - struct bt_mesh_net_rx *rx); -void bt_mesh_rpl_init(void); diff --git a/src/nimble/nimble/host/mesh/src/settings.c b/src/nimble/nimble/host/mesh/src/settings.c deleted file mode 100644 index e0136be12..000000000 --- a/src/nimble/nimble/host/mesh/src/settings.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" -#define MESH_LOG_MODULE BLE_MESH_SETTINGS_LOG - -#if MYNEWT_VAL(BLE_MESH_SETTINGS) - -#include "mesh_priv.h" -#include "nimble/nimble/host/mesh/include/mesh/glue.h" -#include "subnet.h" -#include "app_keys.h" -#include "net.h" -#include "cdb_priv.h" -#include "rpl.h" -#include "crypto.h" -#include "transport.h" -#include "heartbeat.h" -#include "access.h" -#include "pb_gatt_srv.h" -#include "proxy.h" -#include "settings.h" -#include "cfg.h" - - -#include "config/config.h" - -static struct k_work_delayable pending_store; -static ATOMIC_DEFINE(pending_flags, BT_MESH_SETTINGS_FLAG_COUNT); - -int settings_name_next(char *name, char **next) -{ - 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 mesh_commit(void) -{ - if (!bt_mesh_subnet_next(NULL)) { - /* Nothing to do since we're not yet provisioned */ - return 0; - } - - if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { - (void)bt_mesh_pb_gatt_disable(); - } - - bt_mesh_net_settings_commit(); - bt_mesh_model_settings_commit(); - - atomic_set_bit(bt_mesh.flags, BT_MESH_VALID); - - bt_mesh_start(); - return 0; -} - -/* Pending flags that use K_NO_WAIT as the storage timeout */ -#define NO_WAIT_PENDING_BITS (BIT(BT_MESH_SETTINGS_NET_PENDING) | \ - BIT(BT_MESH_SETTINGS_IV_PENDING) | \ - BIT(BT_MESH_SETTINGS_SEQ_PENDING) | \ - BIT(BT_MESH_SETTINGS_CDB_PENDING)) - -/* Pending flags that use CONFIG_BT_MESH_STORE_TIMEOUT */ -#define GENERIC_PENDING_BITS (BIT(BT_MESH_SETTINGS_NET_KEYS_PENDING) | \ - BIT(BT_MESH_SETTINGS_APP_KEYS_PENDING) | \ - BIT(BT_MESH_SETTINGS_HB_PUB_PENDING) | \ - BIT(BT_MESH_SETTINGS_CFG_PENDING) | \ - BIT(BT_MESH_SETTINGS_MOD_PENDING) | \ - BIT(BT_MESH_SETTINGS_VA_PENDING)) - -void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag) -{ - int32_t timeout_ms, remaining_ms; - - atomic_set_bit(pending_flags, flag); - - if (atomic_get(pending_flags) & NO_WAIT_PENDING_BITS) { - timeout_ms = 0; - } else if (CONFIG_BT_MESH_RPL_STORE_TIMEOUT >= 0 && - atomic_test_bit(pending_flags, BT_MESH_SETTINGS_RPL_PENDING) && - !(atomic_get(pending_flags) & GENERIC_PENDING_BITS)) { - timeout_ms = CONFIG_BT_MESH_RPL_STORE_TIMEOUT * MSEC_PER_SEC; - } else { - timeout_ms = CONFIG_BT_MESH_STORE_TIMEOUT * MSEC_PER_SEC; - } - - remaining_ms = k_ticks_to_ms_floor32( - k_work_delayable_remaining_get(&pending_store)); - BT_DBG("Waiting %u ms vs rem %u ms", timeout_ms, remaining_ms); - /* If the new deadline is sooner, override any existing - * deadline; otherwise schedule without changing any existing - * deadline. - */ - if (timeout_ms < remaining_ms) { - k_work_reschedule(&pending_store, K_MSEC(timeout_ms)); - } else { - k_work_schedule(&pending_store, K_MSEC(timeout_ms)); - } -} - -void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag) -{ - atomic_clear_bit(pending_flags, flag); -} - -static void store_pending(struct ble_npl_event *work) -{ - BT_DBG(""); - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_RPL_PENDING)) { - bt_mesh_rpl_pending_store(BT_MESH_ADDR_ALL_NODES); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_NET_KEYS_PENDING)) { - bt_mesh_subnet_pending_store(); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_APP_KEYS_PENDING)) { - bt_mesh_app_key_pending_store(); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_NET_PENDING)) { - bt_mesh_net_pending_net_store(); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_IV_PENDING)) { - bt_mesh_net_pending_iv_store(); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_SEQ_PENDING)) { - bt_mesh_net_pending_seq_store(); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_HB_PUB_PENDING)) { - bt_mesh_hb_pub_pending_store(); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_CFG_PENDING)) { - bt_mesh_cfg_pending_store(); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_MOD_PENDING)) { - bt_mesh_model_pending_store(); - } - - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_VA_PENDING)) { - bt_mesh_va_pending_store(); - } - -#if IS_ENABLED(CONFIG_BT_MESH_CDB) - if (atomic_test_and_clear_bit(pending_flags, - BT_MESH_SETTINGS_CDB_PENDING)) { - bt_mesh_cdb_pending_store(); - } -#endif -} - -static struct conf_handler bt_mesh_settings_conf_handler = { - .ch_name = "bt_mesh", - .ch_get = NULL, - .ch_set = NULL, - .ch_commit = mesh_commit, - .ch_export = NULL, -}; - -void bt_mesh_settings_init(void) -{ - int rc; - - rc = conf_register(&bt_mesh_settings_conf_handler); - - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register bt_mesh_settings conf"); - - k_work_init_delayable(&pending_store, store_pending); -} - -#endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ diff --git a/src/nimble/nimble/host/mesh/src/settings.h b/src/nimble/nimble/host/mesh/src/settings.h deleted file mode 100644 index 73105fb34..000000000 --- a/src/nimble/nimble/host/mesh/src/settings.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -/* Pending storage actions. */ -enum bt_mesh_settings_flag { - BT_MESH_SETTINGS_RPL_PENDING, - BT_MESH_SETTINGS_NET_KEYS_PENDING, - BT_MESH_SETTINGS_APP_KEYS_PENDING, - BT_MESH_SETTINGS_NET_PENDING, - BT_MESH_SETTINGS_IV_PENDING, - BT_MESH_SETTINGS_SEQ_PENDING, - BT_MESH_SETTINGS_HB_PUB_PENDING, - BT_MESH_SETTINGS_CFG_PENDING, - BT_MESH_SETTINGS_MOD_PENDING, - BT_MESH_SETTINGS_VA_PENDING, - BT_MESH_SETTINGS_CDB_PENDING, - - BT_MESH_SETTINGS_FLAG_COUNT, -}; - -void bt_mesh_settings_init(void); -int settings_name_next(char *name, char **next); -void bt_mesh_settings_store_schedule(enum bt_mesh_settings_flag flag); -void bt_mesh_settings_store_cancel(enum bt_mesh_settings_flag flag); diff --git a/src/nimble/nimble/host/mesh/src/shell.c b/src/nimble/nimble/host/mesh/src/shell.c deleted file mode 100644 index 0e35d0ac6..000000000 --- a/src/nimble/nimble/host/mesh/src/shell.c +++ /dev/null @@ -1,3690 +0,0 @@ -/** @file - * @brief Bluetooth Mesh shell - * - */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" - -#if MYNEWT_VAL(BLE_MESH_SHELL) - -#include -#include -#include -#include "nimble/nimble/host/mesh/src/shell.h" -#include "nimble/console/console.h" -#include "nimble/nimble/host/mesh/include/mesh/mesh.h" -#include "nimble/nimble/host/mesh/include/mesh/main.h" -#include "nimble/nimble/host/mesh/include/mesh/glue.h" -#include "nimble/nimble/host/mesh/include/mesh/testing.h" - -/* 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) -#include "nimble/nimble/host/mesh/include/mesh/model_srv.h" -#include "nimble/nimble/host/mesh/include/mesh/model_cli.h" -#include "light_model.h" -#endif - -/* This should be higher priority (lower value) than main task priority */ -#define BLE_MESH_SHELL_TASK_PRIO 126 -#define BLE_MESH_SHELL_STACK_SIZE 768 - -OS_TASK_STACK_DEFINE(g_blemesh_shell_stack, BLE_MESH_SHELL_STACK_SIZE); - -struct os_task mesh_shell_task; -static struct os_eventq mesh_shell_queue; - -#define CID_NVAL 0xffff -#define CID_VENDOR 0x05C3 - -/* Vendor Model data */ -#define VND_MODEL_ID_1 0x1234 - -/* Default net, app & dev key values, unless otherwise specified */ -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 { - 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, -}; - -#define CUR_FAULTS_MAX 4 - -static uint8_t cur_faults[CUR_FAULTS_MAX]; -static uint8_t reg_faults[CUR_FAULTS_MAX * 2]; - -static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count) -{ - uint8_t i, limit = *count; - - for (i = 0, *count = 0; i < faults_size && *count < limit; i++) { - if (faults[i]) { - *dst++ = faults[i]; - (*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"); - - *test_id = 0x00; - *company_id = CID_VENDOR; - - get_faults(cur_faults, sizeof(cur_faults), faults, fault_count); - - return 0; -} - -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); - return -EINVAL; - } - - printk("Sending registered faults\n"); - - *test_id = 0x00; - - get_faults(reg_faults, sizeof(reg_faults), faults, fault_count); - - return 0; -} - -static int fault_clear(struct bt_mesh_model *model, uint16_t cid) -{ - if (cid != CID_VENDOR) { - return -EINVAL; - } - - memset(reg_faults, 0, sizeof(reg_faults)); - - return 0; -} - -static int fault_test(struct bt_mesh_model *model, uint8_t test_id, - uint16_t cid) -{ - if (cid != CID_VENDOR) { - return -EINVAL; - } - - if (test_id != 0x00) { - return -EINVAL; - } - - return 0; -} - -static const struct bt_mesh_health_srv_cb health_srv_cb = { - .fault_get_cur = fault_get_cur, - .fault_get_reg = fault_get_reg, - .fault_clear = fault_clear, - .fault_test = fault_test, -}; - -static struct bt_mesh_health_srv health_srv = { - .cb = &health_srv_cb, -}; - -static struct bt_mesh_model_pub health_pub; - -static void -health_pub_init(void) -{ - health_pub.msg = BT_MESH_HEALTH_FAULT_MSG(CUR_FAULTS_MAX); -} -#if MYNEWT_VAL(BLE_MESH_CFG_CLI) - -static struct bt_mesh_cfg_cli cfg_cli = { -}; - -#endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */ - -#if MYNEWT_VAL(BLE_MESH_HEALTH_CLI) -static void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count) -{ - size_t i; - - if (!fault_count) { - printk("Health Test ID 0x%02x Company ID 0x%04x: no faults\n", - test_id, cid); - return; - } - - printk("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu:\n", - test_id, cid, fault_count); - - for (i = 0; i < fault_count; i++) { - printk("\t0x%02x\n", faults[i]); - } -} - -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); - show_faults(test_id, cid, faults, fault_count); -} - -static struct bt_mesh_health_cli health_cli = { - .current_status = health_current_status, -}; - -#endif /* MYNEWT_VAL(BLE_MESH_HEALTH_CLI) */ - -#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS) -static struct bt_mesh_gen_model_cli gen_onoff_cli; -static struct bt_mesh_model_pub gen_onoff_cli_pub; -static struct bt_mesh_model_pub gen_onoff_srv_pub; -static struct bt_mesh_gen_model_cli gen_level_cli; -static struct bt_mesh_model_pub gen_level_cli_pub; -static struct bt_mesh_model_pub gen_level_srv_pub; -static struct bt_mesh_model_pub light_lightness_pub; -static struct bt_mesh_gen_onoff_srv gen_onoff_srv = { - .get = light_model_gen_onoff_get, - .set = light_model_gen_onoff_set, -}; -static struct bt_mesh_gen_level_srv gen_level_srv = { - .get = light_model_gen_level_get, - .set = light_model_gen_level_set, -}; -static struct bt_mesh_light_lightness_srv light_lightness_srv = { - .get = light_model_light_lightness_get, - .set = light_model_light_lightness_set, -}; - -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, 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, int16_t *level), - int (*set)(struct bt_mesh_model *model, int16_t level)) -{ - light_lightness_srv.get = get; - light_lightness_srv.set = set; -} -#endif - -static struct bt_mesh_model root_models[] = { - 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), -#endif -#if MYNEWT_VAL(BLE_MESH_HEALTH_CLI) - BT_MESH_MODEL_HEALTH_CLI(&health_cli), -#endif -#if MYNEWT_VAL(BLE_MESH_SHELL_MODELS) - BT_MESH_MODEL_GEN_ONOFF_SRV(&gen_onoff_srv, &gen_onoff_srv_pub), - BT_MESH_MODEL_GEN_ONOFF_CLI(&gen_onoff_cli, &gen_onoff_cli_pub), - BT_MESH_MODEL_GEN_LEVEL_SRV(&gen_level_srv, &gen_level_srv_pub), - BT_MESH_MODEL_GEN_LEVEL_CLI(&gen_level_cli, &gen_level_cli_pub), - BT_MESH_MODEL_LIGHT_LIGHTNESS_SRV(&light_lightness_srv, &light_lightness_pub), -#endif -}; - -static struct bt_mesh_model vnd_models[] = { - BT_MESH_MODEL_VND(CID_VENDOR, VND_MODEL_ID_1, - BT_MESH_MODEL_NO_OPS, NULL, NULL), -}; - -static struct bt_mesh_elem elements[] = { - BT_MESH_ELEM(0, root_models, vnd_models), -}; - -static const struct bt_mesh_comp comp = { - .cid = CID_VENDOR, - .elem = elements, - .elem_count = ARRAY_SIZE(elements), -}; - -static uint8_t hex2val(char c) -{ - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - return c - 'A' + 10; - } else { - return 0; - } -} - -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; - - while (*hex && len < bin_len) { - bin[len] = hex2val(*hex++) << 4; - - if (!*hex) { - len++; - break; - } - - bin[len++] |= hex2val(*hex++); - } - - return len; -} - -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); - net.local = addr; - net.net_idx = net_idx, - net.dst = addr; -} - -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); - - net.net_idx = net_idx, - net.dst = addr; -} - -static void prov_input_complete(void) -{ - printk("Input complete"); -} - -static void prov_reset(void) -{ - printk("The local node has been reset and needs reprovisioning\n"); -} - -static int output_number(bt_mesh_output_action_t action, uint32_t number) -{ - printk("OOB Number: %lu\n", number); - return 0; -} - -static int output_string(const char *str) -{ - printk("OOB String: %s\n", str); - return 0; -} - -static bt_mesh_input_action_t input_act; -static uint8_t input_size; - -static int cmd_input_num(int argc, char *argv[]) -{ - int err; - - if (argc < 2) { - return -EINVAL; - } - - if (input_act != BT_MESH_ENTER_NUMBER) { - printk("A number hasn't been requested!\n"); - return 0; - } - - if (strlen(argv[1]) < input_size) { - printk("Too short input (%u digits required)\n", - input_size); - return 0; - } - - err = bt_mesh_input_number(strtoul(argv[1], NULL, 10)); - if (err) { - printk("Numeric input failed (err %d)\n", err); - return 0; - } - - input_act = BT_MESH_NO_INPUT; - return 0; -} - -struct shell_cmd_help cmd_input_num_help = { - NULL, "", NULL -}; - -static int cmd_input_str(int argc, char *argv[]) -{ - int err; - - if (argc < 2) { - return -EINVAL; - } - - if (input_act != BT_MESH_ENTER_STRING) { - printk("A string hasn't been requested!\n"); - return 0; - } - - if (strlen(argv[1]) < input_size) { - printk("Too short input (%u characters required)\n", - input_size); - return 0; - } - - err = bt_mesh_input_string(argv[1]); - if (err) { - printk("String input failed (err %d)\n", err); - return 0; - } - - input_act = BT_MESH_NO_INPUT; - return 0; -} - -struct shell_cmd_help cmd_input_str_help = { - NULL, "", NULL -}; - -static int input(bt_mesh_input_action_t act, uint8_t size) -{ - switch (act) { - case BT_MESH_ENTER_NUMBER: - printk("Enter a number (max %u digits) with: input-num \n", - size); - break; - case BT_MESH_ENTER_STRING: - printk("Enter a string (max %u chars) with: input-str \n", - size); - break; - default: - printk("Unknown input action %u (size %u) requested!\n", - act, size); - return -EINVAL; - } - - input_act = act; - input_size = size; - return 0; -} - -static const char *bearer2str(bt_mesh_prov_bearer_t bearer) -{ - switch (bearer) { - case BT_MESH_PROV_ADV: - return "PB-ADV"; - case BT_MESH_PROV_GATT: - return "PB-GATT"; - default: - return "unknown"; - } -} - -static void link_open(bt_mesh_prov_bearer_t bearer) -{ - printk("Provisioning link opened on %s\n", bearer2str(bearer)); -} - -static void link_close(bt_mesh_prov_bearer_t bearer) -{ - printk("Provisioning link closed on %s\n", bearer2str(bearer)); -} - -static uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID); - -static uint8_t static_val[16]; - -static struct bt_mesh_prov prov = { - .uuid = dev_uuid, - .link_open = link_open, - .link_close = link_close, - .complete = prov_complete, - .node_added = prov_node_added, - .reset = prov_reset, - .static_val = NULL, - .static_val_len = 0, - .output_size = MYNEWT_VAL(BLE_MESH_OOB_OUTPUT_SIZE), - .output_actions = MYNEWT_VAL(BLE_MESH_OOB_OUTPUT_ACTIONS), - .output_number = output_number, - .output_string = output_string, - .input_size = MYNEWT_VAL(BLE_MESH_OOB_INPUT_SIZE), - .input_actions = MYNEWT_VAL(BLE_MESH_OOB_INPUT_ACTIONS), - .input = input, - .input_complete = prov_input_complete, -}; - -static int cmd_static_oob(int argc, char *argv[]) -{ - if (argc < 2) { - prov.static_val = NULL; - prov.static_val_len = 0; - } else { - prov.static_val_len = hex2bin(argv[1], static_val, 16); - if (prov.static_val_len) { - prov.static_val = static_val; - } else { - prov.static_val = NULL; - } - } - - if (prov.static_val) { - printk("Static OOB value set (length %u)\n", - prov.static_val_len); - } else { - printk("Static OOB value cleared\n"); - } - - return 0; -} - -struct shell_cmd_help cmd_static_oob_help = { - NULL, "[val: 1-16 hex values]", NULL -}; - -static int cmd_uuid(int argc, char *argv[]) -{ - uint8_t uuid[16]; - size_t len; - - if (argc < 2) { - return -EINVAL; - } - - len = hex2bin(argv[1], uuid, sizeof(uuid)); - if (len < 1) { - return -EINVAL; - } - - memcpy(dev_uuid, uuid, len); - memset(dev_uuid + len, 0, sizeof(dev_uuid) - len); - - printk("Device UUID set\n"); - - return 0; -} - -struct shell_cmd_help cmd_uuid_help = { - NULL, "", NULL -}; - -static int cmd_reset(int argc, char *argv[]) -{ - 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; -} - -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); - } - - return (!strcmp(str, "on") || !strcmp(str, "enable")); -} - -static bool str2bool(const char *str) -{ - return str2u8(str); -} - -#if MYNEWT_VAL(BLE_MESH_LOW_POWER) -static int cmd_lpn(int argc, char *argv[]) -{ - static bool enabled; - int err; - - if (argc < 2) { - printk("%s\n", enabled ? "enabled" : "disabled"); - return 0; - } - - if (str2bool(argv[1])) { - if (enabled) { - printk("LPN already enabled\n"); - return 0; - } - - err = bt_mesh_lpn_set(true); - if (err) { - printk("Enabling LPN failed (err %d)\n", err); - } else { - enabled = true; - } - } else { - if (!enabled) { - printk("LPN already disabled\n"); - return 0; - } - - err = bt_mesh_lpn_set(false); - if (err) { - printk("Enabling LPN failed (err %d)\n", err); - } else { - enabled = false; - } - } - - return 0; -} - -static int cmd_poll(int argc, char *argv[]) -{ - int err; - - err = bt_mesh_lpn_poll(); - if (err) { - printk("Friend Poll failed (err %d)\n", err); - } - - return 0; -} - -static void lpn_cb(uint16_t friend_addr, bool established) -{ - if (established) { - printk("Friendship (as LPN) established to Friend 0x%04x\n", - friend_addr); - } else { - printk("Friendship (as LPN) lost with Friend 0x%04x\n", - friend_addr); - } -} - -struct shell_cmd_help cmd_lpn_help = { - NULL, "", NULL -}; - -#endif /* MESH_LOW_POWER */ - -static int check_pub_addr_unassigned(void) -{ -#ifdef ARCH_sim - return 0; -#else - uint8_t addr[BLE_DEV_ADDR_LEN]; - - return ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr, NULL) != 0; -#endif -} - -int cmd_mesh_init(int argc, char *argv[]) -{ - int err; - ble_addr_t addr; - - if (check_pub_addr_unassigned()) { - /* Use NRPA */ - err = ble_hs_id_gen_rnd(1, &addr); - assert(err == 0); - err = ble_hs_id_set_rnd(addr.val); - assert(err == 0); - - err = bt_mesh_init(addr.type, &prov, &comp); - } - else { - err = bt_mesh_init(0, &prov, &comp); - } - - if (err) { - printk("Mesh initialization failed (err %d)\n", err); - } - - printk("Mesh initialized\n"); - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - settings_load(); - } - - if (bt_mesh_is_provisioned()) { - printk("Mesh network restored from flash\n"); - } else { - printk("Use \"pb-adv on\" or \"pb-gatt on\" to enable" - " advertising\n"); - } - -#if MYNEWT_VAL(BLE_MESH_LOW_POWER) - bt_mesh_lpn_set_cb(lpn_cb); -#endif - - return 0; -} - -#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) -static int cmd_ident(int argc, char *argv[]) -{ - int err; - - err = bt_mesh_proxy_identity_enable(); - if (err) { - printk("Failed advertise using Node Identity (err %d)\n", err); - } - - return 0; -} -#endif /* MESH_GATT_PROXY */ - -static int cmd_dst(int argc, char *argv[]) -{ - if (argc < 2) { - printk("Destination address: 0x%04x%s\n", net.dst, - net.dst == net.local ? " (local)" : ""); - return 0; - } - - if (!strcmp(argv[1], "local")) { - net.dst = net.local; - } else { - net.dst = strtoul(argv[1], NULL, 0); - } - - printk("Destination address set to 0x%04x%s\n", net.dst, - net.dst == net.local ? " (local)" : ""); - return 0; -} - -struct shell_cmd_help cmd_dst_help = { - NULL, "[destination address]", NULL -}; - -static int cmd_netidx(int argc, char *argv[]) -{ - if (argc < 2) { - printk("NetIdx: 0x%04x\n", net.net_idx); - return 0; - } - - net.net_idx = strtoul(argv[1], NULL, 0); - printk("NetIdx set to 0x%04x\n", net.net_idx); - return 0; -} - -struct shell_cmd_help cmd_netidx_help = { - NULL, "[NetIdx]", NULL -}; - -static int cmd_appidx(int argc, char *argv[]) -{ - if (argc < 2) { - printk("AppIdx: 0x%04x\n", net.app_idx); - return 0; - } - - net.app_idx = strtoul(argv[1], NULL, 0); - printk("AppIdx set to 0x%04x\n", net.app_idx); - return 0; -} - -struct shell_cmd_help cmd_appidx_help = { - NULL, "[AppIdx]", NULL -}; - -static int cmd_net_send(int argc, char *argv[]) -{ - struct os_mbuf *msg = NET_BUF_SIMPLE(32); - struct bt_mesh_msg_ctx ctx = { - .send_ttl = BT_MESH_TTL_DEFAULT, - .net_idx = net.net_idx, - .addr = net.dst, - .app_idx = net.app_idx, - - }; - struct bt_mesh_net_tx tx = { - .ctx = &ctx, - .src = net.local, - }; - size_t len; - int err = 0; - - if (argc < 2) { - err = -EINVAL; - 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); - - err = bt_mesh_trans_send(&tx, msg, NULL, NULL); - if (err) { - printk("Failed to send (err %d)\n", err); - } - -done: - os_mbuf_free_chain(msg); - return err; -} - -struct shell_cmd_help cmd_net_send_help = { - NULL, "", NULL -}; - -static int cmd_rpl_clear(int argc, char *argv[]) -{ - bt_mesh_rpl_clear(); - return 0; -} - -#if MYNEWT_VAL(BLE_MESH_LOW_POWER) -static int cmd_lpn_subscribe(int argc, char *argv[]) -{ - uint16_t address; - - if (argc < 2) { - return -EINVAL; - } - - address = strtoul(argv[1], NULL, 0); - - printk("address 0x%04x", address); - - bt_mesh_lpn_group_add(address); - - return 0; -} - -struct shell_cmd_help cmd_lpn_subscribe_help = { - NULL, "", NULL -}; - -static int cmd_lpn_unsubscribe(int argc, char *argv[]) -{ - uint16_t address; - - if (argc < 2) { - return -EINVAL; - } - - address = strtoul(argv[1], NULL, 0); - - printk("address 0x%04x", address); - - bt_mesh_lpn_group_del(&address, 1); - - return 0; -} - -struct shell_cmd_help cmd_lpn_unsubscribe_help = { - NULL, "", NULL -}; -#endif - -#if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST) -static int cmd_iv_update(int argc, char *argv[]) -{ - if (bt_mesh_iv_update()) { - printk("Transitioned to IV Update In Progress state\n"); - } else { - printk("Transitioned to IV Update Normal state\n"); - } - - printk("IV Index is 0x%08lx\n", bt_mesh.iv_index); - - return 0; -} - -static int cmd_iv_update_test(int argc, char *argv[]) -{ - bool enable; - - if (argc < 2) { - return -EINVAL; - } - - enable = str2bool(argv[1]); - if (enable) { - printk("Enabling IV Update test mode\n"); - } else { - printk("Disabling IV Update test mode\n"); - } - - bt_mesh_iv_update_test(enable); - - return 0; -} - -struct shell_cmd_help cmd_iv_update_test_help = { - NULL, "", NULL -}; -#endif - -#if MYNEWT_VAL(BLE_MESH_CFG_CLI) - -int cmd_timeout(int argc, char *argv[]) -{ - int32_t timeout; - - if (argc < 2) { - timeout = bt_mesh_cfg_cli_timeout_get(); - if (timeout == K_FOREVER) { - printk("Message timeout: forever\n"); - } else { - printk("Message timeout: %lu seconds\n", - timeout / 1000); - } - - return 0; - } - - timeout = strtol(argv[1], NULL, 0); - if (timeout < 0 || timeout > (INT32_MAX / 1000)) { - timeout = K_FOREVER; - } else { - timeout = timeout * 1000; - } - - bt_mesh_cfg_cli_timeout_set(timeout); - if (timeout == K_FOREVER) { - printk("Message timeout: forever\n"); - } else { - printk("Message timeout: %lu seconds\n", - timeout / 1000); - } - - return 0; -} - -struct shell_cmd_help cmd_timeout_help = { - NULL, "[timeout in seconds]", NULL -}; - - -static int cmd_get_comp(int argc, char *argv[]) -{ - struct os_mbuf *buf = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX); - struct bt_mesh_comp_p0_elem elem; - struct bt_mesh_comp_p0 comp; - uint8_t page = 0x00; - int err = 0; - - if (argc > 1) { - page = strtol(argv[1], NULL, 0); - } - - net_buf_simple_init(buf, 0); - err = bt_mesh_cfg_comp_data_get(net.net_idx, net.dst, page, &page, - buf); - if (err) { - printk("Getting composition failed (err %d)\n", err); - goto done; - } - - if (page != 0x00) { - printk("Got page 0x%02x. No parser available.", - page); - goto done; - } - - err = bt_mesh_comp_p0_get(&comp, buf); - if (err) { - printk("Getting composition failed (err %d)\n", err); - goto done; - } - - printk("Got Composition Data for 0x%04x:", net.dst); - printk("\tCID 0x%04x", comp.cid); - printk("\tPID 0x%04x", comp.pid); - printk("\tVID 0x%04x", comp.vid); - printk("\tCRPL 0x%04x", comp.crpl); - printk("\tFeatures 0x%04x", comp.feat); - - while (bt_mesh_comp_p0_elem_pull(&comp, &elem)) { - int i; - - printk("\tElement @ 0x%04x:", elem.loc); - if (elem.nsig) { - printk("\t\tSIG Models:\n"); - } else { - printk("\t\tNo SIG Models\n"); - } - - for (i = 0; i < elem.nsig; i++) { - uint16_t mod_id = bt_mesh_comp_p0_elem_mod(&elem, i); - - printk("\t\t\t0x%04x\n", mod_id); - } - - if (elem.nvnd) { - printk("\t\tVendor Models:\n"); - } else { - printk("\t\tNo Vendor Models\n"); - } - - for (i = 0; i < elem.nvnd; i++) { - struct bt_mesh_mod_id_vnd mod = - bt_mesh_comp_p0_elem_mod_vnd(&elem, i); - - printk("\t\t\tCompany 0x%04x: 0x%04x", - mod.company, mod.id); - } - } - if (buf->om_len) { - printk("\t\t...truncated data!"); - } - -done: - os_mbuf_free_chain(buf); - return err; -} - -struct shell_cmd_help cmd_get_comp_help = { - NULL, "[page]", NULL -}; - -static int cmd_beacon(int argc, char *argv[]) -{ - uint8_t status; - int err; - - if (argc < 2) { - err = bt_mesh_cfg_beacon_get(net.net_idx, net.dst, &status); - } else { - uint8_t val = str2u8(argv[1]); - - err = bt_mesh_cfg_beacon_set(net.net_idx, net.dst, val, - &status); - } - - if (err) { - printk("Unable to send Beacon Get/Set message (err %d)\n", err); - return 0; - } - - printk("Beacon state is 0x%02x\n", status); - - 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[]) -{ - uint8_t ttl; - int err; - - if (argc < 2) { - err = bt_mesh_cfg_ttl_get(net.net_idx, net.dst, &ttl); - } else { - uint8_t val = strtoul(argv[1], NULL, 0); - - err = bt_mesh_cfg_ttl_set(net.net_idx, net.dst, val, &ttl); - } - - if (err) { - printk("Unable to send Default TTL Get/Set (err %d)\n", err); - return 0; - } - - printk("Default TTL is 0x%02x\n", ttl); - - return 0; -} - -struct shell_cmd_help cmd_ttl_help = { - NULL, "[ttl: 0x00, 0x02-0x7f]", NULL -}; - -static int cmd_friend(int argc, char *argv[]) -{ - uint8_t frnd; - int err; - - if (argc < 2) { - err = bt_mesh_cfg_friend_get(net.net_idx, net.dst, &frnd); - } else { - uint8_t val = str2u8(argv[1]); - - err = bt_mesh_cfg_friend_set(net.net_idx, net.dst, val, &frnd); - } - - if (err) { - printk("Unable to send Friend Get/Set (err %d)\n", err); - return 0; - } - - printk("Friend is set to 0x%02x\n", frnd); - - return 0; -} - -struct shell_cmd_help cmd_friend_help = { - NULL, "[val: off, on]", NULL -}; - -static int cmd_gatt_proxy(int argc, char *argv[]) -{ - uint8_t proxy; - int err; - - if (argc < 2) { - err = bt_mesh_cfg_gatt_proxy_get(net.net_idx, net.dst, &proxy); - } else { - uint8_t val = str2u8(argv[1]); - - err = bt_mesh_cfg_gatt_proxy_set(net.net_idx, net.dst, val, - &proxy); - } - - if (err) { - printk("Unable to send GATT Proxy Get/Set (err %d)\n", err); - return 0; - } - - printk("GATT Proxy is set to 0x%02x\n", proxy); - - return 0; -} - -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[]) -{ - uint8_t relay, transmit; - int err; - - if (argc < 2) { - err = bt_mesh_cfg_relay_get(net.net_idx, net.dst, &relay, - &transmit); - } else { - uint8_t val = str2u8(argv[1]); - uint8_t count, interval, new_transmit; - - if (val) { - if (argc > 2) { - count = strtoul(argv[2], NULL, 0); - } else { - count = 2; - } - - if (argc > 3) { - interval = strtoul(argv[3], NULL, 0); - } else { - interval = 20; - } - - new_transmit = BT_MESH_TRANSMIT(count, interval); - } else { - new_transmit = 0; - } - - err = bt_mesh_cfg_relay_set(net.net_idx, net.dst, val, - new_transmit, &relay, &transmit); - } - - if (err) { - printk("Unable to send Relay Get/Set (err %d)\n", err); - return 0; - } - - printk("Relay is 0x%02x, Transmit 0x%02x (count %u interval %ums)\n", - relay, transmit, BT_MESH_TRANSMIT_COUNT(transmit), - BT_MESH_TRANSMIT_INT(transmit)); - - return 0; -} - -struct shell_cmd_help cmd_relay_help = { - NULL, "[val: off, on] [count: 0-7] [interval: 0-32]", NULL -}; - -static int cmd_net_key_add(int argc, char *argv[]) -{ - bool has_key_val = (argc > 2); - uint8_t key_val[16]; - uint16_t key_net_idx; - uint8_t status; - int err; - - if (argc < 2) { - return -EINVAL; - } - - key_net_idx = strtoul(argv[1], NULL, 0); - - if (has_key_val) { - size_t len; - - len = hex2bin(argv[3], key_val, sizeof(key_val)); - memset(key_val, 0, sizeof(key_val) - len); - } else { - 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) { - printk("Unable to send NetKey Add (err %d)\n", err); - return 0; - } - - if (status) { - printk("NetKeyAdd failed with status 0x%02x\n", status); - } else { - printk("NetKey added with NetKey Index 0x%03x\n", key_net_idx); - } - - return 0; -} - -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[]) -{ - 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) { - return -EINVAL; - } - - key_net_idx = strtoul(argv[1], NULL, 0); - key_app_idx = strtoul(argv[2], NULL, 0); - - if (has_key_val) { - size_t len; - - len = hex2bin(argv[3], key_val, sizeof(key_val)); - memset(key_val, 0, sizeof(key_val) - len); - } else { - 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) { - printk("Unable to send App Key Add (err %d)\n", err); - return 0; - } - - if (status) { - printk("AppKeyAdd failed with status 0x%02x\n", status); - } else { - printk("AppKey added, NetKeyIndex 0x%04x AppKeyIndex 0x%04x\n", - key_net_idx, key_app_idx); - } - - return 0; -} - -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[]) -{ - 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_bind_vnd(net.net_idx, net.dst, - elem_addr, mod_app_idx, - mod_id, cid, &status); - } else { - err = bt_mesh_cfg_mod_app_bind(net.net_idx, net.dst, elem_addr, - mod_app_idx, mod_id, &status); - } - - if (err) { - printk("Unable to send Model App Bind (err %d)\n", err); - return 0; - } - - if (status) { - printk("Model App Bind failed with status 0x%02x\n", status); - } else { - printk("AppKey successfully bound\n"); - } - - return 0; -} - -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[]) -{ - uint16_t elem_addr, sub_addr, mod_id, cid; - uint8_t status; - int err; - - if (argc < 4) { - return -EINVAL; - } - - elem_addr = strtoul(argv[1], NULL, 0); - sub_addr = 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_sub_add_vnd(net.net_idx, net.dst, - elem_addr, sub_addr, mod_id, - cid, &status); - } else { - err = bt_mesh_cfg_mod_sub_add(net.net_idx, net.dst, elem_addr, - sub_addr, mod_id, &status); - } - - if (err) { - printk("Unable to send Model Subscription Add (err %d)\n", err); - return 0; - } - - if (status) { - printk("Model Subscription Add failed with status 0x%02x\n", - status); - } else { - printk("Model subscription was successful\n"); - } - - return 0; -} - -struct shell_cmd_help cmd_mod_sub_add_help = { - NULL, " [Company ID]", NULL -}; - -static int cmd_mod_sub_del(int argc, char *argv[]) -{ - uint16_t elem_addr, sub_addr, mod_id, cid; - uint8_t status; - int err; - - if (argc < 4) { - return -EINVAL; - } - - elem_addr = strtoul(argv[1], NULL, 0); - sub_addr = 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_sub_del_vnd(net.net_idx, net.dst, - elem_addr, sub_addr, mod_id, - cid, &status); - } else { - err = bt_mesh_cfg_mod_sub_del(net.net_idx, net.dst, elem_addr, - sub_addr, mod_id, &status); - } - - if (err) { - printk("Unable to send Model Subscription Delete (err %d)\n", - err); - return 0; - } - - if (status) { - printk("Model Subscription Delete failed with status 0x%02x\n", - status); - } else { - printk("Model subscription deltion was successful\n"); - } - - return 0; -} - -struct shell_cmd_help cmd_mod_sub_del_help = { - NULL, " [Company ID]", NULL -}; - -static int cmd_mod_sub_add_va(int argc, char *argv[]) -{ - uint16_t elem_addr, sub_addr, mod_id, cid; - uint8_t label[16]; - uint8_t status; - size_t len; - int err; - - if (argc < 4) { - return -EINVAL; - } - - elem_addr = strtoul(argv[1], NULL, 0); - - len = hex2bin(argv[2], label, sizeof(label)); - memset(label + len, 0, sizeof(label) - len); - - mod_id = strtoul(argv[3], NULL, 0); - - if (argc > 4) { - cid = strtoul(argv[4], NULL, 0); - err = bt_mesh_cfg_mod_sub_va_add_vnd(net.net_idx, net.dst, - elem_addr, label, mod_id, - cid, &sub_addr, &status); - } else { - err = bt_mesh_cfg_mod_sub_va_add(net.net_idx, net.dst, - elem_addr, label, mod_id, - &sub_addr, &status); - } - - if (err) { - printk("Unable to send Mod Sub VA Add (err %d)\n", err); - return 0; - } - - if (status) { - printk("Mod Sub VA Add failed with status 0x%02x\n", - status); - } else { - printk("0x%04x subscribed to Label UUID %s (va 0x%04x)\n", - elem_addr, argv[2], sub_addr); - } - - return 0; -} - -struct shell_cmd_help cmd_mod_sub_add_va_help = { - NULL, "