From 342f6a7829e9be1690b8e812d1fdea4fd5d2fd28 Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Tue, 25 Jun 2019 09:03:58 +0800 Subject: [PATCH] Port NimBLE Host Stack on ESP-IDF --- .gitmodules | 4 + components/bt/Kconfig | 1873 +++++++++-------- components/bt/bt.c | 17 + components/bt/include/esp_bt.h | 2 + components/esp32/ld/esp32.project.ld.in | 44 +- components/nimble/CMakeLists.txt | 142 ++ components/nimble/Kconfig.in | 238 +++ components/nimble/component.mk | 47 + .../nimble/esp-hci/include/esp_nimble_hci.h | 138 ++ .../nimble/esp-hci/src/esp_nimble_hci.c | 434 ++++ components/nimble/nimble | 1 + .../nimble/port/include/console/console.h | 21 + .../nimble/port/include/esp_nimble_cfg.h | 1065 ++++++++++ docs/Doxyfile | 2 + docs/_static/esp32_nimble_stack.png | Bin 0 -> 22217 bytes docs/en/COPYRIGHT.rst | 4 + docs/en/api-reference/bluetooth/index.rst | 5 + .../api-reference/bluetooth/nimble/index.rst | 44 + docs/zh_CN/api-reference/bluetooth/index.rst | 1 + .../api-reference/bluetooth/nimble/index.rst | 1 + examples/README.md | 3 +- examples/bluetooth/nimble/README.md | 32 + .../bluetooth/nimble/blecent/CMakeLists.txt | 6 + examples/bluetooth/nimble/blecent/Makefile | 8 + examples/bluetooth/nimble/blecent/README.md | 94 + .../nimble/blecent/main/CMakeLists.txt | 6 + .../nimble/blecent/main/Kconfig.projbuild | 9 + .../bluetooth/nimble/blecent/main/blecent.h | 113 + .../nimble/blecent/main/component.mk | 4 + examples/bluetooth/nimble/blecent/main/main.c | 550 +++++ examples/bluetooth/nimble/blecent/main/misc.c | 211 ++ examples/bluetooth/nimble/blecent/main/peer.c | 807 +++++++ .../nimble/blecent/sdkconfig.defaults | 12 + .../bluetooth/nimble/blehr/CMakeLists.txt | 6 + examples/bluetooth/nimble/blehr/Makefile | 8 + examples/bluetooth/nimble/blehr/README.md | 61 + .../nimble/blehr/main/CMakeLists.txt | 5 + .../bluetooth/nimble/blehr/main/blehr_sens.h | 50 + .../bluetooth/nimble/blehr/main/component.mk | 4 + .../bluetooth/nimble/blehr/main/gatt_svr.c | 186 ++ examples/bluetooth/nimble/blehr/main/main.c | 304 +++ .../bluetooth/nimble/blehr/sdkconfig.defaults | 12 + .../bluetooth/nimble/blemesh/CMakeLists.txt | 6 + examples/bluetooth/nimble/blemesh/Makefile | 8 + examples/bluetooth/nimble/blemesh/README.md | 89 + .../nimble/blemesh/main/CMakeLists.txt | 4 + .../bluetooth/nimble/blemesh/main/app_mesh.c | 444 ++++ .../nimble/blemesh/main/component.mk | 4 + .../nimble/blemesh/sdkconfig.defaults | 13 + .../bluetooth/nimble/bleprph/CMakeLists.txt | 6 + examples/bluetooth/nimble/bleprph/Makefile | 8 + examples/bluetooth/nimble/bleprph/README.md | 75 + .../nimble/bleprph/main/CMakeLists.txt | 7 + .../nimble/bleprph/main/Kconfig.projbuild | 51 + .../bluetooth/nimble/bleprph/main/bleprph.h | 56 + .../nimble/bleprph/main/component.mk | 4 + .../bluetooth/nimble/bleprph/main/gatt_svr.c | 210 ++ examples/bluetooth/nimble/bleprph/main/main.c | 388 ++++ examples/bluetooth/nimble/bleprph/main/misc.c | 43 + examples/bluetooth/nimble/bleprph/main/scli.c | 161 ++ .../nimble/bleprph/sdkconfig.defaults | 12 + 61 files changed, 7221 insertions(+), 942 deletions(-) create mode 100644 components/nimble/CMakeLists.txt create mode 100644 components/nimble/Kconfig.in create mode 100644 components/nimble/component.mk create mode 100644 components/nimble/esp-hci/include/esp_nimble_hci.h create mode 100644 components/nimble/esp-hci/src/esp_nimble_hci.c create mode 160000 components/nimble/nimble create mode 100644 components/nimble/port/include/console/console.h create mode 100644 components/nimble/port/include/esp_nimble_cfg.h create mode 100644 docs/_static/esp32_nimble_stack.png create mode 100644 docs/en/api-reference/bluetooth/nimble/index.rst create mode 100644 docs/zh_CN/api-reference/bluetooth/nimble/index.rst create mode 100644 examples/bluetooth/nimble/README.md create mode 100644 examples/bluetooth/nimble/blecent/CMakeLists.txt create mode 100644 examples/bluetooth/nimble/blecent/Makefile create mode 100644 examples/bluetooth/nimble/blecent/README.md create mode 100644 examples/bluetooth/nimble/blecent/main/CMakeLists.txt create mode 100644 examples/bluetooth/nimble/blecent/main/Kconfig.projbuild create mode 100644 examples/bluetooth/nimble/blecent/main/blecent.h create mode 100644 examples/bluetooth/nimble/blecent/main/component.mk create mode 100644 examples/bluetooth/nimble/blecent/main/main.c create mode 100644 examples/bluetooth/nimble/blecent/main/misc.c create mode 100644 examples/bluetooth/nimble/blecent/main/peer.c create mode 100644 examples/bluetooth/nimble/blecent/sdkconfig.defaults create mode 100644 examples/bluetooth/nimble/blehr/CMakeLists.txt create mode 100644 examples/bluetooth/nimble/blehr/Makefile create mode 100644 examples/bluetooth/nimble/blehr/README.md create mode 100644 examples/bluetooth/nimble/blehr/main/CMakeLists.txt create mode 100644 examples/bluetooth/nimble/blehr/main/blehr_sens.h create mode 100644 examples/bluetooth/nimble/blehr/main/component.mk create mode 100644 examples/bluetooth/nimble/blehr/main/gatt_svr.c create mode 100644 examples/bluetooth/nimble/blehr/main/main.c create mode 100644 examples/bluetooth/nimble/blehr/sdkconfig.defaults create mode 100644 examples/bluetooth/nimble/blemesh/CMakeLists.txt create mode 100644 examples/bluetooth/nimble/blemesh/Makefile create mode 100644 examples/bluetooth/nimble/blemesh/README.md create mode 100644 examples/bluetooth/nimble/blemesh/main/CMakeLists.txt create mode 100644 examples/bluetooth/nimble/blemesh/main/app_mesh.c create mode 100644 examples/bluetooth/nimble/blemesh/main/component.mk create mode 100644 examples/bluetooth/nimble/blemesh/sdkconfig.defaults create mode 100644 examples/bluetooth/nimble/bleprph/CMakeLists.txt create mode 100644 examples/bluetooth/nimble/bleprph/Makefile create mode 100644 examples/bluetooth/nimble/bleprph/README.md create mode 100644 examples/bluetooth/nimble/bleprph/main/CMakeLists.txt create mode 100644 examples/bluetooth/nimble/bleprph/main/Kconfig.projbuild create mode 100644 examples/bluetooth/nimble/bleprph/main/bleprph.h create mode 100644 examples/bluetooth/nimble/bleprph/main/component.mk create mode 100644 examples/bluetooth/nimble/bleprph/main/gatt_svr.c create mode 100644 examples/bluetooth/nimble/bleprph/main/main.c create mode 100644 examples/bluetooth/nimble/bleprph/main/misc.c create mode 100644 examples/bluetooth/nimble/bleprph/main/scli.c create mode 100644 examples/bluetooth/nimble/bleprph/sdkconfig.defaults diff --git a/.gitmodules b/.gitmodules index 9ec254527..6a656fa4c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -65,3 +65,7 @@ [submodule "components/esp_wifi/lib_esp32"] path = components/esp_wifi/lib_esp32 url = https://github.com/espressif/esp32-wifi-lib.git + +[submodule "components/nimble/nimble"] + path = components/nimble/nimble + url = https://github.com/espressif/esp-nimble.git diff --git a/components/bt/Kconfig b/components/bt/Kconfig index daf83b1be..15286d05f 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -360,1001 +360,1028 @@ menu Bluetooth endmenu - menuconfig BT_BLUEDROID_ENABLED - bool "Bluedroid Enable" - depends on BTDM_CTRL_HCI_MODE_VHCI - default y + choice BT_HOST + prompt "Bluetooth Host" + depends on BT_ENABLED && BTDM_CTRL_HCI_MODE_VHCI + default BT_BLUEDROID_ENABLED help - This enables the default Bluedroid Bluetooth stack + This helps to choose Bluetooth host stack - choice BT_BLUEDROID_PINNED_TO_CORE_CHOICE - prompt "The cpu core which Bluedroid run" - depends on BT_BLUEDROID_ENABLED && !FREERTOS_UNICORE - help - Which the cpu core to run Bluedroid. Can choose core0 and core1. - Can not specify no-affinity. - - config BT_BLUEDROID_PINNED_TO_CORE_0 - bool "Core 0 (PRO CPU)" - config BT_BLUEDROID_PINNED_TO_CORE_1 - bool "Core 1 (APP CPU)" - depends on !FREERTOS_UNICORE - endchoice - - config BT_BLUEDROID_PINNED_TO_CORE - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_BLUEDROID_PINNED_TO_CORE_0 - default 1 if BT_BLUEDROID_PINNED_TO_CORE_1 - default 0 - - config BT_BTC_TASK_STACK_SIZE - int "Bluetooth event (callback to application) task stack size" - depends on BT_BLUEDROID_ENABLED - default 3072 - help - This select btc task stack size - - config BT_BTU_TASK_STACK_SIZE - int "Bluetooth Bluedroid Host Stack task stack size" - depends on BT_BLUEDROID_ENABLED - default 4096 - help - This select btu task stack size - - config BT_BLUEDROID_MEM_DEBUG - bool "Bluedroid memory debug" - depends on BT_BLUEDROID_ENABLED - default n - help - Bluedroid memory debug - - config BT_CLASSIC_ENABLED - bool "Classic Bluetooth" - depends on BT_BLUEDROID_ENABLED - default n - help - For now this option needs "SMP_ENABLE" to be set to yes - - config BT_A2DP_ENABLE - bool "A2DP" - depends on BT_CLASSIC_ENABLED - default n - help - Advanced Audio Distrubution Profile - - config BT_A2DP_SINK_TASK_STACK_SIZE - int "A2DP sink (audio stream decoding) task stack size" - depends on BT_A2DP_ENABLE - default 2048 - - config BT_A2DP_SOURCE_TASK_STACK_SIZE - int "A2DP source (audio stream encoding) task stack size" - depends on BT_A2DP_ENABLE - default 2048 - - config BT_SPP_ENABLED - bool "SPP" - depends on BT_CLASSIC_ENABLED - default n - help - This enables the Serial Port Profile - - config BT_HFP_ENABLE - bool "Hands Free/Handset Profile" - depends on BT_CLASSIC_ENABLED - default n - - choice BT_HFP_ROLE - prompt "Hands-free Profile Role configuration" - depends on BT_HFP_ENABLE - - config BT_HFP_CLIENT_ENABLE - bool "Hands Free Unit" - endchoice - - choice BT_HFP_AUDIO_DATA_PATH - prompt "audio(SCO) data path" - depends on BT_HFP_ENABLE - help - SCO data path, i.e. HCI or PCM. This option is set using API - "esp_bredr_sco_datapath_set" in Bluetooth host. Default SCO data - path can also be set in Bluetooth Controller. - - config BT_HFP_AUDIO_DATA_PATH_PCM - bool "PCM" - config BT_HFP_AUDIO_DATA_PATH_HCI - bool "HCI" - endchoice - - config BT_SSP_ENABLED - bool "Secure Simple Pairing" - depends on BT_CLASSIC_ENABLED - default y - help - This enables the Secure Simple Pairing. If disable this option, Bluedroid will only support Legacy Pairing - - config BT_BLE_ENABLED - bool "Bluetooth Low Energy" - depends on BT_BLUEDROID_ENABLED - default y - help - This enables Bluetooth Low Energy - - config BT_GATTS_ENABLE - bool "Include GATT server module(GATTS)" - depends on BT_BLE_ENABLED - default y - help - This option can be disabled when the app work only on gatt client mode - - choice BT_GATTS_SEND_SERVICE_CHANGE_MODE - prompt "GATTS Service Change Mode" - default BT_GATTS_SEND_SERVICE_CHANGE_AUTO - depends on BT_GATTS_ENABLE - help - Service change indication mode for GATT Server. - - config BT_GATTS_SEND_SERVICE_CHANGE_MANUAL - bool "GATTS manually send service change indication" + config BT_BLUEDROID_ENABLED + bool "Bluedroid - Dual-mode" help - Manually send service change indication through API esp_ble_gatts_send_service_change_indication() + This option is recommended for classic Bluetooth or for dual-mode + usecases - config BT_GATTS_SEND_SERVICE_CHANGE_AUTO - bool "GATTS automatically send service change indication" + config BT_NIMBLE_ENABLED + bool "NimBLE - BLE only" help - Let Bluedroid handle the service change indication internally + This option is recommended for BLE only usecases to save on memory endchoice - config BT_GATTS_SEND_SERVICE_CHANGE_MODE - int - depends on BT_GATTS_ENABLE - default 0 if BT_GATTS_SEND_SERVICE_CHANGE_AUTO - default 1 if BT_GATTS_SEND_SERVICE_CHANGE_MANUAL - default 0 + menu "Bluedroid Options" + visible if BT_BLUEDROID_ENABLED - config BT_GATTC_ENABLE - bool "Include GATT client module(GATTC)" - depends on BT_BLE_ENABLED - default y - help - This option can be close when the app work only on gatt server mode - - config BT_GATTC_CACHE_NVS_FLASH - bool "Save gattc cache data to nvs flash" - depends on BT_GATTC_ENABLE - default n - help - This select can save gattc cache data to nvs flash - - config BT_BLE_SMP_ENABLE - bool "Include BLE security module(SMP)" - depends on BT_BLE_ENABLED - default y - help - This option can be close when the app not used the ble security connect. - - config BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE - bool "Slave enable connection parameters update during pairing" - depends on BT_BLE_SMP_ENABLE - default n - help - In order to reduce the pairing time, slave actively initiates connection parameters update during pairing. - - config BT_STACK_NO_LOG - bool "Disable BT debug logs (minimize bin size)" - depends on BT_BLUEDROID_ENABLED - default n - help - This select can save the rodata code size - - menu "BT DEBUG LOG LEVEL" - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG - - choice BT_LOG_HCI_TRACE_LEVEL - prompt "HCI layer" - default BT_LOG_HCI_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + choice BT_BLUEDROID_PINNED_TO_CORE_CHOICE + prompt "The cpu core which Bluedroid run" + depends on BT_BLUEDROID_ENABLED && !FREERTOS_UNICORE help - Define BT trace level for HCI layer + Which the cpu core to run Bluedroid. Can choose core0 and core1. + Can not specify no-affinity. - config BT_LOG_HCI_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_HCI_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_HCI_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_HCI_TRACE_LEVEL_API - bool "API" - config BT_LOG_HCI_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_HCI_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_HCI_TRACE_LEVEL_VERBOSE - bool "VERBOSE" + config BT_BLUEDROID_PINNED_TO_CORE_0 + bool "Core 0 (PRO CPU)" + config BT_BLUEDROID_PINNED_TO_CORE_1 + bool "Core 1 (APP CPU)" + depends on !FREERTOS_UNICORE endchoice - config BT_LOG_HCI_TRACE_LEVEL + config BT_BLUEDROID_PINNED_TO_CORE int depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_HCI_TRACE_LEVEL_NONE - default 1 if BT_LOG_HCI_TRACE_LEVEL_ERROR - default 2 if BT_LOG_HCI_TRACE_LEVEL_WARNING - default 3 if BT_LOG_HCI_TRACE_LEVEL_API - default 4 if BT_LOG_HCI_TRACE_LEVEL_EVENT - default 5 if BT_LOG_HCI_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_HCI_TRACE_LEVEL_VERBOSE - default 2 + default 0 if BT_BLUEDROID_PINNED_TO_CORE_0 + default 1 if BT_BLUEDROID_PINNED_TO_CORE_1 + default 0 - choice BT_LOG_BTM_TRACE_LEVEL - prompt "BTM layer" - default BT_LOG_BTM_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + config BT_BTC_TASK_STACK_SIZE + int "Bluetooth event (callback to application) task stack size" + depends on BT_BLUEDROID_ENABLED + default 3072 help - Define BT trace level for BTM layer + This select btc task stack size - config BT_LOG_BTM_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_BTM_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_BTM_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_BTM_TRACE_LEVEL_API - bool "API" - config BT_LOG_BTM_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_BTM_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_BTM_TRACE_LEVEL_VERBOSE - bool "VERBOSE" + config BT_BTU_TASK_STACK_SIZE + int "Bluetooth Bluedroid Host Stack task stack size" + depends on BT_BLUEDROID_ENABLED + default 4096 + help + This select btu task stack size + + config BT_BLUEDROID_MEM_DEBUG + bool "Bluedroid memory debug" + depends on BT_BLUEDROID_ENABLED + default n + help + Bluedroid memory debug + + config BT_CLASSIC_ENABLED + bool "Classic Bluetooth" + depends on BT_BLUEDROID_ENABLED + default n + help + For now this option needs "SMP_ENABLE" to be set to yes + + config BT_A2DP_ENABLE + bool "A2DP" + depends on BT_CLASSIC_ENABLED + default n + help + Advanced Audio Distrubution Profile + + config BT_A2DP_SINK_TASK_STACK_SIZE + int "A2DP sink (audio stream decoding) task stack size" + depends on BT_A2DP_ENABLE + default 2048 + + config BT_A2DP_SOURCE_TASK_STACK_SIZE + int "A2DP source (audio stream encoding) task stack size" + depends on BT_A2DP_ENABLE + default 2048 + + config BT_SPP_ENABLED + bool "SPP" + depends on BT_CLASSIC_ENABLED + default n + help + This enables the Serial Port Profile + + config BT_HFP_ENABLE + bool "Hands Free/Handset Profile" + depends on BT_CLASSIC_ENABLED + default n + + choice BT_HFP_ROLE + prompt "Hands-free Profile Role configuration" + depends on BT_HFP_ENABLE + + config BT_HFP_CLIENT_ENABLE + bool "Hands Free Unit" endchoice - config BT_LOG_BTM_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_BTM_TRACE_LEVEL_NONE - default 1 if BT_LOG_BTM_TRACE_LEVEL_ERROR - default 2 if BT_LOG_BTM_TRACE_LEVEL_WARNING - default 3 if BT_LOG_BTM_TRACE_LEVEL_API - default 4 if BT_LOG_BTM_TRACE_LEVEL_EVENT - default 5 if BT_LOG_BTM_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_BTM_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_L2CAP_TRACE_LEVEL - prompt "L2CAP layer" - default BT_LOG_L2CAP_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + choice BT_HFP_AUDIO_DATA_PATH + prompt "audio(SCO) data path" + depends on BT_HFP_ENABLE help - Define BT trace level for L2CAP layer + SCO data path, i.e. HCI or PCM. This option is set using API + "esp_bredr_sco_datapath_set" in Bluetooth host. Default SCO data + path can also be set in Bluetooth Controller. - config BT_LOG_L2CAP_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_L2CAP_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_L2CAP_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_L2CAP_TRACE_LEVEL_API - bool "API" - config BT_LOG_L2CAP_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_L2CAP_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE - bool "VERBOSE" + config BT_HFP_AUDIO_DATA_PATH_PCM + bool "PCM" + config BT_HFP_AUDIO_DATA_PATH_HCI + bool "HCI" endchoice - config BT_LOG_L2CAP_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_L2CAP_TRACE_LEVEL_NONE - default 1 if BT_LOG_L2CAP_TRACE_LEVEL_ERROR - default 2 if BT_LOG_L2CAP_TRACE_LEVEL_WARNING - default 3 if BT_LOG_L2CAP_TRACE_LEVEL_API - default 4 if BT_LOG_L2CAP_TRACE_LEVEL_EVENT - default 5 if BT_LOG_L2CAP_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_RFCOMM_TRACE_LEVEL - prompt "RFCOMM layer" - default BT_LOG_RFCOMM_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + config BT_SSP_ENABLED + bool "Secure Simple Pairing" + depends on BT_CLASSIC_ENABLED + default y help - Define BT trace level for RFCOMM layer + This enables the Secure Simple Pairing. If disable this option, + Bluedroid will only support Legacy Pairing + + config BT_BLE_ENABLED + bool "Bluetooth Low Energy" + depends on BT_BLUEDROID_ENABLED + default y + help + This enables Bluetooth Low Energy + + config BT_GATTS_ENABLE + bool "Include GATT server module(GATTS)" + depends on BT_BLE_ENABLED + default y + help + This option can be disabled when the app work only on gatt client mode + + choice BT_GATTS_SEND_SERVICE_CHANGE_MODE + prompt "GATTS Service Change Mode" + default BT_GATTS_SEND_SERVICE_CHANGE_AUTO + depends on BT_GATTS_ENABLE + help + Service change indication mode for GATT Server. + + config BT_GATTS_SEND_SERVICE_CHANGE_MANUAL + bool "GATTS manually send service change indication" + help + Manually send service change indication through API esp_ble_gatts_send_service_change_indication() + + config BT_GATTS_SEND_SERVICE_CHANGE_AUTO + bool "GATTS automatically send service change indication" + help + Let Bluedroid handle the service change indication internally - config BT_LOG_RFCOMM_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_RFCOMM_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_RFCOMM_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_RFCOMM_TRACE_LEVEL_API - bool "API" - config BT_LOG_RFCOMM_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE - bool "VERBOSE" endchoice - config BT_LOG_RFCOMM_TRACE_LEVEL + config BT_GATTS_SEND_SERVICE_CHANGE_MODE int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_RFCOMM_TRACE_LEVEL_NONE - default 1 if BT_LOG_RFCOMM_TRACE_LEVEL_ERROR - default 2 if BT_LOG_RFCOMM_TRACE_LEVEL_WARNING - default 3 if BT_LOG_RFCOMM_TRACE_LEVEL_API - default 4 if BT_LOG_RFCOMM_TRACE_LEVEL_EVENT - default 5 if BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE - default 2 + depends on BT_GATTS_ENABLE + default 0 if BT_GATTS_SEND_SERVICE_CHANGE_AUTO + default 1 if BT_GATTS_SEND_SERVICE_CHANGE_MANUAL + default 0 - choice BT_LOG_SDP_TRACE_LEVEL - prompt "SDP layer" - default BT_LOG_SDP_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + config BT_GATTC_ENABLE + bool "Include GATT client module(GATTC)" + depends on BT_BLE_ENABLED + default y help - Define BT trace level for SDP layer + This option can be close when the app work only on gatt server mode - config BT_LOG_SDP_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_SDP_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_SDP_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_SDP_TRACE_LEVEL_API - bool "API" - config BT_LOG_SDP_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_SDP_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_SDP_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_SDP_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_SDP_TRACE_LEVEL_NONE - default 1 if BT_LOG_SDP_TRACE_LEVEL_ERROR - default 2 if BT_LOG_SDP_TRACE_LEVEL_WARNING - default 3 if BT_LOG_SDP_TRACE_LEVEL_API - default 4 if BT_LOG_SDP_TRACE_LEVEL_EVENT - default 5 if BT_LOG_SDP_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_SDP_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_GAP_TRACE_LEVEL - prompt "GAP layer" - default BT_LOG_GAP_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + config BT_GATTC_CACHE_NVS_FLASH + bool "Save gattc cache data to nvs flash" + depends on BT_GATTC_ENABLE + default n help - Define BT trace level for GAP layer + This select can save gattc cache data to nvs flash - config BT_LOG_GAP_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_GAP_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_GAP_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_GAP_TRACE_LEVEL_API - bool "API" - config BT_LOG_GAP_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_GAP_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_GAP_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_GAP_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_GAP_TRACE_LEVEL_NONE - default 1 if BT_LOG_GAP_TRACE_LEVEL_ERROR - default 2 if BT_LOG_GAP_TRACE_LEVEL_WARNING - default 3 if BT_LOG_GAP_TRACE_LEVEL_API - default 4 if BT_LOG_GAP_TRACE_LEVEL_EVENT - default 5 if BT_LOG_GAP_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_GAP_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_BNEP_TRACE_LEVEL - prompt "BNEP layer" - default BT_LOG_BNEP_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + config BT_BLE_SMP_ENABLE + bool "Include BLE security module(SMP)" + depends on BT_BLE_ENABLED + default y help - Define BT trace level for BNEP layer + This option can be close when the app not used the ble security connect. - config BT_LOG_BNEP_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_BNEP_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_BNEP_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_BNEP_TRACE_LEVEL_API - bool "API" - config BT_LOG_BNEP_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_BNEP_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_BNEP_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_BNEP_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_BNEP_TRACE_LEVEL_NONE - default 1 if BT_LOG_BNEP_TRACE_LEVEL_ERROR - default 2 if BT_LOG_BNEP_TRACE_LEVEL_WARNING - default 3 if BT_LOG_BNEP_TRACE_LEVEL_API - default 4 if BT_LOG_BNEP_TRACE_LEVEL_EVENT - default 5 if BT_LOG_BNEP_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_BNEP_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_PAN_TRACE_LEVEL - prompt "PAN layer" - default BT_LOG_PAN_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + config BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE + bool "Slave enable connection parameters update during pairing" + depends on BT_BLE_SMP_ENABLE + default n help - Define BT trace level for PAN layer + In order to reduce the pairing time, slave actively initiates connection parameters + update during pairing. - config BT_LOG_PAN_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_PAN_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_PAN_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_PAN_TRACE_LEVEL_API - bool "API" - config BT_LOG_PAN_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_PAN_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_PAN_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_PAN_TRACE_LEVEL - int + config BT_STACK_NO_LOG + bool "Disable BT debug logs (minimize bin size)" depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_PAN_TRACE_LEVEL_NONE - default 1 if BT_LOG_PAN_TRACE_LEVEL_ERROR - default 2 if BT_LOG_PAN_TRACE_LEVEL_WARNING - default 3 if BT_LOG_PAN_TRACE_LEVEL_API - default 4 if BT_LOG_PAN_TRACE_LEVEL_EVENT - default 5 if BT_LOG_PAN_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_PAN_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_A2D_TRACE_LEVEL - prompt "A2D layer" - default BT_LOG_A2D_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + default n help - Define BT trace level for A2D layer + This select can save the rodata code size - config BT_LOG_A2D_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_A2D_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_A2D_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_A2D_TRACE_LEVEL_API - bool "API" - config BT_LOG_A2D_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_A2D_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_A2D_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_A2D_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_A2D_TRACE_LEVEL_NONE - default 1 if BT_LOG_A2D_TRACE_LEVEL_ERROR - default 2 if BT_LOG_A2D_TRACE_LEVEL_WARNING - default 3 if BT_LOG_A2D_TRACE_LEVEL_API - default 4 if BT_LOG_A2D_TRACE_LEVEL_EVENT - default 5 if BT_LOG_A2D_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_A2D_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_AVDT_TRACE_LEVEL - prompt "AVDT layer" - default BT_LOG_AVDT_TRACE_LEVEL_WARNING + menu "BT DEBUG LOG LEVEL" depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG - help - Define BT trace level for AVDT layer - config BT_LOG_AVDT_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_AVDT_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_AVDT_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_AVDT_TRACE_LEVEL_API - bool "API" - config BT_LOG_AVDT_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_AVDT_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_AVDT_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice + choice BT_LOG_HCI_TRACE_LEVEL + prompt "HCI layer" + default BT_LOG_HCI_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for HCI layer - config BT_LOG_AVDT_TRACE_LEVEL - int + config BT_LOG_HCI_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_HCI_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_HCI_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_HCI_TRACE_LEVEL_API + bool "API" + config BT_LOG_HCI_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_HCI_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_HCI_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_HCI_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_HCI_TRACE_LEVEL_NONE + default 1 if BT_LOG_HCI_TRACE_LEVEL_ERROR + default 2 if BT_LOG_HCI_TRACE_LEVEL_WARNING + default 3 if BT_LOG_HCI_TRACE_LEVEL_API + default 4 if BT_LOG_HCI_TRACE_LEVEL_EVENT + default 5 if BT_LOG_HCI_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_HCI_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_BTM_TRACE_LEVEL + prompt "BTM layer" + default BT_LOG_BTM_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BTM layer + + config BT_LOG_BTM_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_BTM_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_BTM_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_BTM_TRACE_LEVEL_API + bool "API" + config BT_LOG_BTM_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_BTM_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_BTM_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_BTM_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_BTM_TRACE_LEVEL_NONE + default 1 if BT_LOG_BTM_TRACE_LEVEL_ERROR + default 2 if BT_LOG_BTM_TRACE_LEVEL_WARNING + default 3 if BT_LOG_BTM_TRACE_LEVEL_API + default 4 if BT_LOG_BTM_TRACE_LEVEL_EVENT + default 5 if BT_LOG_BTM_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_BTM_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_L2CAP_TRACE_LEVEL + prompt "L2CAP layer" + default BT_LOG_L2CAP_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for L2CAP layer + + config BT_LOG_L2CAP_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_L2CAP_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_L2CAP_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_L2CAP_TRACE_LEVEL_API + bool "API" + config BT_LOG_L2CAP_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_L2CAP_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_L2CAP_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_L2CAP_TRACE_LEVEL_NONE + default 1 if BT_LOG_L2CAP_TRACE_LEVEL_ERROR + default 2 if BT_LOG_L2CAP_TRACE_LEVEL_WARNING + default 3 if BT_LOG_L2CAP_TRACE_LEVEL_API + default 4 if BT_LOG_L2CAP_TRACE_LEVEL_EVENT + default 5 if BT_LOG_L2CAP_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_RFCOMM_TRACE_LEVEL + prompt "RFCOMM layer" + default BT_LOG_RFCOMM_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for RFCOMM layer + + config BT_LOG_RFCOMM_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_RFCOMM_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_RFCOMM_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_RFCOMM_TRACE_LEVEL_API + bool "API" + config BT_LOG_RFCOMM_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_RFCOMM_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_RFCOMM_TRACE_LEVEL_NONE + default 1 if BT_LOG_RFCOMM_TRACE_LEVEL_ERROR + default 2 if BT_LOG_RFCOMM_TRACE_LEVEL_WARNING + default 3 if BT_LOG_RFCOMM_TRACE_LEVEL_API + default 4 if BT_LOG_RFCOMM_TRACE_LEVEL_EVENT + default 5 if BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_SDP_TRACE_LEVEL + prompt "SDP layer" + default BT_LOG_SDP_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for SDP layer + + config BT_LOG_SDP_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_SDP_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_SDP_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_SDP_TRACE_LEVEL_API + bool "API" + config BT_LOG_SDP_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_SDP_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_SDP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_SDP_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_SDP_TRACE_LEVEL_NONE + default 1 if BT_LOG_SDP_TRACE_LEVEL_ERROR + default 2 if BT_LOG_SDP_TRACE_LEVEL_WARNING + default 3 if BT_LOG_SDP_TRACE_LEVEL_API + default 4 if BT_LOG_SDP_TRACE_LEVEL_EVENT + default 5 if BT_LOG_SDP_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_SDP_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_GAP_TRACE_LEVEL + prompt "GAP layer" + default BT_LOG_GAP_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for GAP layer + + config BT_LOG_GAP_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_GAP_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_GAP_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_GAP_TRACE_LEVEL_API + bool "API" + config BT_LOG_GAP_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_GAP_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_GAP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_GAP_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_GAP_TRACE_LEVEL_NONE + default 1 if BT_LOG_GAP_TRACE_LEVEL_ERROR + default 2 if BT_LOG_GAP_TRACE_LEVEL_WARNING + default 3 if BT_LOG_GAP_TRACE_LEVEL_API + default 4 if BT_LOG_GAP_TRACE_LEVEL_EVENT + default 5 if BT_LOG_GAP_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_GAP_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_BNEP_TRACE_LEVEL + prompt "BNEP layer" + default BT_LOG_BNEP_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BNEP layer + + config BT_LOG_BNEP_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_BNEP_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_BNEP_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_BNEP_TRACE_LEVEL_API + bool "API" + config BT_LOG_BNEP_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_BNEP_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_BNEP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_BNEP_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_BNEP_TRACE_LEVEL_NONE + default 1 if BT_LOG_BNEP_TRACE_LEVEL_ERROR + default 2 if BT_LOG_BNEP_TRACE_LEVEL_WARNING + default 3 if BT_LOG_BNEP_TRACE_LEVEL_API + default 4 if BT_LOG_BNEP_TRACE_LEVEL_EVENT + default 5 if BT_LOG_BNEP_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_BNEP_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_PAN_TRACE_LEVEL + prompt "PAN layer" + default BT_LOG_PAN_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for PAN layer + + config BT_LOG_PAN_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_PAN_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_PAN_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_PAN_TRACE_LEVEL_API + bool "API" + config BT_LOG_PAN_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_PAN_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_PAN_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_PAN_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_PAN_TRACE_LEVEL_NONE + default 1 if BT_LOG_PAN_TRACE_LEVEL_ERROR + default 2 if BT_LOG_PAN_TRACE_LEVEL_WARNING + default 3 if BT_LOG_PAN_TRACE_LEVEL_API + default 4 if BT_LOG_PAN_TRACE_LEVEL_EVENT + default 5 if BT_LOG_PAN_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_PAN_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_A2D_TRACE_LEVEL + prompt "A2D layer" + default BT_LOG_A2D_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for A2D layer + + config BT_LOG_A2D_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_A2D_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_A2D_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_A2D_TRACE_LEVEL_API + bool "API" + config BT_LOG_A2D_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_A2D_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_A2D_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_A2D_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_A2D_TRACE_LEVEL_NONE + default 1 if BT_LOG_A2D_TRACE_LEVEL_ERROR + default 2 if BT_LOG_A2D_TRACE_LEVEL_WARNING + default 3 if BT_LOG_A2D_TRACE_LEVEL_API + default 4 if BT_LOG_A2D_TRACE_LEVEL_EVENT + default 5 if BT_LOG_A2D_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_A2D_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_AVDT_TRACE_LEVEL + prompt "AVDT layer" + default BT_LOG_AVDT_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for AVDT layer + + config BT_LOG_AVDT_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_AVDT_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_AVDT_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_AVDT_TRACE_LEVEL_API + bool "API" + config BT_LOG_AVDT_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_AVDT_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_AVDT_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_AVDT_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_AVDT_TRACE_LEVEL_NONE + default 1 if BT_LOG_AVDT_TRACE_LEVEL_ERROR + default 2 if BT_LOG_AVDT_TRACE_LEVEL_WARNING + default 3 if BT_LOG_AVDT_TRACE_LEVEL_API + default 4 if BT_LOG_AVDT_TRACE_LEVEL_EVENT + default 5 if BT_LOG_AVDT_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_AVDT_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_AVCT_TRACE_LEVEL + prompt "AVCT layer" + default BT_LOG_AVCT_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for AVCT layer + + config BT_LOG_AVCT_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_AVCT_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_AVCT_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_AVCT_TRACE_LEVEL_API + bool "API" + config BT_LOG_AVCT_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_AVCT_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_AVCT_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_AVCT_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_AVCT_TRACE_LEVEL_NONE + default 1 if BT_LOG_AVCT_TRACE_LEVEL_ERROR + default 2 if BT_LOG_AVCT_TRACE_LEVEL_WARNING + default 3 if BT_LOG_AVCT_TRACE_LEVEL_API + default 4 if BT_LOG_AVCT_TRACE_LEVEL_EVENT + default 5 if BT_LOG_AVCT_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_AVCT_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_AVRC_TRACE_LEVEL + prompt "AVRC layer" + default BT_LOG_AVRC_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for AVRC layer + + config BT_LOG_AVRC_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_AVRC_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_AVRC_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_AVRC_TRACE_LEVEL_API + bool "API" + config BT_LOG_AVRC_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_AVRC_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_AVRC_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_AVRC_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_AVRC_TRACE_LEVEL_NONE + default 1 if BT_LOG_AVRC_TRACE_LEVEL_ERROR + default 2 if BT_LOG_AVRC_TRACE_LEVEL_WARNING + default 3 if BT_LOG_AVRC_TRACE_LEVEL_API + default 4 if BT_LOG_AVRC_TRACE_LEVEL_EVENT + default 5 if BT_LOG_AVRC_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_AVRC_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_MCA_TRACE_LEVEL + prompt "MCA layer" + default BT_LOG_MCA_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for MCA layer + + config BT_LOG_MCA_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_MCA_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_MCA_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_MCA_TRACE_LEVEL_API + bool "API" + config BT_LOG_MCA_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_MCA_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_MCA_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_MCA_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_MCA_TRACE_LEVEL_NONE + default 1 if BT_LOG_MCA_TRACE_LEVEL_ERROR + default 2 if BT_LOG_MCA_TRACE_LEVEL_WARNING + default 3 if BT_LOG_MCA_TRACE_LEVEL_API + default 4 if BT_LOG_MCA_TRACE_LEVEL_EVENT + default 5 if BT_LOG_MCA_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_MCA_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_HID_TRACE_LEVEL + prompt "HID layer" + default BT_LOG_HID_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for HID layer + + config BT_LOG_HID_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_HID_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_HID_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_HID_TRACE_LEVEL_API + bool "API" + config BT_LOG_HID_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_HID_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_HID_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_HID_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_HID_TRACE_LEVEL_NONE + default 1 if BT_LOG_HID_TRACE_LEVEL_ERROR + default 2 if BT_LOG_HID_TRACE_LEVEL_WARNING + default 3 if BT_LOG_HID_TRACE_LEVEL_API + default 4 if BT_LOG_HID_TRACE_LEVEL_EVENT + default 5 if BT_LOG_HID_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_HID_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_APPL_TRACE_LEVEL + prompt "APPL layer" + default BT_LOG_APPL_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for APPL layer + + config BT_LOG_APPL_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_APPL_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_APPL_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_APPL_TRACE_LEVEL_API + bool "API" + config BT_LOG_APPL_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_APPL_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_APPL_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_APPL_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_APPL_TRACE_LEVEL_NONE + default 1 if BT_LOG_APPL_TRACE_LEVEL_ERROR + default 2 if BT_LOG_APPL_TRACE_LEVEL_WARNING + default 3 if BT_LOG_APPL_TRACE_LEVEL_API + default 4 if BT_LOG_APPL_TRACE_LEVEL_EVENT + default 5 if BT_LOG_APPL_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_APPL_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_GATT_TRACE_LEVEL + prompt "GATT layer" + default BT_LOG_GATT_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for GATT layer + + config BT_LOG_GATT_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_GATT_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_GATT_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_GATT_TRACE_LEVEL_API + bool "API" + config BT_LOG_GATT_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_GATT_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_GATT_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_GATT_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_GATT_TRACE_LEVEL_NONE + default 1 if BT_LOG_GATT_TRACE_LEVEL_ERROR + default 2 if BT_LOG_GATT_TRACE_LEVEL_WARNING + default 3 if BT_LOG_GATT_TRACE_LEVEL_API + default 4 if BT_LOG_GATT_TRACE_LEVEL_EVENT + default 5 if BT_LOG_GATT_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_GATT_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_SMP_TRACE_LEVEL + prompt "SMP layer" + default BT_LOG_SMP_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for SMP layer + + config BT_LOG_SMP_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_SMP_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_SMP_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_SMP_TRACE_LEVEL_API + bool "API" + config BT_LOG_SMP_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_SMP_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_SMP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_SMP_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_SMP_TRACE_LEVEL_NONE + default 1 if BT_LOG_SMP_TRACE_LEVEL_ERROR + default 2 if BT_LOG_SMP_TRACE_LEVEL_WARNING + default 3 if BT_LOG_SMP_TRACE_LEVEL_API + default 4 if BT_LOG_SMP_TRACE_LEVEL_EVENT + default 5 if BT_LOG_SMP_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_SMP_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_BTIF_TRACE_LEVEL + prompt "BTIF layer" + default BT_LOG_BTIF_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BTIF layer + + config BT_LOG_BTIF_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_BTIF_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_BTIF_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_BTIF_TRACE_LEVEL_API + bool "API" + config BT_LOG_BTIF_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_BTIF_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_BTIF_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_BTIF_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_BTIF_TRACE_LEVEL_NONE + default 1 if BT_LOG_BTIF_TRACE_LEVEL_ERROR + default 2 if BT_LOG_BTIF_TRACE_LEVEL_WARNING + default 3 if BT_LOG_BTIF_TRACE_LEVEL_API + default 4 if BT_LOG_BTIF_TRACE_LEVEL_EVENT + default 5 if BT_LOG_BTIF_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_BTIF_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_BTC_TRACE_LEVEL + prompt "BTC layer" + default BT_LOG_BTC_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BTC layer + + config BT_LOG_BTC_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_BTC_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_BTC_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_BTC_TRACE_LEVEL_API + bool "API" + config BT_LOG_BTC_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_BTC_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_BTC_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_BTC_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_BTC_TRACE_LEVEL_NONE + default 1 if BT_LOG_BTC_TRACE_LEVEL_ERROR + default 2 if BT_LOG_BTC_TRACE_LEVEL_WARNING + default 3 if BT_LOG_BTC_TRACE_LEVEL_API + default 4 if BT_LOG_BTC_TRACE_LEVEL_EVENT + default 5 if BT_LOG_BTC_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_BTC_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_OSI_TRACE_LEVEL + prompt "OSI layer" + default BT_LOG_OSI_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for OSI layer + + config BT_LOG_OSI_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_OSI_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_OSI_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_OSI_TRACE_LEVEL_API + bool "API" + config BT_LOG_OSI_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_OSI_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_OSI_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_OSI_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_OSI_TRACE_LEVEL_NONE + default 1 if BT_LOG_OSI_TRACE_LEVEL_ERROR + default 2 if BT_LOG_OSI_TRACE_LEVEL_WARNING + default 3 if BT_LOG_OSI_TRACE_LEVEL_API + default 4 if BT_LOG_OSI_TRACE_LEVEL_EVENT + default 5 if BT_LOG_OSI_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_OSI_TRACE_LEVEL_VERBOSE + default 2 + + choice BT_LOG_BLUFI_TRACE_LEVEL + prompt "BLUFI layer" + default BT_LOG_BLUFI_TRACE_LEVEL_WARNING + depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BLUFI layer + + config BT_LOG_BLUFI_TRACE_LEVEL_NONE + bool "NONE" + config BT_LOG_BLUFI_TRACE_LEVEL_ERROR + bool "ERROR" + config BT_LOG_BLUFI_TRACE_LEVEL_WARNING + bool "WARNING" + config BT_LOG_BLUFI_TRACE_LEVEL_API + bool "API" + config BT_LOG_BLUFI_TRACE_LEVEL_EVENT + bool "EVENT" + config BT_LOG_BLUFI_TRACE_LEVEL_DEBUG + bool "DEBUG" + config BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE + bool "VERBOSE" + endchoice + + config BT_LOG_BLUFI_TRACE_LEVEL + int + depends on BT_BLUEDROID_ENABLED + default 0 if BT_LOG_BLUFI_TRACE_LEVEL_NONE + default 1 if BT_LOG_BLUFI_TRACE_LEVEL_ERROR + default 2 if BT_LOG_BLUFI_TRACE_LEVEL_WARNING + default 3 if BT_LOG_BLUFI_TRACE_LEVEL_API + default 4 if BT_LOG_BLUFI_TRACE_LEVEL_EVENT + default 5 if BT_LOG_BLUFI_TRACE_LEVEL_DEBUG + default 6 if BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE + default 2 + + endmenu #BT DEBUG LOG LEVEL + + + config BT_ACL_CONNECTIONS + int "BT/BLE MAX ACL CONNECTIONS(1~7)" depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_AVDT_TRACE_LEVEL_NONE - default 1 if BT_LOG_AVDT_TRACE_LEVEL_ERROR - default 2 if BT_LOG_AVDT_TRACE_LEVEL_WARNING - default 3 if BT_LOG_AVDT_TRACE_LEVEL_API - default 4 if BT_LOG_AVDT_TRACE_LEVEL_EVENT - default 5 if BT_LOG_AVDT_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_AVDT_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_AVCT_TRACE_LEVEL - prompt "AVCT layer" - default BT_LOG_AVCT_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + range 1 7 + default 4 help - Define BT trace level for AVCT layer + Maximum BT/BLE connection count - config BT_LOG_AVCT_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_AVCT_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_AVCT_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_AVCT_TRACE_LEVEL_API - bool "API" - config BT_LOG_AVCT_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_AVCT_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_AVCT_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_AVCT_TRACE_LEVEL - int + config BT_ALLOCATION_FROM_SPIRAM_FIRST + bool "BT/BLE will first malloc the memory from the PSRAM" depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_AVCT_TRACE_LEVEL_NONE - default 1 if BT_LOG_AVCT_TRACE_LEVEL_ERROR - default 2 if BT_LOG_AVCT_TRACE_LEVEL_WARNING - default 3 if BT_LOG_AVCT_TRACE_LEVEL_API - default 4 if BT_LOG_AVCT_TRACE_LEVEL_EVENT - default 5 if BT_LOG_AVCT_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_AVCT_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_AVRC_TRACE_LEVEL - prompt "AVRC layer" - default BT_LOG_AVRC_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + default n help - Define BT trace level for AVRC layer + This select can save the internal RAM if there have the PSRAM - config BT_LOG_AVRC_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_AVRC_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_AVRC_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_AVRC_TRACE_LEVEL_API - bool "API" - config BT_LOG_AVRC_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_AVRC_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_AVRC_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_AVRC_TRACE_LEVEL - int + config BT_BLE_DYNAMIC_ENV_MEMORY + bool "Use dynamic memory allocation in BT/BLE stack" depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_AVRC_TRACE_LEVEL_NONE - default 1 if BT_LOG_AVRC_TRACE_LEVEL_ERROR - default 2 if BT_LOG_AVRC_TRACE_LEVEL_WARNING - default 3 if BT_LOG_AVRC_TRACE_LEVEL_API - default 4 if BT_LOG_AVRC_TRACE_LEVEL_EVENT - default 5 if BT_LOG_AVRC_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_AVRC_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_MCA_TRACE_LEVEL - prompt "MCA layer" - default BT_LOG_MCA_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + default n help - Define BT trace level for MCA layer + This select can make the allocation of memory will become more flexible - config BT_LOG_MCA_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_MCA_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_MCA_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_MCA_TRACE_LEVEL_API - bool "API" - config BT_LOG_MCA_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_MCA_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_MCA_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_MCA_TRACE_LEVEL - int + config BT_BLE_HOST_QUEUE_CONG_CHECK + bool "BLE queue congestion check" depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_MCA_TRACE_LEVEL_NONE - default 1 if BT_LOG_MCA_TRACE_LEVEL_ERROR - default 2 if BT_LOG_MCA_TRACE_LEVEL_WARNING - default 3 if BT_LOG_MCA_TRACE_LEVEL_API - default 4 if BT_LOG_MCA_TRACE_LEVEL_EVENT - default 5 if BT_LOG_MCA_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_MCA_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_HID_TRACE_LEVEL - prompt "HID layer" - default BT_LOG_HID_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + default n help - Define BT trace level for HID layer + When scanning and scan duplicate is not enabled, if there are a lot of adv packets around + or application layer handling adv packets is slow, it will cause the controller memory + to run out. if enabled, adv packets will be lost when host queue is congested. - config BT_LOG_HID_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_HID_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_HID_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_HID_TRACE_LEVEL_API - bool "API" - config BT_LOG_HID_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_HID_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_HID_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_HID_TRACE_LEVEL - int + config BT_SMP_ENABLE + bool depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_HID_TRACE_LEVEL_NONE - default 1 if BT_LOG_HID_TRACE_LEVEL_ERROR - default 2 if BT_LOG_HID_TRACE_LEVEL_WARNING - default 3 if BT_LOG_HID_TRACE_LEVEL_API - default 4 if BT_LOG_HID_TRACE_LEVEL_EVENT - default 5 if BT_LOG_HID_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_HID_TRACE_LEVEL_VERBOSE - default 2 + default BT_CLASSIC_ENABLED || BT_BLE_SMP_ENABLE - choice BT_LOG_APPL_TRACE_LEVEL - prompt "APPL layer" - default BT_LOG_APPL_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + config BT_BLE_ACT_SCAN_REP_ADV_SCAN + bool "Report adv data and scan response individually when BLE active scan" + depends on BT_BLUEDROID_ENABLED && (BTDM_CTRL_MODE_BTDM || BTDM_CTRL_MODE_BLE_ONLY) + default n help - Define BT trace level for APPL layer + Originally, when doing BLE active scan, Bluedroid will not report adv to application layer + until receive scan response. This option is used to disable the behavior. When enable this option, + Bluedroid will report adv data or scan response to application layer immediately. - config BT_LOG_APPL_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_APPL_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_APPL_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_APPL_TRACE_LEVEL_API - bool "API" - config BT_LOG_APPL_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_APPL_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_APPL_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice + # Memory reserved at start of DRAM for Bluetooth stack - config BT_LOG_APPL_TRACE_LEVEL - int + config BT_BLE_ESTAB_LINK_CONN_TOUT + int "Timeout of BLE connection establishment" depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_APPL_TRACE_LEVEL_NONE - default 1 if BT_LOG_APPL_TRACE_LEVEL_ERROR - default 2 if BT_LOG_APPL_TRACE_LEVEL_WARNING - default 3 if BT_LOG_APPL_TRACE_LEVEL_API - default 4 if BT_LOG_APPL_TRACE_LEVEL_EVENT - default 5 if BT_LOG_APPL_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_APPL_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_GATT_TRACE_LEVEL - prompt "GATT layer" - default BT_LOG_GATT_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG + range 1 60 + default 30 help - Define BT trace level for GATT layer + Bluetooth Connection establishment maximum time, if connection time exceeds this value, the connection + establishment fails, ESP_GATTC_OPEN_EVT or ESP_GATTS_OPEN_EVT is triggered. - config BT_LOG_GATT_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_GATT_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_GATT_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_GATT_TRACE_LEVEL_API - bool "API" - config BT_LOG_GATT_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_GATT_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_GATT_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice + config BT_RESERVE_DRAM + hex + default 0xdb5c if BT_ENABLED + default 0 - config BT_LOG_GATT_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_GATT_TRACE_LEVEL_NONE - default 1 if BT_LOG_GATT_TRACE_LEVEL_ERROR - default 2 if BT_LOG_GATT_TRACE_LEVEL_WARNING - default 3 if BT_LOG_GATT_TRACE_LEVEL_API - default 4 if BT_LOG_GATT_TRACE_LEVEL_EVENT - default 5 if BT_LOG_GATT_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_GATT_TRACE_LEVEL_VERBOSE - default 2 + endmenu - choice BT_LOG_SMP_TRACE_LEVEL - prompt "SMP layer" - default BT_LOG_SMP_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG - help - Define BT trace level for SMP layer + menu "NimBLE Options" + visible if BT_NIMBLE_ENABLED - config BT_LOG_SMP_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_SMP_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_SMP_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_SMP_TRACE_LEVEL_API - bool "API" - config BT_LOG_SMP_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_SMP_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_SMP_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_SMP_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_SMP_TRACE_LEVEL_NONE - default 1 if BT_LOG_SMP_TRACE_LEVEL_ERROR - default 2 if BT_LOG_SMP_TRACE_LEVEL_WARNING - default 3 if BT_LOG_SMP_TRACE_LEVEL_API - default 4 if BT_LOG_SMP_TRACE_LEVEL_EVENT - default 5 if BT_LOG_SMP_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_SMP_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_BTIF_TRACE_LEVEL - prompt "BTIF layer" - default BT_LOG_BTIF_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG - help - Define BT trace level for BTIF layer - - config BT_LOG_BTIF_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_BTIF_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_BTIF_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_BTIF_TRACE_LEVEL_API - bool "API" - config BT_LOG_BTIF_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_BTIF_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_BTIF_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_BTIF_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_BTIF_TRACE_LEVEL_NONE - default 1 if BT_LOG_BTIF_TRACE_LEVEL_ERROR - default 2 if BT_LOG_BTIF_TRACE_LEVEL_WARNING - default 3 if BT_LOG_BTIF_TRACE_LEVEL_API - default 4 if BT_LOG_BTIF_TRACE_LEVEL_EVENT - default 5 if BT_LOG_BTIF_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_BTIF_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_BTC_TRACE_LEVEL - prompt "BTC layer" - default BT_LOG_BTC_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG - help - Define BT trace level for BTC layer - - config BT_LOG_BTC_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_BTC_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_BTC_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_BTC_TRACE_LEVEL_API - bool "API" - config BT_LOG_BTC_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_BTC_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_BTC_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_BTC_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_BTC_TRACE_LEVEL_NONE - default 1 if BT_LOG_BTC_TRACE_LEVEL_ERROR - default 2 if BT_LOG_BTC_TRACE_LEVEL_WARNING - default 3 if BT_LOG_BTC_TRACE_LEVEL_API - default 4 if BT_LOG_BTC_TRACE_LEVEL_EVENT - default 5 if BT_LOG_BTC_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_BTC_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_OSI_TRACE_LEVEL - prompt "OSI layer" - default BT_LOG_OSI_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG - help - Define BT trace level for OSI layer - - config BT_LOG_OSI_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_OSI_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_OSI_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_OSI_TRACE_LEVEL_API - bool "API" - config BT_LOG_OSI_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_OSI_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_OSI_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_OSI_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_OSI_TRACE_LEVEL_NONE - default 1 if BT_LOG_OSI_TRACE_LEVEL_ERROR - default 2 if BT_LOG_OSI_TRACE_LEVEL_WARNING - default 3 if BT_LOG_OSI_TRACE_LEVEL_API - default 4 if BT_LOG_OSI_TRACE_LEVEL_EVENT - default 5 if BT_LOG_OSI_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_OSI_TRACE_LEVEL_VERBOSE - default 2 - - choice BT_LOG_BLUFI_TRACE_LEVEL - prompt "BLUFI layer" - default BT_LOG_BLUFI_TRACE_LEVEL_WARNING - depends on BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG - help - Define BT trace level for BLUFI layer - - config BT_LOG_BLUFI_TRACE_LEVEL_NONE - bool "NONE" - config BT_LOG_BLUFI_TRACE_LEVEL_ERROR - bool "ERROR" - config BT_LOG_BLUFI_TRACE_LEVEL_WARNING - bool "WARNING" - config BT_LOG_BLUFI_TRACE_LEVEL_API - bool "API" - config BT_LOG_BLUFI_TRACE_LEVEL_EVENT - bool "EVENT" - config BT_LOG_BLUFI_TRACE_LEVEL_DEBUG - bool "DEBUG" - config BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE - bool "VERBOSE" - endchoice - - config BT_LOG_BLUFI_TRACE_LEVEL - int - depends on BT_BLUEDROID_ENABLED - default 0 if BT_LOG_BLUFI_TRACE_LEVEL_NONE - default 1 if BT_LOG_BLUFI_TRACE_LEVEL_ERROR - default 2 if BT_LOG_BLUFI_TRACE_LEVEL_WARNING - default 3 if BT_LOG_BLUFI_TRACE_LEVEL_API - default 4 if BT_LOG_BLUFI_TRACE_LEVEL_EVENT - default 5 if BT_LOG_BLUFI_TRACE_LEVEL_DEBUG - default 6 if BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE - default 2 - - endmenu #BT DEBUG LOG LEVEL - - - config BT_ACL_CONNECTIONS - int "BT/BLE MAX ACL CONNECTIONS(1~7)" - depends on BT_BLUEDROID_ENABLED - range 1 7 - default 4 - help - Maximum BT/BLE connection count - - config BT_ALLOCATION_FROM_SPIRAM_FIRST - bool "BT/BLE will first malloc the memory from the PSRAM" - depends on BT_BLUEDROID_ENABLED - default n - help - This select can save the internal RAM if there have the PSRAM - - config BT_BLE_DYNAMIC_ENV_MEMORY - bool "Use dynamic memory allocation in BT/BLE stack" - depends on BT_BLUEDROID_ENABLED - default n - help - This select can make the allocation of memory will become more flexible - - config BT_BLE_HOST_QUEUE_CONG_CHECK - bool "BLE queue congestion check" - depends on BT_BLUEDROID_ENABLED - default n - help - When scanning and scan duplicate is not enabled, if there are a lot of adv packets around or application - layer handling adv packets is slow, it will cause the controller memory to run out. if enabled, adv - packets will be lost when host queue is congested. - - config BT_SMP_ENABLE - bool - depends on BT_BLUEDROID_ENABLED - default BT_CLASSIC_ENABLED || BT_BLE_SMP_ENABLE - - config BT_BLE_ACT_SCAN_REP_ADV_SCAN - bool "Report adv data and scan response individually when BLE active scan" - depends on BT_BLUEDROID_ENABLED && (BTDM_CTRL_MODE_BTDM || BTDM_CTRL_MODE_BLE_ONLY) - default n - help - Originally, when doing BLE active scan, Bluedroid will not report adv to application layer - until receive scan response. This option is used to disable the behavior. When enable this option, - Bluedroid will report adv data or scan response to application layer immediately. - - # Memory reserved at start of DRAM for Bluetooth stack - - config BT_BLE_ESTAB_LINK_CONN_TOUT - int "Timeout of BLE connection establishment" - depends on BT_BLUEDROID_ENABLED - range 1 60 - default 30 - help - Bluetooth Connection establishment maximum time, if connection time exceeds this value, the connection - establishment fails, ESP_GATTC_OPEN_EVT or ESP_GATTS_OPEN_EVT is triggered. - - config BT_RESERVE_DRAM - hex - default 0xdb5c if BT_ENABLED - default 0 + source "$IDF_PATH/components/nimble/Kconfig.in" + endmenu endmenu menuconfig BLE_MESH bool "BLE Mesh Support" + depends on BT_BLUEDROID_ENABLED help This option enables BLE Mesh support. The specific features that are available may depend on other features that have been enabled in the diff --git a/components/bt/bt.c b/components/bt/bt.c index 2c665f20a..db19faea2 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -234,10 +234,14 @@ extern uint32_t _data_end_btdm_rom; extern uint32_t _bt_bss_start; extern uint32_t _bt_bss_end; +extern uint32_t _nimble_bss_start; +extern uint32_t _nimble_bss_end; extern uint32_t _btdm_bss_start; extern uint32_t _btdm_bss_end; extern uint32_t _bt_data_start; extern uint32_t _bt_data_end; +extern uint32_t _nimble_data_start; +extern uint32_t _nimble_data_end; extern uint32_t _btdm_data_start; extern uint32_t _btdm_data_end; @@ -1045,6 +1049,19 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) ESP_LOGD(BTDM_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x]", mem_start, mem_end); ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); } + + mem_start = (intptr_t)&_nimble_bss_start; + mem_end = (intptr_t)&_nimble_bss_end; + if (mem_start != mem_end) { + ESP_LOGD(BTDM_LOG_TAG, "Release NimBLE BSS [0x%08x] - [0x%08x]", mem_start, mem_end); + ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); + } + mem_start = (intptr_t)&_nimble_data_start; + mem_end = (intptr_t)&_nimble_data_end; + if (mem_start != mem_end) { + ESP_LOGD(BTDM_LOG_TAG, "Release NimBLE Data [0x%08x] - [0x%08x]", mem_start, mem_end); + ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); + } } return ESP_OK; } diff --git a/components/bt/include/esp_bt.h b/components/bt/include/esp_bt.h index 115784321..c0bc9c58f 100644 --- a/components/bt/include/esp_bt.h +++ b/components/bt/include/esp_bt.h @@ -417,6 +417,8 @@ esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode); * esp_bt_controller_deinit(); * esp_bt_mem_release(ESP_BT_MODE_BTDM); * + * @note In case of NimBLE host, to release BSS and data memory to heap, the mode needs to be + * set to ESP_BT_MODE_BTDM as controller is dual mode. * @param mode : the mode whose memory is to be released * @return ESP_OK - success, other - failed */ diff --git a/components/esp32/ld/esp32.project.ld.in b/components/esp32/ld/esp32.project.ld.in index 774ebcefb..872cecd33 100644 --- a/components/esp32/ld/esp32.project.ld.in +++ b/components/esp32/ld/esp32.project.ld.in @@ -15,9 +15,9 @@ SECTIONS *rtc_wake_stub*.*(.literal .text .literal.* .text.*) _rtc_text_end = ABSOLUTE(.); } > rtc_iram_seg - + /* - This section is required to skip rtc.text area because rtc_iram_seg and + This section is required to skip rtc.text area because rtc_iram_seg and rtc_data_seg are reflect the same address space on different buses. */ .rtc.dummy : @@ -28,8 +28,8 @@ SECTIONS _rtc_dummy_end = ABSOLUTE(.); } > rtc_data_seg - /* This section located in RTC FAST Memory area. - It holds data marked with RTC_FAST_ATTR attribute. + /* This section located in RTC FAST Memory area. + It holds data marked with RTC_FAST_ATTR attribute. See the file "esp_attr.h" for more information. */ .rtc.force_fast : @@ -45,7 +45,7 @@ SECTIONS data/rodata, including from any source file named rtc_wake_stub*.c and the data marked with RTC_DATA_ATTR, RTC_RODATA_ATTR attributes. - The memory location of the data is dependent on + The memory location of the data is dependent on CONFIG_ESP32_RTCDATA_IN_FAST_MEM option. */ .rtc.data : @@ -70,11 +70,11 @@ SECTIONS _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location - /* This section holds data that should not be initialized at power up + /* This section holds data that should not be initialized at power up and will be retained during deep sleep. User data marked with RTC_NOINIT_ATTR will be placed - into this section. See the file "esp_attr.h" for more information. - The memory location of the data is dependent on + into this section. See the file "esp_attr.h" for more information. + The memory location of the data is dependent on CONFIG_ESP32_RTCDATA_IN_FAST_MEM option. */ .rtc_noinit (NOLOAD): @@ -86,8 +86,8 @@ SECTIONS _rtc_noinit_end = ABSOLUTE(.); } > rtc_data_location - /* This section located in RTC SLOW Memory area. - It holds data marked with RTC_SLOW_ATTR attribute. + /* This section located in RTC SLOW Memory area. + It holds data marked with RTC_SLOW_ATTR attribute. See the file "esp_attr.h" for more information. */ .rtc.force_slow : @@ -100,17 +100,17 @@ SECTIONS } > rtc_slow_seg /* Get size of rtc slow data based on rtc_data_location alias */ - _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_slow_end - _rtc_data_start) + _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) + ? (_rtc_force_slow_end - _rtc_data_start) : (_rtc_force_slow_end - _rtc_force_slow_start); - _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) - ? (_rtc_force_fast_end - _rtc_fast_start) + _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location)) + ? (_rtc_force_fast_end - _rtc_fast_start) : (_rtc_noinit_end - _rtc_fast_start); - + ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)), "RTC_SLOW segment data does not fit.") - + ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)), "RTC_FAST segment data does not fit.") @@ -178,6 +178,10 @@ SECTIONS *libbtdm_app.a:(.data .data.*) . = ALIGN (4); _btdm_data_end = ABSOLUTE(.); + _nimble_data_start = ABSOLUTE(.); + *libnimble.a:(.data .data.*) + . = ALIGN (4); + _nimble_data_end = ABSOLUTE(.); *(.gnu.linkonce.d.*) *(.data1) *(.sdata) @@ -203,7 +207,7 @@ SECTIONS { . = ALIGN(4); _noinit_start = ABSOLUTE(.); - *(.noinit .noinit.*) + *(.noinit .noinit.*) . = ALIGN(4) ; _noinit_end = ABSOLUTE(.); } > dram0_0_seg @@ -222,6 +226,10 @@ SECTIONS *libbtdm_app.a:(.bss .bss.* COMMON) . = ALIGN (4); _btdm_bss_end = ABSOLUTE(.); + _nimble_bss_start = ABSOLUTE(.); + *libnimble.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _nimble_bss_end = ABSOLUTE(.); mapping[dram0_bss] @@ -243,7 +251,7 @@ SECTIONS ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.") - + .flash.rodata : { _rodata_start = ABSOLUTE(.); diff --git a/components/nimble/CMakeLists.txt b/components/nimble/CMakeLists.txt new file mode 100644 index 000000000..34c5944e5 --- /dev/null +++ b/components/nimble/CMakeLists.txt @@ -0,0 +1,142 @@ +if(CONFIG_BT_NIMBLE_ENABLED) + + set(COMPONENT_ADD_INCLUDEDIRS + nimble/porting/nimble/include + port/include + nimble/nimble/include + nimble/nimble/host/include + nimble/nimble/host/services/ans/include + nimble/nimble/host/services/bas/include + nimble/nimble/host/services/gap/include + nimble/nimble/host/services/gatt/include + nimble/nimble/host/services/ias/include + nimble/nimble/host/services/lls/include + nimble/nimble/host/services/tps/include + nimble/nimble/host/util/include + nimble/nimble/host/store/ram/include + nimble/nimble/host/store/config/include + nimble/porting/npl/freertos/include + nimble/ext/tinycrypt/include + esp-hci/include) + + + + set(COMPONENT_SRCS "./nimble/ext/tinycrypt/src/utils.c" + "./nimble/ext/tinycrypt/src/sha256.c" + "./nimble/ext/tinycrypt/src/ecc.c" + "./nimble/ext/tinycrypt/src/ctr_prng.c" + "./nimble/ext/tinycrypt/src/ctr_mode.c" + "./nimble/ext/tinycrypt/src/aes_decrypt.c" + "./nimble/ext/tinycrypt/src/aes_encrypt.c" + "./nimble/ext/tinycrypt/src/ccm_mode.c" + "./nimble/ext/tinycrypt/src/ecc_dsa.c" + "./nimble/ext/tinycrypt/src/cmac_mode.c" + "./nimble/ext/tinycrypt/src/ecc_dh.c" + "./nimble/ext/tinycrypt/src/hmac_prng.c" + "./nimble/ext/tinycrypt/src/ecc_platform_specific.c" + "./nimble/ext/tinycrypt/src/hmac.c" + "./nimble/ext/tinycrypt/src/cbc_mode.c" + "./nimble/nimble/host/util/src/addr.c" + "./nimble/nimble/host/services/gatt/src/ble_svc_gatt.c" + "./nimble/nimble/host/services/tps/src/ble_svc_tps.c" + "./nimble/nimble/host/services/ias/src/ble_svc_ias.c" + "./nimble/nimble/host/services/ans/src/ble_svc_ans.c" + "./nimble/nimble/host/services/gap/src/ble_svc_gap.c" + "./nimble/nimble/host/services/bas/src/ble_svc_bas.c" + "./nimble/nimble/host/services/lls/src/ble_svc_lls.c" + "./nimble/nimble/host/src/ble_hs_conn.c" + "./nimble/nimble/host/src/ble_store_util.c" + "./nimble/nimble/host/src/ble_sm.c" + "./nimble/nimble/host/src/ble_hs_shutdown.c" + "./nimble/nimble/host/src/ble_l2cap_sig_cmd.c" + "./nimble/nimble/host/src/ble_hs_hci_cmd.c" + "./nimble/nimble/host/src/ble_hs_id.c" + "./nimble/nimble/host/src/ble_att_svr.c" + "./nimble/nimble/host/src/ble_gatts_lcl.c" + "./nimble/nimble/host/src/ble_ibeacon.c" + "./nimble/nimble/host/src/ble_hs_atomic.c" + "./nimble/nimble/host/src/ble_sm_alg.c" + "./nimble/nimble/host/src/ble_hs_stop.c" + "./nimble/nimble/host/src/ble_hs.c" + "./nimble/nimble/host/src/ble_hs_hci_evt.c" + "./nimble/nimble/host/src/ble_hs_dbg.c" + "./nimble/nimble/host/src/ble_hs_mqueue.c" + "./nimble/nimble/host/src/ble_att.c" + "./nimble/nimble/host/src/ble_gattc.c" + "./nimble/nimble/host/src/ble_store.c" + "./nimble/nimble/host/src/ble_sm_lgcy.c" + "./nimble/nimble/host/src/ble_hs_cfg.c" + "./nimble/nimble/host/src/ble_monitor.c" + "./nimble/nimble/host/src/ble_att_clt.c" + "./nimble/nimble/host/src/ble_l2cap_coc.c" + "./nimble/nimble/host/src/ble_hs_mbuf.c" + "./nimble/nimble/host/src/ble_att_cmd.c" + "./nimble/nimble/host/src/ble_hs_log.c" + "./nimble/nimble/host/src/ble_eddystone.c" + "./nimble/nimble/host/src/ble_hs_startup.c" + "./nimble/nimble/host/src/ble_l2cap_sig.c" + "./nimble/nimble/host/src/ble_gap.c" + "./nimble/nimble/host/src/ble_sm_cmd.c" + "./nimble/nimble/host/src/ble_uuid.c" + "./nimble/nimble/host/src/ble_hs_pvcy.c" + "./nimble/nimble/host/src/ble_hs_flow.c" + "./nimble/nimble/host/src/ble_l2cap.c" + "./nimble/nimble/host/src/ble_sm_sc.c" + "./nimble/nimble/host/src/ble_hs_misc.c" + "./nimble/nimble/host/src/ble_gatts.c" + "./nimble/nimble/host/src/ble_hs_adv.c" + "./nimble/nimble/host/src/ble_hs_hci.c" + "./nimble/nimble/host/src/ble_hs_hci_util.c" + "./nimble/nimble/host/store/ram/src/ble_store_ram.c" + "./nimble/nimble/host/store/config/src/ble_store_config.c" + "./nimble/nimble/host/store/config/src/ble_store_nvs.c" + "./nimble/nimble/src/ble_util.c" + "./nimble/porting/npl/freertos/src/nimble_port_freertos.c" + "./nimble/porting/npl/freertos/src/npl_os_freertos.c" + "./nimble/porting/nimble/src/endian.c" + "./nimble/porting/nimble/src/os_cputime_pwr2.c" + "./nimble/porting/nimble/src/hal_timer.c" + "./nimble/porting/nimble/src/os_mempool.c" + "./nimble/porting/nimble/src/os_msys_init.c" + "./nimble/porting/nimble/src/nimble_port.c" + "./nimble/porting/nimble/src/mem.c" + "./nimble/porting/nimble/src/os_mbuf.c" + "./nimble/porting/nimble/src/os_cputime.c" + "./esp-hci/src/esp_nimble_hci.c") + + if(CONFIG_BT_NIMBLE_MESH) + + list(APPEND COMPONENT_ADD_INCLUDEDIRS + nimble/nimble/host/mesh/include) + + list(APPEND COMPONENT_SRCS + "./nimble/nimble/host/mesh/src/shell.c" + "./nimble/nimble/host/mesh/src/friend.c" + "./nimble/nimble/host/mesh/src/crypto.c" + "./nimble/nimble/host/mesh/src/settings.c" + "./nimble/nimble/host/mesh/src/adv.c" + "./nimble/nimble/host/mesh/src/model_srv.c" + "./nimble/nimble/host/mesh/src/beacon.c" + "./nimble/nimble/host/mesh/src/glue.c" + "./nimble/nimble/host/mesh/src/model_cli.c" + "./nimble/nimble/host/mesh/src/transport.c" + "./nimble/nimble/host/mesh/src/prov.c" + "./nimble/nimble/host/mesh/src/mesh.c" + "./nimble/nimble/host/mesh/src/access.c" + "./nimble/nimble/host/mesh/src/cfg_srv.c" + "./nimble/nimble/host/mesh/src/cfg_cli.c" + "./nimble/nimble/host/mesh/src/light_model.c" + "./nimble/nimble/host/mesh/src/health_cli.c" + "./nimble/nimble/host/mesh/src/lpn.c" + "./nimble/nimble/host/mesh/src/proxy.c" + "./nimble/nimble/host/mesh/src/health_srv.c" + "./nimble/nimble/host/mesh/src/testing.c" + "./nimble/nimble/host/mesh/src/net.c") + + endif() +endif() + +# requirements can't depend on config +set(COMPONENT_PRIV_REQUIRES bt nvs_flash) + +register_component() diff --git a/components/nimble/Kconfig.in b/components/nimble/Kconfig.in new file mode 100644 index 000000000..24d969e74 --- /dev/null +++ b/components/nimble/Kconfig.in @@ -0,0 +1,238 @@ + +config BT_NIMBLE_MAX_CONNECTIONS + int "Maximum number of concurrent connections" + range 1 10 + default 1 + depends on BT_NIMBLE_ENABLED + help + Defines maximum number of concurrent BLE connections + +config BT_NIMBLE_L2CAP_COC_MAX_NUM + int "Maximum number of connection oriented channels" + range 0 10 + depends on BT_NIMBLE_ENABLED + default 0 + help + Defines maximum number of BLE Connection Oriented Channels. When set to (0), BLE COC is not compiled in + +choice BT_NIMBLE_PINNED_TO_CORE_CHOICE + prompt "The CPU core on which NimBLE host will run" + depends on BT_NIMBLE_ENABLED && !FREERTOS_UNICORE + help + The CPU core on which NimBLE host will run. You can choose Core 0 or Core 1. + Cannot specify no-affinity + + config BT_NIMBLE_PINNED_TO_CORE_0 + bool "Core 0 (PRO CPU)" + config BT_NIMBLE_PINNED_TO_CORE_1 + bool "Core 1 (APP CPU)" + depends on !FREERTOS_UNICORE +endchoice + +config BT_NIMBLE_PINNED_TO_CORE + int + depends on BT_NIMBLE_ENABLED + default 0 if BT_NIMBLE_PINNED_TO_CORE_0 + default 1 if BT_NIMBLE_PINNED_TO_CORE_1 + default 0 + +config BT_NIMBLE_ROLE_CENTRAL + bool "Enable BLE Central role" + depends on BT_NIMBLE_ENABLED + default y + +config BT_NIMBLE_ROLE_PERIPHERAL + bool "Enable BLE Peripheral role" + depends on BT_NIMBLE_ENABLED + default y + +config BT_NIMBLE_ROLE_BROADCASTER + bool "Enable BLE Broadcaster role" + depends on BT_NIMBLE_ENABLED + default y + +config BT_NIMBLE_ROLE_OBSERVER + bool "Enable BLE Observer role" + depends on BT_NIMBLE_ENABLED + default y + +config BT_NIMBLE_NVS_PERSIST + bool "Persist the BLE Bonding keys in NVS" + depends on BT_NIMBLE_ENABLED + default y + help + Enable this flag to make bonding persistent across device reboots + +config BT_NIMBLE_SM_LEGACY + bool "Security manager legacy pairing" + depends on BT_NIMBLE_ENABLED + default y + help + Enable security manager legacy pairing + +config BT_NIMBLE_SM_SC + bool "Security manager secure connections (4.2)" + depends on BT_NIMBLE_ENABLED + default y + help + Enable security manager secure connections + +config BT_NIMBLE_DEBUG + bool "Enable host debugging" + default n + depends on BT_NIMBLE_ENABLED + help + This enables extra runtime assertions + +config BT_NIMBLE_SVC_GAP_DEVICE_NAME + string "BLE GAP default device name" + depends on BT_NIMBLE_ENABLED + default "nimble" + help + The Device Name characteristic shall contain the name of the device as an UTF-8 string. + This name can be changed by using API ble_svc_gap_device_name_set() + +config BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN + int "Maximum length of BLE device name in octets" + depends on BT_NIMBLE_ENABLED + default 31 + help + Device Name characteristic value shall be 0 to 248 octets in length + +config BT_NIMBLE_ATT_PREFERRED_MTU + int "Preferred MTU size in octets" + depends on BT_NIMBLE_ENABLED + default 256 + help + This is the default value of ATT MTU indicated by the device during an ATT MTU exchange. + This value can be changed using API ble_att_set_preferred_mtu() + +config BT_NIMBLE_SVC_GAP_APPEARANCE + hex "External appearance of the device" + depends on BT_NIMBLE_ENABLED + default 0 + help + Standard BLE GAP Appearance value in HEX format e.g. 0x02C0 + +config BT_NIMBLE_ACL_BUF_COUNT + int "ACL Buffer count" + depends on BT_NIMBLE_ENABLED + default 12 + help + The number of ACL data buffers. + +config BT_NIMBLE_ACL_BUF_SIZE + int "ACL Buffer size" + depends on BT_NIMBLE_ENABLED + default 255 + help + This is the maximum size of the data portion of HCI ACL data packets. + It does not include the HCI data header (of 4 bytes) + +config BT_NIMBLE_HCI_EVT_BUF_SIZE + int "HCI Event Buffer size" + depends on BT_NIMBLE_ENABLED + default 70 + help + This is the size of each HCI event buffer in bytes + +config BT_NIMBLE_HCI_EVT_HI_BUF_COUNT + int "High Priority HCI Event Buffer count" + depends on BT_NIMBLE_ENABLED + default 30 + help + This is the high priority HCI events' buffer size. High-priority + event buffers are for everything except advertising reports. If there + are no free high-priority event buffers then host will try to allocate a + low-priority buffer instead + +config BT_NIMBLE_HCI_EVT_LO_BUF_COUNT + int "Low Priority HCI Event Buffer count" + depends on BT_NIMBLE_ENABLED + default 8 + help + This is the low priority HCI events' buffer size. Low-priority event + buffers are only used for advertising reports. If there are no free + low-priority event buffers, then an incoming advertising report will + get dropped + +menuconfig BT_NIMBLE_MESH + bool "Enable BLE mesh functionality" + select BT_NIMBLE_SM_SC + depends on BT_NIMBLE_ENABLED + default n + help + Enable BLE Mesh functionality + +config BT_NIMBLE_MESH_PROXY + bool "Enable mesh proxy functionality" + default n + depends on BT_NIMBLE_MESH + help + Enable proxy. This is automatically set whenever NIMBLE_MESH_PB_GATT or + NIMBLE_MESH_GATT_PROXY is set + + +config BT_NIMBLE_MESH_PROV + bool "Enable BLE mesh provisioning" + default y + depends on BT_NIMBLE_MESH + help + Enable mesh provisioning + +config BT_NIMBLE_MESH_PB_ADV + bool "Enable mesh provisioning over advertising bearer" + default y + depends on BT_NIMBLE_MESH_PROV + help + Enable this option to allow the device to be provisioned over + the advertising bearer + + +config BT_NIMBLE_MESH_PB_GATT + bool "Enable mesh provisioning over GATT bearer" + default y + select BT_NIMBLE_MESH_PROXY + depends on BT_NIMBLE_MESH_PROV + help + Enable this option to allow the device to be provisioned over the GATT + bearer + +config BT_NIMBLE_MESH_GATT_PROXY + bool "Enable GATT Proxy functionality" + default y + select BT_NIMBLE_MESH_PROXY + depends on BT_NIMBLE_MESH + help + This option enables support for the Mesh GATT Proxy Service, + i.e. the ability to act as a proxy between a Mesh GATT Client + and a Mesh network + +config BT_NIMBLE_MESH_RELAY + bool "Enable mesh relay functionality" + default n + depends on BT_NIMBLE_MESH + help + Support for acting as a Mesh Relay Node + +config BT_NIMBLE_MESH_LOW_POWER + bool "Enable mesh low power mode" + default n + depends on BT_NIMBLE_MESH + help + Enable this option to be able to act as a Low Power Node + +config BT_NIMBLE_MESH_FRIEND + bool "Enable mesh friend functionality" + default n + depends on BT_NIMBLE_MESH + help + Enable this option to be able to act as a Friend Node + +config BT_NIMBLE_MESH_DEVICE_NAME + string "Set mesh device name" + default "nimble-mesh-node" + depends on BT_NIMBLE_MESH + help + This value defines Bluetooth Mesh device/node name + diff --git a/components/nimble/component.mk b/components/nimble/component.mk new file mode 100644 index 000000000..148e13d67 --- /dev/null +++ b/components/nimble/component.mk @@ -0,0 +1,47 @@ +# +# Component Makefile +# + +ifeq ($(CONFIG_BT_NIMBLE_ENABLED),y) +COMPONENT_ADD_INCLUDEDIRS := nimble/nimble/include \ + nimble/nimble/host/include \ + nimble/porting/nimble/include \ + nimble/porting/npl/freertos/include \ + nimble/nimble/host/services/ans/include \ + nimble/nimble/host/services/bas/include \ + nimble/nimble/host/services/gap/include \ + nimble/nimble/host/services/gatt/include \ + nimble/nimble/host/services/ias/include \ + nimble/nimble/host/services/lls/include \ + nimble/nimble/host/services/tps/include \ + nimble/nimble/host/util/include \ + nimble/nimble/host/store/ram/include \ + nimble/nimble/host/store/config/include \ + nimble/nimble/host/mesh/include \ + nimble/ext/tinycrypt/include \ + esp-hci/include \ + port/include \ + + +COMPONENT_SRCDIRS := nimble/nimble/host/src \ + nimble/porting/nimble/src \ + nimble/porting/npl/freertos/src \ + nimble/ext/tinycrypt/src \ + nimble/nimble/host/services/ans/src \ + nimble/nimble/host/services/bas/src \ + nimble/nimble/host/services/gap/src \ + nimble/nimble/host/services/gatt/src \ + nimble/nimble/host/services/ias/src \ + nimble/nimble/host/services/lls/src \ + nimble/nimble/host/services/tps/src \ + nimble/nimble/host/util/src \ + nimble/nimble/host/store/ram/src \ + nimble/nimble/host/store/config/src \ + esp-hci/src \ + +COMPONENT_OBJEXCLUDE := nimble/nimble/host/store/config/src/ble_store_config_conf.o + +ifeq ($(CONFIG_BT_NIMBLE_MESH),y) +COMPONENT_SRCDIRS += nimble/nimble/host/mesh/src +endif +endif diff --git a/components/nimble/esp-hci/include/esp_nimble_hci.h b/components/nimble/esp-hci/include/esp_nimble_hci.h new file mode 100644 index 000000000..e10436f3c --- /dev/null +++ b/components/nimble/esp-hci/include/esp_nimble_hci.h @@ -0,0 +1,138 @@ +/* + * Copyright 2019 Espressif Systems (Shanghai) PTE LTD + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __ESP_NIMBLE_HCI_H__ +#define __ESP_NIMBLE_HCI_H__ + +#include "nimble/ble_hci_trans.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define BLE_HCI_UART_H4_NONE 0x00 +#define BLE_HCI_UART_H4_CMD 0x01 +#define BLE_HCI_UART_H4_ACL 0x02 +#define BLE_HCI_UART_H4_SCO 0x03 +#define BLE_HCI_UART_H4_EVT 0x04 + +/** + * @brief Initialize VHCI transport layer between NimBLE Host and + * ESP Bluetooth controller + * + * This function initializes the transport buffers to be exchanged + * between NimBLE host and ESP controller. It also registers required + * host callbacks with the controller. + * + * @return + * - ESP_OK if the initialization is successful + * - Appropriate error code from esp_err_t in case of an error + */ +esp_err_t esp_nimble_hci_init(void); + +/** + * @brief Initialize ESP Bluetooth controller(link layer) and VHCI transport + * layer between NimBLE Host and ESP Bluetooth controller + * + * This function initializes ESP controller in BLE only mode and the + * transport buffers to be exchanged between NimBLE host and ESP controller. + * It also registers required host callbacks with the controller. + * + * Below is the sequence of APIs to be called to init/enable NimBLE host and ESP controller: + * + * @code{c} + * void ble_host_task(void *param) + * { + * nimble_port_run(); //This function will return only when nimble_port_stop() is executed. + * nimble_port_freertos_deinit(); + * } + * + * int ret = esp_nimble_hci_and_controller_init(); + * if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_nimble_hci_and_controller_init() failed with error: %d", ret); + * return; + * } + * + * nimble_port_init(); + * + * //Initialize the NimBLE Host configuration + * + * nimble_port_freertos_init(ble_host_task); + * @endcode + * + * nimble_port_freertos_init() is an optional call that creates a new task in which the NimBLE + * host will run. The task function should have a call to nimble_port_run(). If a separate task + * is not required, calling nimble_port_run() will run the NimBLE host in the current task. + * + * @return + * - ESP_OK if the initialization is successful + * - Appropriate error code from esp_err_t in case of an error + */ +esp_err_t esp_nimble_hci_and_controller_init(void); + +/** + * @brief Deinitialize VHCI transport layer between NimBLE Host and + * ESP Bluetooth controller + * + * @note This function should be called after the NimBLE host is deinitialized. + * + * @return + * - ESP_OK if the deinitialization is successful + * - Appropriate error codes from esp_err_t in case of an error + */ +esp_err_t esp_nimble_hci_deinit(void); + +/** + * @brief Deinitialize VHCI transport layer between NimBLE Host and + * ESP Bluetooth controller and disable and deinitialize the controller + * + * @note This function should not be executed in the context of Bluetooth host task. + * + * @note This function should be called after the NimBLE host is deinitialized. + * + * Below is the sequence of APIs to be called to disable/deinit NimBLE host and ESP controller: + * + * @code{c} + * int ret = nimble_port_stop(); + * if (ret == 0) { + * nimble_port_deinit(); + * + * ret = esp_nimble_hci_and_controller_deinit(); + * if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret); + * } + * } + * @endcode + * + * If nimble_port_freertos_init() is used during initialization, then + * nimble_port_freertos_deinit() should be called in the host task after nimble_port_run(). + * + * @return + * - ESP_OK if the deinitialization is successful + * - Appropriate error codes from esp_err_t in case of an error + */ +esp_err_t esp_nimble_hci_and_controller_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_NIMBLE_HCI_H__ */ diff --git a/components/nimble/esp-hci/src/esp_nimble_hci.c b/components/nimble/esp-hci/src/esp_nimble_hci.c new file mode 100644 index 000000000..545334e92 --- /dev/null +++ b/components/nimble/esp-hci/src/esp_nimble_hci.c @@ -0,0 +1,434 @@ +/* + * Copyright 2019 Espressif Systems (Shanghai) PTE LTD + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "sysinit/sysinit.h" +#include "nimble/hci_common.h" +#include "host/ble_hs.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "esp_nimble_hci.h" +#include "esp_bt.h" + +static ble_hci_trans_rx_cmd_fn *ble_hci_rx_cmd_hs_cb; +static void *ble_hci_rx_cmd_hs_arg; + +static ble_hci_trans_rx_acl_fn *ble_hci_rx_acl_hs_cb; +static void *ble_hci_rx_acl_hs_arg; + +static struct os_mbuf_pool ble_hci_acl_mbuf_pool; +static struct os_mempool_ext ble_hci_acl_pool; +/* + * The MBUF payload size must accommodate the HCI data header size plus the + * maximum ACL data packet length. The ACL block size is the size of the + * mbufs we will allocate. + */ +#define ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \ + + BLE_MBUF_MEMBLOCK_OVERHEAD \ + + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT) + +static os_membuf_t ble_hci_acl_buf[ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT), + ACL_BLOCK_SIZE)]; + +static struct os_mempool ble_hci_cmd_pool; +static os_membuf_t ble_hci_cmd_buf[ + OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ) +]; + +static struct os_mempool ble_hci_evt_hi_pool; +static os_membuf_t ble_hci_evt_hi_buf[ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) +]; + +static struct os_mempool ble_hci_evt_lo_pool; +static os_membuf_t ble_hci_evt_lo_buf[ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) +]; + +void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, + void *cmd_arg, + ble_hci_trans_rx_acl_fn *acl_cb, + void *acl_arg) +{ + ble_hci_rx_cmd_hs_cb = cmd_cb; + ble_hci_rx_cmd_hs_arg = cmd_arg; + ble_hci_rx_acl_hs_cb = acl_cb; + ble_hci_rx_acl_hs_arg = acl_arg; +} + + +int ble_hci_trans_hs_cmd_tx(uint8_t *cmd) +{ + uint16_t len; + + assert(cmd != NULL); + *cmd = BLE_HCI_UART_H4_CMD; + len = BLE_HCI_CMD_HDR_LEN + cmd[3] + 1; + while (!esp_vhci_host_check_send_available()) { + } + esp_vhci_host_send_packet(cmd, len); + + ble_hci_trans_buf_free(cmd); + return 0; +} + +int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev) +{ + int rc = ESP_FAIL; + + if (ble_hci_rx_cmd_hs_cb) { + rc = ble_hci_rx_cmd_hs_cb(hci_ev, ble_hci_rx_cmd_hs_arg); + } + return rc; +} + +int ble_hci_trans_hs_acl_tx(struct os_mbuf *om) +{ + uint16_t len = 0; + uint8_t data[MYNEWT_VAL(BLE_ACL_BUF_SIZE) + 1]; + /* If this packet is zero length, just free it */ + if (OS_MBUF_PKTLEN(om) == 0) { + os_mbuf_free_chain(om); + return 0; + } + data[0] = BLE_HCI_UART_H4_ACL; + len++; + + while (!esp_vhci_host_check_send_available()) { + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + + os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]); + len += OS_MBUF_PKTLEN(om); + + esp_vhci_host_send_packet(data, len); + + os_mbuf_free_chain(om); + + return 0; +} + +int ble_hci_trans_ll_acl_tx(struct os_mbuf *om) +{ + int rc = ESP_FAIL; + + if (ble_hci_rx_acl_hs_cb) { + rc = ble_hci_rx_acl_hs_cb(om, ble_hci_rx_acl_hs_arg); + } + return rc; +} + +uint8_t *ble_hci_trans_buf_alloc(int type) +{ + uint8_t *buf; + + switch (type) { + case BLE_HCI_TRANS_BUF_CMD: + buf = os_memblock_get(&ble_hci_cmd_pool); + break; + + case BLE_HCI_TRANS_BUF_EVT_HI: + buf = os_memblock_get(&ble_hci_evt_hi_pool); + if (buf == NULL) { + /* If no high-priority event buffers remain, try to grab a + * low-priority one. + */ + buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + } + break; + + case BLE_HCI_TRANS_BUF_EVT_LO: + buf = os_memblock_get(&ble_hci_evt_lo_pool); + break; + + default: + assert(0); + buf = NULL; + } + + return buf; +} + +void ble_hci_trans_buf_free(uint8_t *buf) +{ + int rc; + /* XXX: this may look a bit odd, but the controller uses the command + * buffer to send back the command complete/status as an immediate + * response to the command. This was done to insure that the controller + * could always send back one of these events when a command was received. + * Thus, we check to see which pool the buffer came from so we can free + * it to the appropriate pool + */ + if (os_memblock_from(&ble_hci_evt_hi_pool, buf)) { + rc = os_memblock_put(&ble_hci_evt_hi_pool, buf); + assert(rc == 0); + } else if (os_memblock_from(&ble_hci_evt_lo_pool, buf)) { + rc = os_memblock_put(&ble_hci_evt_lo_pool, buf); + assert(rc == 0); + } else { + assert(os_memblock_from(&ble_hci_cmd_pool, buf)); + rc = os_memblock_put(&ble_hci_cmd_pool, buf); + assert(rc == 0); + } +} + +/** + * Unsupported; the RAM transport does not have a dedicated ACL data packet + * pool. + */ +int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg) +{ + return BLE_ERR_UNSUPPORTED; +} + +int ble_hci_trans_reset(void) +{ + /* No work to do. All allocated buffers are owned by the host or + * controller, and they will get freed by their owners. + */ + return 0; +} + +/** + * Allocates a buffer (mbuf) for ACL operation. + * + * @return The allocated buffer on success; + * NULL on buffer exhaustion. + */ +static struct os_mbuf *ble_hci_trans_acl_buf_alloc(void) +{ + struct os_mbuf *m; + uint8_t usrhdr_len; + +#if MYNEWT_VAL(BLE_DEVICE) + usrhdr_len = sizeof(struct ble_mbuf_hdr); +#elif MYNEWT_VAL(BLE_HS_FLOW_CTRL) + usrhdr_len = BLE_MBUF_HS_HDR_LEN; +#else + usrhdr_len = 0; +#endif + + m = os_mbuf_get_pkthdr(&ble_hci_acl_mbuf_pool, usrhdr_len); + return m; +} + +static void ble_hci_rx_acl(uint8_t *data, uint16_t len) +{ + struct os_mbuf *m; + int sr; + if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) { + return; + } + + m = ble_hci_trans_acl_buf_alloc(); + + if (!m) { + return; + } + if (os_mbuf_append(m, data, len)) { + os_mbuf_free_chain(m); + return; + } + OS_ENTER_CRITICAL(sr); + if (ble_hci_rx_acl_hs_cb) { + ble_hci_rx_acl_hs_cb(m, NULL); + } + OS_EXIT_CRITICAL(sr); +} + +static void ble_hci_transport_init(void) +{ + int rc; + + /* Ensure this function only gets called by sysinit. */ + SYSINIT_ASSERT_ACTIVE(); + + rc = os_mempool_ext_init(&ble_hci_acl_pool, + MYNEWT_VAL(BLE_ACL_BUF_COUNT), + ACL_BLOCK_SIZE, + ble_hci_acl_buf, + "ble_hci_acl_pool"); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mbuf_pool_init(&ble_hci_acl_mbuf_pool, + &ble_hci_acl_pool.mpe_mp, + ACL_BLOCK_SIZE, + MYNEWT_VAL(BLE_ACL_BUF_COUNT)); + SYSINIT_PANIC_ASSERT(rc == 0); + + /* + * Create memory pool of HCI command buffers. NOTE: we currently dont + * allow this to be configured. The controller will only allow one + * outstanding command. We decided to keep this a pool in case we allow + * allow the controller to handle more than one outstanding command. + */ + rc = os_mempool_init(&ble_hci_cmd_pool, + 1, + BLE_HCI_TRANS_CMD_SZ, + ble_hci_cmd_buf, + "ble_hci_cmd_pool"); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mempool_init(&ble_hci_evt_hi_pool, + MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE), + ble_hci_evt_hi_buf, + "ble_hci_evt_hi_pool"); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mempool_init(&ble_hci_evt_lo_pool, + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), + MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE), + ble_hci_evt_lo_buf, + "ble_hci_evt_lo_pool"); + SYSINIT_PANIC_ASSERT(rc == 0); +} + +/* + * @brief: BT controller callback function, used to notify the upper layer that + * controller is ready to receive command + */ +static void controller_rcv_pkt_ready(void) +{ +} + +/* + * @brief: BT controller callback function, to transfer data packet to the host + */ +static int host_rcv_pkt(uint8_t *data, uint16_t len) +{ + + if (data[0] == BLE_HCI_UART_H4_EVT) { + uint8_t *evbuf; + int totlen; + int rc; + + totlen = BLE_HCI_EVENT_HDR_LEN + data[2]; + assert(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN); + + if (data[1] == BLE_HCI_EVCODE_HW_ERROR) { + assert(0); + } + + /* Allocate LE Advertising Report Event from lo pool only */ + if ((data[1] == BLE_HCI_EVCODE_LE_META) && (data[3] == BLE_HCI_LE_SUBEV_ADV_RPT)) { + evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO); + /* Skip advertising report if we're out of memory */ + if (!evbuf) { + return 0; + } + } else { + evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI); + assert(evbuf != NULL); + } + + memcpy(evbuf, &data[1], totlen); + + rc = ble_hci_trans_ll_evt_tx(evbuf); + assert(rc == 0); + } else if (data[0] == BLE_HCI_UART_H4_ACL) { + ble_hci_rx_acl(data + 1, len - 1); + } + return 0; +} + +static esp_vhci_host_callback_t vhci_host_cb = { + controller_rcv_pkt_ready, + host_rcv_pkt +}; + +esp_err_t esp_nimble_hci_init(void) +{ + esp_err_t ret; + if ((ret = esp_vhci_host_register_callback(&vhci_host_cb)) != ESP_OK) { + return ret; + } + + ble_hci_transport_init(); + + return ESP_OK; +} + +esp_err_t esp_nimble_hci_and_controller_init(void) +{ + esp_err_t ret; + + esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + + if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { + return ret; + } + + if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) { + return ret; + } + return esp_nimble_hci_init(); +} + +static esp_err_t ble_hci_transport_deinit(void) +{ + int ret = 0; + + ret += os_mempool_clear(&ble_hci_evt_lo_pool); + + ret += os_mempool_clear(&ble_hci_evt_hi_pool); + + ret += os_mempool_clear(&ble_hci_cmd_pool); + + ret += os_mempool_ext_clear(&ble_hci_acl_pool); + + if (ret) { + return ESP_FAIL; + } else { + return ESP_OK; + } +} + +esp_err_t esp_nimble_hci_deinit(void) +{ + return ble_hci_transport_deinit(); +} + +esp_err_t esp_nimble_hci_and_controller_deinit(void) +{ + int ret; + ret = esp_nimble_hci_deinit(); + if (ret != ESP_OK) { + return ret; + } + + ret = esp_bt_controller_disable(); + if (ret != ESP_OK) { + return ret; + } + + ret = esp_bt_controller_deinit(); + if (ret != ESP_OK) { + return ret; + } + + return ESP_OK; +} diff --git a/components/nimble/nimble b/components/nimble/nimble new file mode 160000 index 000000000..4f96f4cc3 --- /dev/null +++ b/components/nimble/nimble @@ -0,0 +1 @@ +Subproject commit 4f96f4cc351dd5bff2310b311285a89f73104bb6 diff --git a/components/nimble/port/include/console/console.h b/components/nimble/port/include/console/console.h new file mode 100644 index 000000000..96f965159 --- /dev/null +++ b/components/nimble/port/include/console/console.h @@ -0,0 +1,21 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +//Licensed 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 _CONSOLE_H +#define _CONSOLE_H + +#include + +#define console_printf printf + +#endif diff --git a/components/nimble/port/include/esp_nimble_cfg.h b/components/nimble/port/include/esp_nimble_cfg.h new file mode 100644 index 000000000..5208f733d --- /dev/null +++ b/components/nimble/port/include/esp_nimble_cfg.h @@ -0,0 +1,1065 @@ + +#ifndef __ESP_NIMBLE_CFG__ +#define __ESP_NIMBLE_CFG__ +#include "sdkconfig.h" + +/** + * This macro exists to ensure code includes this header when needed. If code + * checks the existence of a setting directly via ifdef without including this + * header, the setting macro will silently evaluate to 0. In contrast, an + * attempt to use these macros without including this header will result in a + * compiler error. + */ +#define MYNEWT_VAL(x) MYNEWT_VAL_ ## x + +/*** kernel/os */ +#ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT +#ifdef CONFIG_BT_NIMBLE_MESH +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (20) +#else +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12) +#endif +#endif + +#ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE +#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292) +#endif + +#ifndef MYNEWT_VAL_MSYS_2_BLOCK_COUNT +#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0) +#endif + +#ifndef MYNEWT_VAL_MSYS_2_BLOCK_SIZE +#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0) +#endif + +#ifndef MYNEWT_VAL_OS_CPUTIME_FREQ +#define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) +#endif + +#ifndef MYNEWT_VAL_OS_CPUTIME_TIMER_NUM +#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) +#endif + +/*** nimble */ +#ifndef MYNEWT_VAL_BLE_EXT_ADV +#define MYNEWT_VAL_BLE_EXT_ADV (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE +#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) +#endif + +#ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS +#define MYNEWT_VAL_BLE_MAX_CONNECTIONS CONFIG_BT_NIMBLE_MAX_CONNECTIONS +#endif + +#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES +#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0) +#endif + +#ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER +#ifdef CONFIG_BT_NIMBLE_ROLE_BROADCASTER +#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1) +#else +#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_ROLE_CENTRAL +#ifdef CONFIG_BT_NIMBLE_ROLE_CENTRAL +#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1) +#else +#define MYNEWT_VAL_BLE_ROLE_CENTRAL (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_ROLE_OBSERVER +#ifdef CONFIG_BT_NIMBLE_ROLE_OBSERVER +#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1) +#else +#define MYNEWT_VAL_BLE_ROLE_OBSERVER (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_ROLE_PERIPHERAL +#ifdef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL +#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1) +#else +#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_WHITELIST +#define MYNEWT_VAL_BLE_WHITELIST (1) +#endif + +/*** @apache-mynewt-nimble/nimble/controller */ +#ifndef MYNEWT_VAL_BLE_DEVICE +#define MYNEWT_VAL_BLE_DEVICE (0) +#endif + +/* Overridden by @apache-mynewt-nimble/nimble/controller (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE +#define MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS +#define MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_EXT_SCAN_FILT +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_EXT_SCAN_FILT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY (0) +#endif + +/* Overridden by @apache-mynewt-nimble/nimble/controller (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2 +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2 (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_PING +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_PING (MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV (MYNEWT_VAL_BLE_EXT_ADV) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES +#define MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES (27) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MIN_WIN_OFFSET +#define MYNEWT_VAL_BLE_LL_CONN_INIT_MIN_WIN_OFFSET (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS +#define MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS (4) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DIRECT_TEST_MODE +#define MYNEWT_VAL_BLE_LL_DIRECT_TEST_MODE (0) +#endif + +/* Overridden by @apache-mynewt-nimble/nimble/controller (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_EXT_ADV_AUX_PTR_CNT +#define MYNEWT_VAL_BLE_LL_EXT_ADV_AUX_PTR_CNT (5) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_MASTER_SCA +#define MYNEWT_VAL_BLE_LL_MASTER_SCA (4) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE +#define MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE (251) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_MFRG_ID +#define MYNEWT_VAL_BLE_LL_MFRG_ID (0xFFFF) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_NUM_SCAN_DUP_ADVS +#define MYNEWT_VAL_BLE_LL_NUM_SCAN_DUP_ADVS (8) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_NUM_SCAN_RSP_ADVS +#define MYNEWT_VAL_BLE_LL_NUM_SCAN_RSP_ADVS (8) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_OUR_SCA +#define MYNEWT_VAL_BLE_LL_OUR_SCA (60) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_PRIO +#define MYNEWT_VAL_BLE_LL_PRIO (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_RESOLV_LIST_SIZE +#define MYNEWT_VAL_BLE_LL_RESOLV_LIST_SIZE (4) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_RNG_BUFSIZE +#define MYNEWT_VAL_BLE_LL_RNG_BUFSIZE (32) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING +#define MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SUPP_MAX_RX_BYTES +#define MYNEWT_VAL_BLE_LL_SUPP_MAX_RX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SUPP_MAX_TX_BYTES +#define MYNEWT_VAL_BLE_LL_SUPP_MAX_TX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SYSVIEW +#define MYNEWT_VAL_BLE_LL_SYSVIEW (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_TX_PWR_DBM +#define MYNEWT_VAL_BLE_LL_TX_PWR_DBM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_USECS_PER_PERIOD +#define MYNEWT_VAL_BLE_LL_USECS_PER_PERIOD (3250) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_VND_EVENT_ON_ASSERT +#define MYNEWT_VAL_BLE_LL_VND_EVENT_ON_ASSERT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_WHITELIST_SIZE +#define MYNEWT_VAL_BLE_LL_WHITELIST_SIZE (8) +#endif + +#ifndef MYNEWT_VAL_BLE_LP_CLOCK +#define MYNEWT_VAL_BLE_LP_CLOCK (1) +#endif + +#ifndef MYNEWT_VAL_BLE_NUM_COMP_PKT_RATE +#define MYNEWT_VAL_BLE_NUM_COMP_PKT_RATE ((2 * OS_TICKS_PER_SEC)) +#endif + +#ifndef MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR +#define MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR ((uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +#endif + +#ifndef MYNEWT_VAL_BLE_XTAL_SETTLE_TIME +#define MYNEWT_VAL_BLE_XTAL_SETTLE_TIME (0) +#endif + +/*** @apache-mynewt-nimble/nimble/host */ +#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU +#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO +#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE +#define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_INDICATE +#define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES +#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE +#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO +#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ +#define MYNEWT_VAL_BLE_ATT_SVR_READ (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB +#define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE +#define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_MULT +#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE +#define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE +#define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE +#define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP +#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) +#endif + +#ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE +#define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID +#define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID +#define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS +#define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_INDICATE +#define MYNEWT_VAL_BLE_GATT_INDICATE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_MAX_PROCS +#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY +#define MYNEWT_VAL_BLE_GATT_NOTIFY (1) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ +#define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_LONG +#define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS +#define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT +#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID +#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_RESUME_RATE +#define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_SIGNED_WRITE +#define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE +#define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE_LONG +#define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS +#define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP +#define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE +#define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_HOST +#define MYNEWT_VAL_BLE_HOST (1) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_DEBUG +#ifdef CONFIG_BT_NIMBLE_DEBUG +#define MYNEWT_VAL_BLE_HS_DEBUG (1) +#else +#define MYNEWT_VAL_BLE_HS_DEBUG (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_HS_AUTO_START +#define MYNEWT_VAL_BLE_HS_AUTO_START (1) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS +#define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_REQUIRE_OS +#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS +#define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_MAX_CHANS +#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT +#define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH +#ifdef CONFIG_BT_NIMBLE_MESH +#define MYNEWT_VAL_BLE_MESH (1) +#else +#define MYNEWT_VAL_BLE_MESH (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT +#define MYNEWT_VAL_BLE_MONITOR_RTT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("monitor") +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART +#define MYNEWT_VAL_BLE_MONITOR_UART (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE +#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_DEV +#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0") +#endif + +#ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT +#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_BONDING +#define MYNEWT_VAL_BLE_SM_BONDING (1) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_IO_CAP +#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_KEYPRESS +#define MYNEWT_VAL_BLE_SM_KEYPRESS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_LEGACY +#ifdef CONFIG_BT_NIMBLE_SM_LEGACY +#define MYNEWT_VAL_BLE_SM_LEGACY (1) +#else +#define MYNEWT_VAL_BLE_SM_LEGACY (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS +#define MYNEWT_VAL_BLE_SM_MAX_PROCS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_MITM +#define MYNEWT_VAL_BLE_SM_MITM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG +#define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST +#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SC +#ifdef CONFIG_BT_NIMBLE_SM_SC +#define MYNEWT_VAL_BLE_SM_SC (1) +#else +#define MYNEWT_VAL_BLE_SM_SC (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST +#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) +#endif + +#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS +#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3) +#endif + +#ifndef MYNEWT_VAL_BLE_STORE_MAX_CCCDS +#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8) +#endif + +#ifndef MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST +#ifdef CONFIG_BT_NIMBLE_NVS_PERSIST +#define MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST (1) +#else +#define MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST (0) +#endif +#endif + +/*** nimble/host/services/ans */ +#ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT +#define MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT (0) +#endif + + +#ifndef MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT +#define MYNEWT_VAL_BLE_SVC_ANS_UNR_ALERT_CAT (0) +#endif + +/*** nimble/host/services/bas */ +#ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE +#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM +#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM (0) +#endif +#ifndef MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO +#define MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO (9) +#endif + + +/*** @apache-mynewt-nimble/nimble/host/mesh */ +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT +#define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (20) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT +#define MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_CFG_CLI +#define MYNEWT_VAL_BLE_MESH_CFG_CLI (0) +#endif +#ifndef MYNEWT_VAL_BLE_MESH_CRPL +#define MYNEWT_VAL_BLE_MESH_CRPL (10) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG +#define MYNEWT_VAL_BLE_MESH_DEBUG (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_ACCESS +#define MYNEWT_VAL_BLE_MESH_DEBUG_ACCESS (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_ADV +#define MYNEWT_VAL_BLE_MESH_DEBUG_ADV (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG +#define MYNEWT_VAL_BLE_MESH_DEBUG (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_ACCESS +#define MYNEWT_VAL_BLE_MESH_DEBUG_ACCESS (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_ADV +#define MYNEWT_VAL_BLE_MESH_DEBUG_ADV (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_BEACON +#define MYNEWT_VAL_BLE_MESH_DEBUG_BEACON (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_CRYPTO +#define MYNEWT_VAL_BLE_MESH_DEBUG_CRYPTO (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_FRIEND +#define MYNEWT_VAL_BLE_MESH_DEBUG_FRIEND (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_LOW_POWER +#define MYNEWT_VAL_BLE_MESH_DEBUG_LOW_POWER (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_MODEL +#define MYNEWT_VAL_BLE_MESH_DEBUG_MODEL (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_NET +#define MYNEWT_VAL_BLE_MESH_DEBUG_NET (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_PROV +#define MYNEWT_VAL_BLE_MESH_DEBUG_PROV (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_PROXY +#define MYNEWT_VAL_BLE_MESH_DEBUG_PROXY (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_SETTINGS +#define MYNEWT_VAL_BLE_MESH_DEBUG_SETTINGS (1) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_TRANS +#define MYNEWT_VAL_BLE_MESH_DEBUG_TRANS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_DEVICE_NAME +#define MYNEWT_VAL_BLE_MESH_DEVICE_NAME CONFIG_BT_NIMBLE_MESH_DEVICE_NAME +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_DEV_UUID +#define MYNEWT_VAL_BLE_MESH_DEV_UUID (((uint8_t[16]){0x11, 0x22, 0})) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_FRIEND +#ifdef CONFIG_BT_NIMBLE_MESH_FRIEND +#define MYNEWT_VAL_BLE_MESH_FRIEND (1) +#else +#define MYNEWT_VAL_BLE_MESH_FRIEND (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_LPN_COUNT +#define MYNEWT_VAL_BLE_MESH_FRIEND_LPN_COUNT (2) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_QUEUE_SIZE +#define MYNEWT_VAL_BLE_MESH_FRIEND_QUEUE_SIZE (16) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_RECV_WIN +#define MYNEWT_VAL_BLE_MESH_FRIEND_RECV_WIN (255) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_SEG_RX +#define MYNEWT_VAL_BLE_MESH_FRIEND_SEG_RX (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_SUB_LIST_SIZE +#define MYNEWT_VAL_BLE_MESH_FRIEND_SUB_LIST_SIZE (3) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY +#ifdef CONFIG_BT_NIMBLE_MESH_GATT_PROXY +#define MYNEWT_VAL_BLE_MESH_GATT_PROXY (1) +#else +#define MYNEWT_VAL_BLE_MESH_GATT_PROXY (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_HEALTH_CLI +#define MYNEWT_VAL_BLE_MESH_HEALTH_CLI (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_IVU_DIVIDER +#define MYNEWT_VAL_BLE_MESH_IVU_DIVIDER (4) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST +#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LABEL_COUNT +#define MYNEWT_VAL_BLE_MESH_LABEL_COUNT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LOW_POWER +#ifdef CONFIG_BT_NIMBLE_MESH_LOW_POWER +#define MYNEWT_VAL_BLE_MESH_LOW_POWER (1) +#else +#define MYNEWT_VAL_BLE_MESH_LOW_POWER (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_AUTO +#define MYNEWT_VAL_BLE_MESH_LPN_AUTO (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_AUTO_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_LPN_AUTO_TIMEOUT (15) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_ESTABLISHMENT +#define MYNEWT_VAL_BLE_MESH_LPN_ESTABLISHMENT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_GROUPS +#define MYNEWT_VAL_BLE_MESH_LPN_GROUPS (10) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT (MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_MIN_QUEUE_SIZE +#define MYNEWT_VAL_BLE_MESH_LPN_MIN_QUEUE_SIZE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT (300) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_RECV_DELAY +#define MYNEWT_VAL_BLE_MESH_LPN_RECV_DELAY (100) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_RECV_WIN_FACTOR +#define MYNEWT_VAL_BLE_MESH_LPN_RECV_WIN_FACTOR (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_RETRY_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_LPN_RETRY_TIMEOUT (8) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_RSSI_FACTOR +#define MYNEWT_VAL_BLE_MESH_LPN_RSSI_FACTOR (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_SCAN_LATENCY +#define MYNEWT_VAL_BLE_MESH_LPN_SCAN_LATENCY (10) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT +#define MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_MODEL_KEY_COUNT +#define MYNEWT_VAL_BLE_MESH_MODEL_KEY_COUNT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE +#define MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE (10) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_NODE_ID_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_NODE_ID_TIMEOUT (60) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_OOB_INPUT_ACTIONS +#define MYNEWT_VAL_BLE_MESH_OOB_INPUT_ACTIONS (((BT_MESH_NO_INPUT))) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_OOB_INPUT_SIZE +#define MYNEWT_VAL_BLE_MESH_OOB_INPUT_SIZE (4) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_ACTIONS +#define MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_ACTIONS (((BT_MESH_DISPLAY_NUMBER))) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_SIZE +#define MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_SIZE (4) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_PB_ADV +#ifdef CONFIG_BT_NIMBLE_MESH_PB_ADV +#define MYNEWT_VAL_BLE_MESH_PB_ADV (1) +#else +#define MYNEWT_VAL_BLE_MESH_PB_ADV (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_PB_GATT +#ifdef CONFIG_BT_NIMBLE_MESH_PB_GATT +#define MYNEWT_VAL_BLE_MESH_PB_GATT (1) +#else +#define MYNEWT_VAL_BLE_MESH_PB_GATT (0) +#endif +#endif + +/* Overridden by @apache-mynewt-nimble/nimble/host/mesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_PROV +#ifdef CONFIG_BT_NIMBLE_MESH_PROV +#define MYNEWT_VAL_BLE_MESH_PROV (1) +#else +#define MYNEWT_VAL_BLE_MESH_PROV (0) +#endif +#endif + +/* Overridden by @apache-mynewt-nimble/nimble/host/mesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_PROXY +#ifdef CONFIG_BT_NIMBLE_MESH_PROXY +#define MYNEWT_VAL_BLE_MESH_PROXY (1) +#else +#define MYNEWT_VAL_BLE_MESH_PROXY (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE +#define MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE (1) +#endif + + +#ifndef MYNEWT_VAL_BLE_MESH_RELAY +#ifdef CONFIG_BT_NIMBLE_MESH_RELAY +#define MYNEWT_VAL_BLE_MESH_RELAY (1) +#else +#define MYNEWT_VAL_BLE_MESH_RELAY (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT (5) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RX_SDU_MAX +#define MYNEWT_VAL_BLE_MESH_RX_SDU_MAX (72) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT +#define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (2) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE +#define MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE (128) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_SETTINGS +#define MYNEWT_VAL_BLE_MESH_SETTINGS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_SHELL +#define MYNEWT_VAL_BLE_MESH_SHELL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_SHELL_MODELS +#define MYNEWT_VAL_BLE_MESH_SHELL_MODELS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_STORE_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_STORE_TIMEOUT (2) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_SUBNET_COUNT +#define MYNEWT_VAL_BLE_MESH_SUBNET_COUNT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_TESTING +#define MYNEWT_VAL_BLE_MESH_TESTING (0) +#endif + +/* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ +#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MAX +#define MYNEWT_VAL_BLE_MESH_TX_SEG_MAX (6) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT +#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (4) +#endif + +/*** @apache-mynewt-nimble/nimble/host/services/gap */ +#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION +#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0) +#endif + +/*** nimble/transport */ +#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_EMSPI +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_EMSPI (0) +#endif + +/* Overridden by targets/porting-nimble (defined by nimble/transport) */ +#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_NIMBLE_BUILTIN +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_NIMBLE_BUILTIN (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_RAM +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_RAM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET (0) +#endif + +/* Overridden by targets/porting-nimble (defined by nimble/transport) */ +#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_UART +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_UART (1) +#endif + +/*** nimble/transport/uart */ +#ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT +#define MYNEWT_VAL_BLE_ACL_BUF_COUNT CONFIG_BT_NIMBLE_ACL_BUF_COUNT +#endif + +#ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE +#define MYNEWT_VAL_BLE_ACL_BUF_SIZE CONFIG_BT_NIMBLE_ACL_BUF_SIZE +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT +#define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (12) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE +#define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT +#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT +#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT +#endif + +/* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */ +#ifndef MYNEWT_VAL_BLE_HCI_UART_BAUD +#define MYNEWT_VAL_BLE_HCI_UART_BAUD (115200) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_UART_DATA_BITS +#define MYNEWT_VAL_BLE_HCI_UART_DATA_BITS (8) +#endif + +/* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */ +#ifndef MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL +#define MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_UART_PARITY +#define MYNEWT_VAL_BLE_HCI_UART_PARITY (HAL_UART_PARITY_NONE) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_UART_PORT +#define MYNEWT_VAL_BLE_HCI_UART_PORT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_UART_STOP_BITS +#define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1) +#endif + +#endif diff --git a/docs/Doxyfile b/docs/Doxyfile index 6f9ada9ee..d0237cdcb 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -57,6 +57,8 @@ INPUT = \ ../../components/bt/bluedroid/api/include/api/esp_spp_api.h \ ../../components/bt/bluedroid/api/include/api/esp_hf_defs.h \ ../../components/bt/bluedroid/api/include/api/esp_hf_client_api.h \ + ## NimBLE related Bluetooth APIs + ../../components/nimble/esp-hci/include/esp_nimble_hci.h \ ## ## Ethernet - API Reference ## diff --git a/docs/_static/esp32_nimble_stack.png b/docs/_static/esp32_nimble_stack.png new file mode 100644 index 0000000000000000000000000000000000000000..4aba0ae8827fb40ff9c82e96ea8a0c754f9d9b5b GIT binary patch literal 22217 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 C-Y(hz literal 0 HcmV?d00001 diff --git a/docs/en/COPYRIGHT.rst b/docs/en/COPYRIGHT.rst index cb4272af6..2891e13f5 100644 --- a/docs/en/COPYRIGHT.rst +++ b/docs/en/COPYRIGHT.rst @@ -58,6 +58,9 @@ These third party libraries can be included into the application (firmware) prod * :component:`ESP-MQTT ` MQTT Package (contiki-mqtt) - Copyright (c) 2014, Stephen Robinson, MQTT-ESP - Tuan PM is licensed under Apache License 2.0. * :component:`BLE Mesh ` is adapted from Zephyr Project, Copyright (c) 2017-2018 Intel Corporation and licensed under Apache License 2.0 +* `mynewt-nimble`_ Apache Mynewt NimBLE, Copyright 2015-2018, The Apache Software Foundation, is licensed under Apache License 2.0. + + Build Tools ----------- @@ -160,3 +163,4 @@ Copyright (C) 2011, ChaN, all right reserved. .. _asio: https://github.com/chriskohlhoff/asio .. _mqtt: https://github.com/espressif/esp-mqtt .. _zephyr: https://github.com/zephyrproject-rtos/zephyr +.. _mynewt-nimble: https://github.com/apache/mynewt-nimble diff --git a/docs/en/api-reference/bluetooth/index.rst b/docs/en/api-reference/bluetooth/index.rst index 4e1e2d14b..b9e3ce2c5 100644 --- a/docs/en/api-reference/bluetooth/index.rst +++ b/docs/en/api-reference/bluetooth/index.rst @@ -10,6 +10,11 @@ Bluetooth API Bluetooth Common Bluetooth LE Bluetooth Classic + NimBLE + +ESP-IDF currently supports two host stacks. The Bluedroid based stack (default) supports classic Bluetooth as well as BLE. On the other hand, Apache NimBLE based stack is BLE only. For users to make a choice: +* For usecases involving classic Bluetooth as well as BLE, Bluedroid should be used. +* For BLE-only usecases, using NimBLE is recommended. It is less demanding in terms of code footprint and runtime memory, making it suitable for such scenarios. For the overview of the ESP32 Bluetooth stack architecture, follow the links below: diff --git a/docs/en/api-reference/bluetooth/nimble/index.rst b/docs/en/api-reference/bluetooth/nimble/index.rst new file mode 100644 index 000000000..e035c6199 --- /dev/null +++ b/docs/en/api-reference/bluetooth/nimble/index.rst @@ -0,0 +1,44 @@ +NimBLE-based host APIs +********************** +Overview +======== + +Apache MyNewt NimBLE is a highly configurable and BT SIG qualifiable BLE stack providing both host and controller functionalities. ESP-IDF supports NimBLE host stack which is specifically ported for ESP32 platform and FreeRTOS. The underlying controller is still the same (as in case of Bluedroid) providing VHCI interface. Refer to `NimBLE user guide `_ for a complete list of features and additional information on NimBLE stack. Most features of NimBLE including BLE Mesh are supported by ESP-IDF. The porting layer is kept cleaner by maintaining all the existing APIs of NimBLE along with a single ESP-NimBLE API for initialization, making it simpler for the application developers. + +Architecture +============ + +Currently, NimBLE host and controller support different transports such as UART and RAM between them. However, RAM transport cannot be used as is in case of ESP as ESP controller supports VHCI interface and buffering schemes used by NimBLE host is incompatible with that used by ESP controller. Therefore, a new transport between NimBLE host and ESP controller has been added. This is depicted in the figure below. This layer is responsible for maintaining pool of transport buffers and formatting buffers exchanges between host and controller as per the requirements. + +.. figure:: ../../../../_static/esp32_nimble_stack.png + :align: center + :alt: ESP NimBLE Stack. + :scale: 50 + + ESP NimBLE Stack + + +Threading Model +=============== + +The NimBLE host can run inside the application thread or can have its own independent thread. This flexibility is inherently provided by NimBLE design. By default, a thread is spawned by the porting function ``nimble_port_freertos_init``. This behavior can be changed by overriding the same function. For BLE Mesh, additional thread (advertising thread) is used which keeps on feeding advertisement events to the main thread. + +Programming Sequence +==================== + +To begin with, make sure that the NimBLE stack is enabled from menuconfig :ref:`choose NimBLE for the Bluetooth host `. + +Typical programming sequence with NimBLE stack consists of the following steps: + * Initialize NVS flash using :cpp:func:`nvs_flash_init` API. This is because ESP controller uses NVS during initialization. + * Call :cpp:func:`esp_nimble_hci_and_controller_init` to initialize ESP controller as well as transport layer. This will also link the host and controller modules together. Alternatively, if ESP controller is already initialized, then :cpp:func:`esp_nimble_hci_init` can be called for the remaining initialization. + * Initialize the host stack using ``nimble_port_init``. + * Initialize the required NimBLE host configuration parameters and callbacks + * Perform application specific tasks/initialization + * Run the thread for host stack using ``nimble_port_freertos_init`` + +This documentation does not cover NimBLE APIs. Refer to `NimBLE tutorial `_ for more details on the programming sequence/NimBLE APIs for different scenarios. + +API Reference +============= + +.. include:: /_build/inc/esp_nimble_hci.inc diff --git a/docs/zh_CN/api-reference/bluetooth/index.rst b/docs/zh_CN/api-reference/bluetooth/index.rst index 47e5ddd48..e8383b09e 100644 --- a/docs/zh_CN/api-reference/bluetooth/index.rst +++ b/docs/zh_CN/api-reference/bluetooth/index.rst @@ -10,6 +10,7 @@ Bluetooth Common Bluetooth LE Bluetooth Classic + NimBLE 请点击下方链接,查看 ESP32 蓝牙架构: diff --git a/docs/zh_CN/api-reference/bluetooth/nimble/index.rst b/docs/zh_CN/api-reference/bluetooth/nimble/index.rst new file mode 100644 index 000000000..48efe410c --- /dev/null +++ b/docs/zh_CN/api-reference/bluetooth/nimble/index.rst @@ -0,0 +1 @@ +.. include:: ../../../../en/api-reference/bluetooth/nimble/index.rst diff --git a/examples/README.md b/examples/README.md index 62e0b73bd..339115b12 100644 --- a/examples/README.md +++ b/examples/README.md @@ -6,7 +6,8 @@ This directory contains a range of example ESP-IDF projects. These are intended The examples are grouped into subdirectories by category. Each category directory contains one or more example projects: -* `bluetooth` contains Bluetooth (BLE & BT Classic) examples. +* `bluetooth` contains Bluetooth (BLE & BT Classic) examples using default Bluedroid host stack. +* `bleutooth/nimble` contains BLE examples using NimBLE host stack * `ethernet` contains Ethernet examples. * `get-started` contains some very simple examples with minimal functionality. * `mesh` contains Wi-Fi Mesh examples. diff --git a/examples/bluetooth/nimble/README.md b/examples/bluetooth/nimble/README.md new file mode 100644 index 000000000..39f97c19a --- /dev/null +++ b/examples/bluetooth/nimble/README.md @@ -0,0 +1,32 @@ +# NimBLE Examples + +This directory includes examples to demonstrate BLE functionality using Apache MyNewt NimBLE (https://github.com/apache/mynewt-nimble) host stack. + +## bleprph + +Shows how ESP32 acts as a BLE Peripheral. + +See the [README.md](./bleprph/README.md) file in the example [bleprph](./bleprph/). + +## blecent + +Shows how ESP32 acts as a BLE central. + +See the [README.md](./blecent/README.md) file in the example [blecent](./blecent/). + +## blemesh + +Demonstrates BLE mesh functionality of NimBLE. + +See the [README.md](./blemesh/README.md) file in the example [blemesh](./blemesh/). + +## blehr + +Demonstrates standard Heart Rate measurement BLE peripheral. + +See the [README.md](./blehr/README.md) file in the example [blehr](./blehr/). + +# More + +See the [README.md](../../README.md) file in the upper level [examples](../../) directory for more information about examples. + diff --git a/examples/bluetooth/nimble/blecent/CMakeLists.txt b/examples/bluetooth/nimble/blecent/CMakeLists.txt new file mode 100644 index 000000000..b3ac70b41 --- /dev/null +++ b/examples/bluetooth/nimble/blecent/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(blecent) diff --git a/examples/bluetooth/nimble/blecent/Makefile b/examples/bluetooth/nimble/blecent/Makefile new file mode 100644 index 000000000..2b3a9fe81 --- /dev/null +++ b/examples/bluetooth/nimble/blecent/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := blecent + +include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/nimble/blecent/README.md b/examples/bluetooth/nimble/blecent/README.md new file mode 100644 index 000000000..bfa7b68d4 --- /dev/null +++ b/examples/bluetooth/nimble/blecent/README.md @@ -0,0 +1,94 @@ +# BLE central example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example creates GATT client and performs passive scan, it then connects to peripheral device if the device advertises connectability and the device advertises support for the Alert Notification service (0x1811) as primary service UUID. + +It performs three GATT operations against the specified peer: + +* Reads the ANS Supported New Alert Category characteristic. + +* After the read operation is completed, writes the ANS Alert Notification Control Point characteristic. + +* After the write operation is completed, subscribes to notifications for the ANS Unread Alert Status characteristic. + +If the peer does not support a required service, characteristic, or descriptor, then the peer lied when it claimed support for the alert notification service! When this happens, or if a GATT procedure fails, this function immediately terminates the connection. + +It uses ESP32's Bluetooth controller and NimBLE stack based BLE host. + +This example aims at understanding BLE service discovery, connection and characteristic operations. + +To test this demo, use any BLE GATT server app that advertises support for the Alert Notification service (0x1811) and includes it in the GATT database. + + +## How to use example + +### Configure the project + +``` +make menuconfig +``` + +* Set serial port under Serial Flasher Options. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +make -j4 flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +There is this console output on successful connection: +``` +I (202) BTDM_INIT: BT controller compile version [0b60040] +I (202) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +W (212) phy_init: failed to load RF calibration data (0xffffffff), falling back to full calibration +I (422) phy: phy_version: 4007, 9c6b43b, Jan 11 2019, 16:45:07, 0, 2 +I (722) NimBLE_BLE_CENT: BLE Host Task Started +GAP procedure initiated: stop advertising. +GAP procedure initiated: discovery; own_addr_type=0 filter_policy=0 passive=1 limited=0 filter_duplicates=1 duration=forever +GAP procedure initiated: connect; peer_addr_type=1 peer_addr=xx:xx:xx:xx:xx:xx scan_itvl=16 scan_window=16 itvl_min=24 itvl_max=40 latency=0 supervision_timeout=256 min_ce_len=16 max_ce_len=768 own_addr_type=0 +Connection established +GATT procedure initiated: discover all services +GATT procedure initiated: discover all characteristics; start_handle=1 end_handle=3 +GATT procedure initiated: discover all characteristics; start_handle=20 end_handle=26 +GATT procedure initiated: discover all characteristics; start_handle=40 end_handle=65535 +GATT procedure initiated: discover all descriptors; chr_val_handle=42 end_handle=43 +GATT procedure initiated: discover all descriptors; chr_val_handle=49 end_handle=65535 +Service discovery complete; status=0 conn_handle=0 +GATT procedure initiated: read; att_handle=45 +GATT procedure initiated: write; att_handle=47 len=2 +GATT procedure initiated: write; att_handle=43 len=2 +Read complete; status=0 conn_handle=0 attr_handle=45 value=0x02 +Write complete; status=0 conn_handle=0 attr_handle=47 +Subscribe complete; status=0 conn_handle=0 attr_handle=43 +``` + +There is this console output on failure (or peripheral does not support New Alert Service category): +``` +I (180) BTDM_INIT: BT controller compile version [8e87ec7] +I (180) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (250) phy: phy_version: 4000, b6198fa, Sep 3 2018, 15:11:06, 0, 0 +I (480) NimBLE_BLE_CENT: BLE Host Task Started +GAP procedure initiated: stop advertising. +GAP procedure initiated: discovery; own_addr_type=0 filter_policy=0 passive=1 limited=0 filter_duplicates=1 duration=forever +GAP procedure initiated: connect; peer_addr_type=1 peer_addr=xx:xx:xx:xx:xx:xx scan_itvl=16 scan_window=16 itvl_min=24 itvl_max=40 latency=0 supervision_timeout=256 min_ce_len=16 max_ce_len=768 own_addr_type=0 +Connection established +GATT procedure initiated: discover all services +GATT procedure initiated: discover all characteristics; start_handle=1 end_handle=3 +GATT procedure initiated: discover all characteristics; start_handle=20 end_handle=26 +GATT procedure initiated: discover all characteristics; start_handle=40 end_handle=65535 +GATT procedure initiated: discover all descriptors; chr_val_handle=42 end_handle=43 +GATT procedure initiated: discover all descriptors; chr_val_handle=47 end_handle=65535 +Service discovery complete; status=0 conn_handle=0 +Error: Peer doesn't support the Supported New Alert Category characteristic +GAP procedure initiated: terminate connection; conn_handle=0 hci_reason=19 +disconnect; reason=534 +``` diff --git a/examples/bluetooth/nimble/blecent/main/CMakeLists.txt b/examples/bluetooth/nimble/blecent/main/CMakeLists.txt new file mode 100644 index 000000000..7ad90092b --- /dev/null +++ b/examples/bluetooth/nimble/blecent/main/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCS "main.c" + "misc.c" + "peer.c") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/bluetooth/nimble/blecent/main/Kconfig.projbuild b/examples/bluetooth/nimble/blecent/main/Kconfig.projbuild new file mode 100644 index 000000000..dbfbdb132 --- /dev/null +++ b/examples/bluetooth/nimble/blecent/main/Kconfig.projbuild @@ -0,0 +1,9 @@ +menu "Example Configuration" + + config EXAMPLE_PEER_ADDR + string "Peer Address" + default "ADDR_ANY" + help + Enter the peer address in aa:bb:cc:dd:ee:ff form to connect to a specific peripheral + +endmenu diff --git a/examples/bluetooth/nimble/blecent/main/blecent.h b/examples/bluetooth/nimble/blecent/main/blecent.h new file mode 100644 index 000000000..1e7635ffa --- /dev/null +++ b/examples/bluetooth/nimble/blecent/main/blecent.h @@ -0,0 +1,113 @@ +/* + * 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_BLECENT_ +#define H_BLECENT_ + +#include "modlog/modlog.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_adv_fields; +struct ble_gap_conn_desc; +struct ble_hs_cfg; +union ble_store_value; +union ble_store_key; + +#define BLECENT_SVC_ALERT_UUID 0x1811 +#define BLECENT_CHR_SUP_NEW_ALERT_CAT_UUID 0x2A47 +#define BLECENT_CHR_NEW_ALERT 0x2A46 +#define BLECENT_CHR_SUP_UNR_ALERT_CAT_UUID 0x2A48 +#define BLECENT_CHR_UNR_ALERT_STAT_UUID 0x2A45 +#define BLECENT_CHR_ALERT_NOT_CTRL_PT 0x2A44 + +/** Misc. */ +void print_bytes(const uint8_t *bytes, int len); +void print_mbuf(const struct os_mbuf *om); +char *addr_str(const void *addr); +void print_uuid(const ble_uuid_t *uuid); +void print_conn_desc(const struct ble_gap_conn_desc *desc); +void print_adv_fields(const struct ble_hs_adv_fields *fields); + +/** Peer. */ +struct peer_dsc { + SLIST_ENTRY(peer_dsc) next; + struct ble_gatt_dsc dsc; +}; +SLIST_HEAD(peer_dsc_list, peer_dsc); + +struct peer_chr { + SLIST_ENTRY(peer_chr) next; + struct ble_gatt_chr chr; + + struct peer_dsc_list dscs; +}; +SLIST_HEAD(peer_chr_list, peer_chr); + +struct peer_svc { + SLIST_ENTRY(peer_svc) next; + struct ble_gatt_svc svc; + + struct peer_chr_list chrs; +}; +SLIST_HEAD(peer_svc_list, peer_svc); + +struct peer; +typedef void peer_disc_fn(const struct peer *peer, int status, void *arg); + +struct peer { + SLIST_ENTRY(peer) next; + + uint16_t conn_handle; + + /** List of discovered GATT services. */ + struct peer_svc_list svcs; + + /** Keeps track of where we are in the service discovery process. */ + uint16_t disc_prev_chr_val; + struct peer_svc *cur_svc; + + /** Callback that gets executed when service discovery completes. */ + peer_disc_fn *disc_cb; + void *disc_cb_arg; +}; + +int peer_disc_all(uint16_t conn_handle, peer_disc_fn *disc_cb, + void *disc_cb_arg); +const struct peer_dsc * +peer_dsc_find_uuid(const struct peer *peer, const ble_uuid_t *svc_uuid, + const ble_uuid_t *chr_uuid, const ble_uuid_t *dsc_uuid); +const struct peer_chr * +peer_chr_find_uuid(const struct peer *peer, const ble_uuid_t *svc_uuid, + const ble_uuid_t *chr_uuid); +const struct peer_svc * +peer_svc_find_uuid(const struct peer *peer, const ble_uuid_t *uuid); +int peer_delete(uint16_t conn_handle); +int peer_add(uint16_t conn_handle); +int peer_init(int max_peers, int max_svcs, int max_chrs, int max_dscs); +struct peer * +peer_find(uint16_t conn_handle); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/bluetooth/nimble/blecent/main/component.mk b/examples/bluetooth/nimble/blecent/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/bluetooth/nimble/blecent/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/bluetooth/nimble/blecent/main/main.c b/examples/bluetooth/nimble/blecent/main/main.c new file mode 100644 index 000000000..be179a069 --- /dev/null +++ b/examples/bluetooth/nimble/blecent/main/main.c @@ -0,0 +1,550 @@ +/* + * 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 "esp_log.h" +#include "nvs_flash.h" +/* BLE */ +#include "esp_nimble_hci.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "console/console.h" +#include "services/gap/ble_svc_gap.h" +#include "blecent.h" + +static const char *tag = "NimBLE_BLE_CENT"; +static int blecent_gap_event(struct ble_gap_event *event, void *arg); +static uint8_t peer_addr[6]; + +void ble_store_config_init(void); + +/** + * Application callback. Called when the attempt to subscribe to notifications + * for the ANS Unread Alert Status characteristic has completed. + */ +static int +blecent_on_subscribe(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, + void *arg) +{ + MODLOG_DFLT(INFO, "Subscribe complete; status=%d conn_handle=%d " + "attr_handle=%d\n", + error->status, conn_handle, attr->handle); + + return 0; +} + +/** + * Application callback. Called when the write to the ANS Alert Notification + * Control Point characteristic has completed. + */ +static int +blecent_on_write(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, + void *arg) +{ + MODLOG_DFLT(INFO, + "Write complete; status=%d conn_handle=%d attr_handle=%d\n", + error->status, conn_handle, attr->handle); + + /* Subscribe to notifications for the Unread Alert Status characteristic. + * A central enables notifications by writing two bytes (1, 0) to the + * characteristic's client-characteristic-configuration-descriptor (CCCD). + */ + const struct peer_dsc *dsc; + uint8_t value[2]; + int rc; + const struct peer *peer = peer_find(conn_handle); + + dsc = peer_dsc_find_uuid(peer, + BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID), + BLE_UUID16_DECLARE(BLECENT_CHR_UNR_ALERT_STAT_UUID), + BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16)); + if (dsc == NULL) { + MODLOG_DFLT(ERROR, "Error: Peer lacks a CCCD for the Unread Alert " + "Status characteristic\n"); + goto err; + } + + value[0] = 1; + value[1] = 0; + rc = ble_gattc_write_flat(conn_handle, dsc->dsc.handle, + value, sizeof value, blecent_on_subscribe, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Error: Failed to subscribe to characteristic; " + "rc=%d\n", rc); + goto err; + } + + return 0; +err: + /* Terminate the connection. */ + return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); +} + +/** + * Application callback. Called when the read of the ANS Supported New Alert + * Category characteristic has completed. + */ +static int +blecent_on_read(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, + void *arg) +{ + MODLOG_DFLT(INFO, "Read complete; status=%d conn_handle=%d", error->status, + conn_handle); + if (error->status == 0) { + MODLOG_DFLT(INFO, " attr_handle=%d value=", attr->handle); + print_mbuf(attr->om); + } + MODLOG_DFLT(INFO, "\n"); + + /* Write two bytes (99, 100) to the alert-notification-control-point + * characteristic. + */ + const struct peer_chr *chr; + uint8_t value[2]; + int rc; + const struct peer *peer = peer_find(conn_handle); + + chr = peer_chr_find_uuid(peer, + BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID), + BLE_UUID16_DECLARE(BLECENT_CHR_ALERT_NOT_CTRL_PT)); + if (chr == NULL) { + MODLOG_DFLT(ERROR, "Error: Peer doesn't support the Alert " + "Notification Control Point characteristic\n"); + goto err; + } + + value[0] = 99; + value[1] = 100; + rc = ble_gattc_write_flat(conn_handle, chr->chr.val_handle, + value, sizeof value, blecent_on_write, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Error: Failed to write characteristic; rc=%d\n", + rc); + goto err; + } + + return 0; +err: + /* Terminate the connection. */ + return ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); +} + +/** + * Performs three GATT operations against the specified peer: + * 1. Reads the ANS Supported New Alert Category characteristic. + * 2. After read is completed, writes the ANS Alert Notification Control Point characteristic. + * 3. After write is completed, subscribes to notifications for the ANS Unread Alert Status + * characteristic. + * + * If the peer does not support a required service, characteristic, or + * descriptor, then the peer lied when it claimed support for the alert + * notification service! When this happens, or if a GATT procedure fails, + * this function immediately terminates the connection. + */ +static void +blecent_read_write_subscribe(const struct peer *peer) +{ + const struct peer_chr *chr; + int rc; + + /* Read the supported-new-alert-category characteristic. */ + chr = peer_chr_find_uuid(peer, + BLE_UUID16_DECLARE(BLECENT_SVC_ALERT_UUID), + BLE_UUID16_DECLARE(BLECENT_CHR_SUP_NEW_ALERT_CAT_UUID)); + if (chr == NULL) { + MODLOG_DFLT(ERROR, "Error: Peer doesn't support the Supported New " + "Alert Category characteristic\n"); + goto err; + } + + rc = ble_gattc_read(peer->conn_handle, chr->chr.val_handle, + blecent_on_read, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Error: Failed to read characteristic; rc=%d\n", + rc); + goto err; + } + + return; +err: + /* Terminate the connection. */ + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); +} + +/** + * Called when service discovery of the specified peer has completed. + */ +static void +blecent_on_disc_complete(const struct peer *peer, int status, void *arg) +{ + + if (status != 0) { + /* Service discovery failed. Terminate the connection. */ + MODLOG_DFLT(ERROR, "Error: Service discovery failed; status=%d " + "conn_handle=%d\n", status, peer->conn_handle); + ble_gap_terminate(peer->conn_handle, BLE_ERR_REM_USER_CONN_TERM); + return; + } + + /* Service discovery has completed successfully. Now we have a complete + * list of services, characteristics, and descriptors that the peer + * supports. + */ + MODLOG_DFLT(ERROR, "Service discovery complete; status=%d " + "conn_handle=%d\n", status, peer->conn_handle); + + /* Now perform three GATT procedures against the peer: read, + * write, and subscribe to notifications. + */ + blecent_read_write_subscribe(peer); +} + +/** + * Initiates the GAP general discovery procedure. + */ +static void +blecent_scan(void) +{ + uint8_t own_addr_type; + struct ble_gap_disc_params disc_params; + int rc; + + /* Figure out address to use while advertising (no privacy for now) */ + rc = ble_hs_id_infer_auto(0, &own_addr_type); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); + return; + } + + /* Tell the controller to filter duplicates; we don't want to process + * repeated advertisements from the same device. + */ + disc_params.filter_duplicates = 1; + + /** + * Perform a passive scan. I.e., don't send follow-up scan requests to + * each advertiser. + */ + disc_params.passive = 1; + + /* Use defaults for the rest of the parameters. */ + disc_params.itvl = 0; + disc_params.window = 0; + disc_params.filter_policy = 0; + disc_params.limited = 0; + + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, + blecent_gap_event, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Error initiating GAP discovery procedure; rc=%d\n", + rc); + } +} + +/** + * Indicates whether we should try to connect to the sender of the specified + * advertisement. The function returns a positive result if the device + * advertises connectability and support for the Alert Notification service. + */ +static int +blecent_should_connect(const struct ble_gap_disc_desc *disc) +{ + struct ble_hs_adv_fields fields; + int rc; + int i; + + /* The device has to be advertising connectability. */ + if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && + disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { + + return 0; + } + + rc = ble_hs_adv_parse_fields(&fields, disc->data, disc->length_data); + if (rc != 0) { + return rc; + } + + if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { + ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); + /* Convert string to address */ + sscanf(CONFIG_EXAMPLE_PEER_ADDR, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &peer_addr[5], &peer_addr[4], &peer_addr[3], + &peer_addr[2], &peer_addr[1], &peer_addr[0]); + if (memcmp(peer_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { + return 0; + } + } + + /* The device has to advertise support for the Alert Notification + * service (0x1811). + */ + for (i = 0; i < fields.num_uuids16; i++) { + if (ble_uuid_u16(&fields.uuids16[i].u) == BLECENT_SVC_ALERT_UUID) { + return 1; + } + } + + return 0; +} + +/** + * Connects to the sender of the specified advertisement of it looks + * interesting. A device is "interesting" if it advertises connectability and + * support for the Alert Notification service. + */ +static void +blecent_connect_if_interesting(const struct ble_gap_disc_desc *disc) +{ + int rc; + + /* Don't do anything if we don't care about this advertiser. */ + if (!blecent_should_connect(disc)) { + return; + } + + /* Scanning must be stopped before a connection can be initiated. */ + rc = ble_gap_disc_cancel(); + if (rc != 0) { + MODLOG_DFLT(DEBUG, "Failed to cancel scan; rc=%d\n", rc); + return; + } + + /* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for + * timeout. + */ + + rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &disc->addr, 30000, NULL, + blecent_gap_event, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Error: Failed to connect to device; addr_type=%d " + "addr=%s\n", + disc->addr.type, addr_str(disc->addr.val)); + return; + } +} + +/** + * The nimble host executes this callback when a GAP event occurs. The + * application associates a GAP event callback with each connection that is + * established. blecent uses the same callback for all connections. + * + * @param event The event being signalled. + * @param arg Application-specified argument; unused by + * blecent. + * + * @return 0 if the application successfully handled the + * event; nonzero on failure. The semantics + * of the return code is specific to the + * particular GAP event being signalled. + */ +static int +blecent_gap_event(struct ble_gap_event *event, void *arg) +{ + struct ble_gap_conn_desc desc; + struct ble_hs_adv_fields fields; + int rc; + + switch (event->type) { + case BLE_GAP_EVENT_DISC: + rc = ble_hs_adv_parse_fields(&fields, event->disc.data, + event->disc.length_data); + if (rc != 0) { + return 0; + } + + /* An advertisment report was received during GAP discovery. */ + print_adv_fields(&fields); + + /* Try to connect to the advertiser if it looks interesting. */ + blecent_connect_if_interesting(&event->disc); + return 0; + + case BLE_GAP_EVENT_CONNECT: + /* A new connection was established or a connection attempt failed. */ + if (event->connect.status == 0) { + /* Connection successfully established. */ + MODLOG_DFLT(INFO, "Connection established "); + + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + assert(rc == 0); + print_conn_desc(&desc); + MODLOG_DFLT(INFO, "\n"); + + /* Remember peer. */ + rc = peer_add(event->connect.conn_handle); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Failed to add peer; rc=%d\n", rc); + return 0; + } + + /* Perform service discovery. */ + rc = peer_disc_all(event->connect.conn_handle, + blecent_on_disc_complete, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "Failed to discover services; rc=%d\n", rc); + return 0; + } + } else { + /* Connection attempt failed; resume scanning. */ + MODLOG_DFLT(ERROR, "Error: Connection failed; status=%d\n", + event->connect.status); + blecent_scan(); + } + + return 0; + + case BLE_GAP_EVENT_DISCONNECT: + /* Connection terminated. */ + MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason); + print_conn_desc(&event->disconnect.conn); + MODLOG_DFLT(INFO, "\n"); + + /* Forget about peer. */ + peer_delete(event->disconnect.conn.conn_handle); + + /* Resume scanning. */ + blecent_scan(); + return 0; + + case BLE_GAP_EVENT_DISC_COMPLETE: + MODLOG_DFLT(INFO, "discovery complete; reason=%d\n", + event->disc_complete.reason); + return 0; + + case BLE_GAP_EVENT_ENC_CHANGE: + /* Encryption has been enabled or disabled for this connection. */ + MODLOG_DFLT(INFO, "encryption change event; status=%d ", + event->enc_change.status); + rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc); + assert(rc == 0); + print_conn_desc(&desc); + return 0; + + case BLE_GAP_EVENT_NOTIFY_RX: + /* Peer sent us a notification or indication. */ + MODLOG_DFLT(INFO, "received %s; conn_handle=%d attr_handle=%d " + "attr_len=%d\n", + event->notify_rx.indication ? + "indication" : + "notification", + event->notify_rx.conn_handle, + event->notify_rx.attr_handle, + OS_MBUF_PKTLEN(event->notify_rx.om)); + + /* Attribute data is contained in event->notify_rx.attr_data. */ + return 0; + + case BLE_GAP_EVENT_MTU: + MODLOG_DFLT(INFO, "mtu update event; conn_handle=%d cid=%d mtu=%d\n", + event->mtu.conn_handle, + event->mtu.channel_id, + event->mtu.value); + return 0; + + case BLE_GAP_EVENT_REPEAT_PAIRING: + /* We already have a bond with the peer, but it is attempting to + * establish a new secure link. This app sacrifices security for + * convenience: just throw away the old bond and accept the new link. + */ + + /* Delete the old bond. */ + rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc); + assert(rc == 0); + ble_store_util_delete_peer(&desc.peer_id_addr); + + /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should + * continue with the pairing operation. + */ + return BLE_GAP_REPEAT_PAIRING_RETRY; + + default: + return 0; + } +} + +static void +blecent_on_reset(int reason) +{ + MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason); +} + +static void +blecent_on_sync(void) +{ + int rc; + + /* Make sure we have proper identity address set (public preferred) */ + rc = ble_hs_util_ensure_addr(0); + assert(rc == 0); + + /* Begin scanning for a peripheral to connect to. */ + blecent_scan(); +} + +void blecent_host_task(void *param) +{ + ESP_LOGI(tag, "BLE Host Task Started"); + /* This function will return only when nimble_port_stop() is executed */ + nimble_port_run(); + + nimble_port_freertos_deinit(); +} + +void +app_main(void) +{ + int rc; + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init()); + + nimble_port_init(); + /* Configure the host. */ + ble_hs_cfg.reset_cb = blecent_on_reset; + ble_hs_cfg.sync_cb = blecent_on_sync; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + /* Initialize data structures to track connected peers. */ + rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); + assert(rc == 0); + + /* Set the default device name. */ + rc = ble_svc_gap_device_name_set("nimble-blecent"); + assert(rc == 0); + + /* XXX Need to have template for store */ + ble_store_config_init(); + + nimble_port_freertos_init(blecent_host_task); + +} diff --git a/examples/bluetooth/nimble/blecent/main/misc.c b/examples/bluetooth/nimble/blecent/main/misc.c new file mode 100644 index 000000000..c17944326 --- /dev/null +++ b/examples/bluetooth/nimble/blecent/main/misc.c @@ -0,0 +1,211 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include "host/ble_hs.h" +#include "host/ble_uuid.h" +#include "blecent.h" + +/** + * Utility function to log an array of bytes. + */ +void +print_bytes(const uint8_t *bytes, int len) +{ + int i; + + for (i = 0; i < len; i++) { + MODLOG_DFLT(DEBUG, "%s0x%02x", i != 0 ? ":" : "", bytes[i]); + } +} + +void +print_mbuf(const struct os_mbuf *om) +{ + int colon, i; + + colon = 0; + while (om != NULL) { + if (colon) { + MODLOG_DFLT(INFO, ":"); + } else { + colon = 1; + } + for (i = 0; i < om->om_len; i++) { + MODLOG_DFLT(INFO, "%s0x%02x", i != 0 ? ":" : "", om->om_data[i]); + } + om = SLIST_NEXT(om, om_next); + } +} + +char * +addr_str(const void *addr) +{ + static char buf[6 * 2 + 5 + 1]; + const uint8_t *u8p; + + u8p = addr; + sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", + u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]); + + return buf; +} + +void +print_uuid(const ble_uuid_t *uuid) +{ + char buf[BLE_UUID_STR_LEN]; + + MODLOG_DFLT(DEBUG, "%s", ble_uuid_to_str(uuid, buf)); +} + +/** + * Logs information about a connection to the console. + */ +void +print_conn_desc(const struct ble_gap_conn_desc *desc) +{ + MODLOG_DFLT(DEBUG, "handle=%d our_ota_addr_type=%d our_ota_addr=%s ", + desc->conn_handle, desc->our_ota_addr.type, + addr_str(desc->our_ota_addr.val)); + MODLOG_DFLT(DEBUG, "our_id_addr_type=%d our_id_addr=%s ", + desc->our_id_addr.type, addr_str(desc->our_id_addr.val)); + MODLOG_DFLT(DEBUG, "peer_ota_addr_type=%d peer_ota_addr=%s ", + desc->peer_ota_addr.type, addr_str(desc->peer_ota_addr.val)); + MODLOG_DFLT(DEBUG, "peer_id_addr_type=%d peer_id_addr=%s ", + desc->peer_id_addr.type, addr_str(desc->peer_id_addr.val)); + MODLOG_DFLT(DEBUG, "conn_itvl=%d conn_latency=%d supervision_timeout=%d " + "encrypted=%d authenticated=%d bonded=%d", + desc->conn_itvl, desc->conn_latency, + desc->supervision_timeout, + desc->sec_state.encrypted, + desc->sec_state.authenticated, + desc->sec_state.bonded); +} + + +void +print_adv_fields(const struct ble_hs_adv_fields *fields) +{ + char s[BLE_HS_ADV_MAX_SZ]; + const uint8_t *u8p; + int i; + + if (fields->flags != 0) { + MODLOG_DFLT(DEBUG, " flags=0x%02x\n", fields->flags); + } + + if (fields->uuids16 != NULL) { + MODLOG_DFLT(DEBUG, " uuids16(%scomplete)=", + fields->uuids16_is_complete ? "" : "in"); + for (i = 0; i < fields->num_uuids16; i++) { + print_uuid(&fields->uuids16[i].u); + MODLOG_DFLT(DEBUG, " "); + } + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->uuids32 != NULL) { + MODLOG_DFLT(DEBUG, " uuids32(%scomplete)=", + fields->uuids32_is_complete ? "" : "in"); + for (i = 0; i < fields->num_uuids32; i++) { + print_uuid(&fields->uuids32[i].u); + MODLOG_DFLT(DEBUG, " "); + } + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->uuids128 != NULL) { + MODLOG_DFLT(DEBUG, " uuids128(%scomplete)=", + fields->uuids128_is_complete ? "" : "in"); + for (i = 0; i < fields->num_uuids128; i++) { + print_uuid(&fields->uuids128[i].u); + MODLOG_DFLT(DEBUG, " "); + } + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->name != NULL) { + assert(fields->name_len < sizeof s - 1); + memcpy(s, fields->name, fields->name_len); + s[fields->name_len] = '\0'; + MODLOG_DFLT(DEBUG, " name(%scomplete)=%s\n", + fields->name_is_complete ? "" : "in", s); + } + + if (fields->tx_pwr_lvl_is_present) { + MODLOG_DFLT(DEBUG, " tx_pwr_lvl=%d\n", fields->tx_pwr_lvl); + } + + if (fields->slave_itvl_range != NULL) { + MODLOG_DFLT(DEBUG, " slave_itvl_range="); + print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN); + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->svc_data_uuid16 != NULL) { + MODLOG_DFLT(DEBUG, " svc_data_uuid16="); + print_bytes(fields->svc_data_uuid16, fields->svc_data_uuid16_len); + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->public_tgt_addr != NULL) { + MODLOG_DFLT(DEBUG, " public_tgt_addr="); + u8p = fields->public_tgt_addr; + for (i = 0; i < fields->num_public_tgt_addrs; i++) { + MODLOG_DFLT(DEBUG, "public_tgt_addr=%s ", addr_str(u8p)); + u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN; + } + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->appearance_is_present) { + MODLOG_DFLT(DEBUG, " appearance=0x%04x\n", fields->appearance); + } + + if (fields->adv_itvl_is_present) { + MODLOG_DFLT(DEBUG, " adv_itvl=0x%04x\n", fields->adv_itvl); + } + + if (fields->svc_data_uuid32 != NULL) { + MODLOG_DFLT(DEBUG, " svc_data_uuid32="); + print_bytes(fields->svc_data_uuid32, fields->svc_data_uuid32_len); + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->svc_data_uuid128 != NULL) { + MODLOG_DFLT(DEBUG, " svc_data_uuid128="); + print_bytes(fields->svc_data_uuid128, fields->svc_data_uuid128_len); + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->uri != NULL) { + MODLOG_DFLT(DEBUG, " uri="); + print_bytes(fields->uri, fields->uri_len); + MODLOG_DFLT(DEBUG, "\n"); + } + + if (fields->mfg_data != NULL) { + MODLOG_DFLT(DEBUG, " mfg_data="); + print_bytes(fields->mfg_data, fields->mfg_data_len); + MODLOG_DFLT(DEBUG, "\n"); + } +} diff --git a/examples/bluetooth/nimble/blecent/main/peer.c b/examples/bluetooth/nimble/blecent/main/peer.c new file mode 100644 index 000000000..a01ae061e --- /dev/null +++ b/examples/bluetooth/nimble/blecent/main/peer.c @@ -0,0 +1,807 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "host/ble_hs.h" +#include "blecent.h" + +static void *peer_svc_mem; +static struct os_mempool peer_svc_pool; + +static void *peer_chr_mem; +static struct os_mempool peer_chr_pool; + +static void *peer_dsc_mem; +static struct os_mempool peer_dsc_pool; + +static void *peer_mem; +static struct os_mempool peer_pool; +static SLIST_HEAD(, peer) peers; + +static struct peer_svc * +peer_svc_find_range(struct peer *peer, uint16_t attr_handle); +static struct peer_svc * +peer_svc_find(struct peer *peer, uint16_t svc_start_handle, + struct peer_svc **out_prev); +int +peer_svc_is_empty(const struct peer_svc *svc); + +uint16_t +chr_end_handle(const struct peer_svc *svc, const struct peer_chr *chr); +int +chr_is_empty(const struct peer_svc *svc, const struct peer_chr *chr); +static struct peer_chr * +peer_chr_find(const struct peer_svc *svc, uint16_t chr_def_handle, + struct peer_chr **out_prev); +static void +peer_disc_chrs(struct peer *peer); + +static int +peer_dsc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, + uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, + void *arg); + +struct peer * +peer_find(uint16_t conn_handle) +{ + struct peer *peer; + + SLIST_FOREACH(peer, &peers, next) { + if (peer->conn_handle == conn_handle) { + return peer; + } + } + + return NULL; +} + +static void +peer_disc_complete(struct peer *peer, int rc) +{ + peer->disc_prev_chr_val = 0; + + /* Notify caller that discovery has completed. */ + if (peer->disc_cb != NULL) { + peer->disc_cb(peer, rc, peer->disc_cb_arg); + } +} + +static struct peer_dsc * +peer_dsc_find_prev(const struct peer_chr *chr, uint16_t dsc_handle) +{ + struct peer_dsc *prev; + struct peer_dsc *dsc; + + prev = NULL; + SLIST_FOREACH(dsc, &chr->dscs, next) { + if (dsc->dsc.handle >= dsc_handle) { + break; + } + + prev = dsc; + } + + return prev; +} + +static struct peer_dsc * +peer_dsc_find(const struct peer_chr *chr, uint16_t dsc_handle, + struct peer_dsc **out_prev) +{ + struct peer_dsc *prev; + struct peer_dsc *dsc; + + prev = peer_dsc_find_prev(chr, dsc_handle); + if (prev == NULL) { + dsc = SLIST_FIRST(&chr->dscs); + } else { + dsc = SLIST_NEXT(prev, next); + } + + if (dsc != NULL && dsc->dsc.handle != dsc_handle) { + dsc = NULL; + } + + if (out_prev != NULL) { + *out_prev = prev; + } + return dsc; +} + +static int +peer_dsc_add(struct peer *peer, uint16_t chr_val_handle, + const struct ble_gatt_dsc *gatt_dsc) +{ + struct peer_dsc *prev; + struct peer_dsc *dsc; + struct peer_svc *svc; + struct peer_chr *chr; + + svc = peer_svc_find_range(peer, chr_val_handle); + if (svc == NULL) { + /* Can't find service for discovered descriptor; this shouldn't + * happen. + */ + assert(0); + return BLE_HS_EUNKNOWN; + } + + chr = peer_chr_find(svc, chr_val_handle, NULL); + if (chr == NULL) { + /* Can't find characteristic for discovered descriptor; this shouldn't + * happen. + */ + assert(0); + return BLE_HS_EUNKNOWN; + } + + dsc = peer_dsc_find(chr, gatt_dsc->handle, &prev); + if (dsc != NULL) { + /* Descriptor already discovered. */ + return 0; + } + + dsc = os_memblock_get(&peer_dsc_pool); + if (dsc == NULL) { + /* Out of memory. */ + return BLE_HS_ENOMEM; + } + memset(dsc, 0, sizeof * dsc); + + dsc->dsc = *gatt_dsc; + + if (prev == NULL) { + SLIST_INSERT_HEAD(&chr->dscs, dsc, next); + } else { + SLIST_NEXT(prev, next) = dsc; + } + + return 0; +} + +static void +peer_disc_dscs(struct peer *peer) +{ + struct peer_chr *chr; + struct peer_svc *svc; + int rc; + + /* Search through the list of discovered characteristics for the first + * characteristic that contains undiscovered descriptors. Then, discover + * all descriptors belonging to that characteristic. + */ + SLIST_FOREACH(svc, &peer->svcs, next) { + SLIST_FOREACH(chr, &svc->chrs, next) { + if (!chr_is_empty(svc, chr) && + SLIST_EMPTY(&chr->dscs) && + peer->disc_prev_chr_val <= chr->chr.def_handle) { + + rc = ble_gattc_disc_all_dscs(peer->conn_handle, + chr->chr.val_handle, + chr_end_handle(svc, chr), + peer_dsc_disced, peer); + if (rc != 0) { + peer_disc_complete(peer, rc); + } + + peer->disc_prev_chr_val = chr->chr.val_handle; + return; + } + } + } + + /* All descriptors discovered. */ + peer_disc_complete(peer, 0); +} + +static int +peer_dsc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, + uint16_t chr_val_handle, const struct ble_gatt_dsc *dsc, + void *arg) +{ + struct peer *peer; + int rc; + + peer = arg; + assert(peer->conn_handle == conn_handle); + + switch (error->status) { + case 0: + rc = peer_dsc_add(peer, chr_val_handle, dsc); + break; + + case BLE_HS_EDONE: + /* All descriptors in this characteristic discovered; start discovering + * descriptors in the next characteristic. + */ + if (peer->disc_prev_chr_val > 0) { + peer_disc_dscs(peer); + } + rc = 0; + break; + + default: + /* Error; abort discovery. */ + rc = error->status; + break; + } + + if (rc != 0) { + /* Error; abort discovery. */ + peer_disc_complete(peer, rc); + } + + return rc; +} + +uint16_t +chr_end_handle(const struct peer_svc *svc, const struct peer_chr *chr) +{ + const struct peer_chr *next_chr; + + next_chr = SLIST_NEXT(chr, next); + if (next_chr != NULL) { + return next_chr->chr.def_handle - 1; + } else { + return svc->svc.end_handle; + } +} + +int +chr_is_empty(const struct peer_svc *svc, const struct peer_chr *chr) +{ + return chr_end_handle(svc, chr) <= chr->chr.val_handle; +} + +static struct peer_chr * +peer_chr_find_prev(const struct peer_svc *svc, uint16_t chr_val_handle) +{ + struct peer_chr *prev; + struct peer_chr *chr; + + prev = NULL; + SLIST_FOREACH(chr, &svc->chrs, next) { + if (chr->chr.val_handle >= chr_val_handle) { + break; + } + + prev = chr; + } + + return prev; +} + +static struct peer_chr * +peer_chr_find(const struct peer_svc *svc, uint16_t chr_val_handle, + struct peer_chr **out_prev) +{ + struct peer_chr *prev; + struct peer_chr *chr; + + prev = peer_chr_find_prev(svc, chr_val_handle); + if (prev == NULL) { + chr = SLIST_FIRST(&svc->chrs); + } else { + chr = SLIST_NEXT(prev, next); + } + + if (chr != NULL && chr->chr.val_handle != chr_val_handle) { + chr = NULL; + } + + if (out_prev != NULL) { + *out_prev = prev; + } + return chr; +} + +static void +peer_chr_delete(struct peer_chr *chr) +{ + struct peer_dsc *dsc; + + while ((dsc = SLIST_FIRST(&chr->dscs)) != NULL) { + SLIST_REMOVE_HEAD(&chr->dscs, next); + os_memblock_put(&peer_dsc_pool, dsc); + } + + os_memblock_put(&peer_chr_pool, chr); +} + +static int +peer_chr_add(struct peer *peer, uint16_t svc_start_handle, + const struct ble_gatt_chr *gatt_chr) +{ + struct peer_chr *prev; + struct peer_chr *chr; + struct peer_svc *svc; + + svc = peer_svc_find(peer, svc_start_handle, NULL); + if (svc == NULL) { + /* Can't find service for discovered characteristic; this shouldn't + * happen. + */ + assert(0); + return BLE_HS_EUNKNOWN; + } + + chr = peer_chr_find(svc, gatt_chr->def_handle, &prev); + if (chr != NULL) { + /* Characteristic already discovered. */ + return 0; + } + + chr = os_memblock_get(&peer_chr_pool); + if (chr == NULL) { + /* Out of memory. */ + return BLE_HS_ENOMEM; + } + memset(chr, 0, sizeof * chr); + + chr->chr = *gatt_chr; + + if (prev == NULL) { + SLIST_INSERT_HEAD(&svc->chrs, chr, next); + } else { + SLIST_NEXT(prev, next) = chr; + } + + return 0; +} + +static int +peer_chr_disced(uint16_t conn_handle, const struct ble_gatt_error *error, + const struct ble_gatt_chr *chr, void *arg) +{ + struct peer *peer; + int rc; + + peer = arg; + assert(peer->conn_handle == conn_handle); + + switch (error->status) { + case 0: + rc = peer_chr_add(peer, peer->cur_svc->svc.start_handle, chr); + break; + + case BLE_HS_EDONE: + /* All characteristics in this service discovered; start discovering + * characteristics in the next service. + */ + if (peer->disc_prev_chr_val > 0) { + peer_disc_chrs(peer); + } + rc = 0; + break; + + default: + rc = error->status; + break; + } + + if (rc != 0) { + /* Error; abort discovery. */ + peer_disc_complete(peer, rc); + } + + return rc; +} + +static void +peer_disc_chrs(struct peer *peer) +{ + struct peer_svc *svc; + int rc; + + /* Search through the list of discovered service for the first service that + * contains undiscovered characteristics. Then, discover all + * characteristics belonging to that service. + */ + SLIST_FOREACH(svc, &peer->svcs, next) { + if (!peer_svc_is_empty(svc) && SLIST_EMPTY(&svc->chrs)) { + peer->cur_svc = svc; + rc = ble_gattc_disc_all_chrs(peer->conn_handle, + svc->svc.start_handle, + svc->svc.end_handle, + peer_chr_disced, peer); + if (rc != 0) { + peer_disc_complete(peer, rc); + } + return; + } + } + + /* All characteristics discovered. */ + peer_disc_dscs(peer); +} + +int +peer_svc_is_empty(const struct peer_svc *svc) +{ + return svc->svc.end_handle <= svc->svc.start_handle; +} + +static struct peer_svc * +peer_svc_find_prev(struct peer *peer, uint16_t svc_start_handle) +{ + struct peer_svc *prev; + struct peer_svc *svc; + + prev = NULL; + SLIST_FOREACH(svc, &peer->svcs, next) { + if (svc->svc.start_handle >= svc_start_handle) { + break; + } + + prev = svc; + } + + return prev; +} + +static struct peer_svc * +peer_svc_find(struct peer *peer, uint16_t svc_start_handle, + struct peer_svc **out_prev) +{ + struct peer_svc *prev; + struct peer_svc *svc; + + prev = peer_svc_find_prev(peer, svc_start_handle); + if (prev == NULL) { + svc = SLIST_FIRST(&peer->svcs); + } else { + svc = SLIST_NEXT(prev, next); + } + + if (svc != NULL && svc->svc.start_handle != svc_start_handle) { + svc = NULL; + } + + if (out_prev != NULL) { + *out_prev = prev; + } + return svc; +} + +static struct peer_svc * +peer_svc_find_range(struct peer *peer, uint16_t attr_handle) +{ + struct peer_svc *svc; + + SLIST_FOREACH(svc, &peer->svcs, next) { + if (svc->svc.start_handle <= attr_handle && + svc->svc.end_handle >= attr_handle) { + + return svc; + } + } + + return NULL; +} + +const struct peer_svc * +peer_svc_find_uuid(const struct peer *peer, const ble_uuid_t *uuid) +{ + const struct peer_svc *svc; + + SLIST_FOREACH(svc, &peer->svcs, next) { + if (ble_uuid_cmp(&svc->svc.uuid.u, uuid) == 0) { + return svc; + } + } + + return NULL; +} + +const struct peer_chr * +peer_chr_find_uuid(const struct peer *peer, const ble_uuid_t *svc_uuid, + const ble_uuid_t *chr_uuid) +{ + const struct peer_svc *svc; + const struct peer_chr *chr; + + svc = peer_svc_find_uuid(peer, svc_uuid); + if (svc == NULL) { + return NULL; + } + + SLIST_FOREACH(chr, &svc->chrs, next) { + if (ble_uuid_cmp(&chr->chr.uuid.u, chr_uuid) == 0) { + return chr; + } + } + + return NULL; +} + +const struct peer_dsc * +peer_dsc_find_uuid(const struct peer *peer, const ble_uuid_t *svc_uuid, + const ble_uuid_t *chr_uuid, const ble_uuid_t *dsc_uuid) +{ + const struct peer_chr *chr; + const struct peer_dsc *dsc; + + chr = peer_chr_find_uuid(peer, svc_uuid, chr_uuid); + if (chr == NULL) { + return NULL; + } + + SLIST_FOREACH(dsc, &chr->dscs, next) { + if (ble_uuid_cmp(&dsc->dsc.uuid.u, dsc_uuid) == 0) { + return dsc; + } + } + + return NULL; +} + +static int +peer_svc_add(struct peer *peer, const struct ble_gatt_svc *gatt_svc) +{ + struct peer_svc *prev; + struct peer_svc *svc; + + svc = peer_svc_find(peer, gatt_svc->start_handle, &prev); + if (svc != NULL) { + /* Service already discovered. */ + return 0; + } + + svc = os_memblock_get(&peer_svc_pool); + if (svc == NULL) { + /* Out of memory. */ + return BLE_HS_ENOMEM; + } + memset(svc, 0, sizeof * svc); + + svc->svc = *gatt_svc; + SLIST_INIT(&svc->chrs); + + if (prev == NULL) { + SLIST_INSERT_HEAD(&peer->svcs, svc, next); + } else { + SLIST_INSERT_AFTER(prev, svc, next); + } + + return 0; +} + +static void +peer_svc_delete(struct peer_svc *svc) +{ + struct peer_chr *chr; + + while ((chr = SLIST_FIRST(&svc->chrs)) != NULL) { + SLIST_REMOVE_HEAD(&svc->chrs, next); + peer_chr_delete(chr); + } + + os_memblock_put(&peer_svc_pool, svc); +} + +static int +peer_svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, + const struct ble_gatt_svc *service, void *arg) +{ + struct peer *peer; + int rc; + + peer = arg; + assert(peer->conn_handle == conn_handle); + + switch (error->status) { + case 0: + rc = peer_svc_add(peer, service); + break; + + case BLE_HS_EDONE: + /* All services discovered; start discovering characteristics. */ + if (peer->disc_prev_chr_val > 0) { + peer_disc_chrs(peer); + } + rc = 0; + break; + + default: + rc = error->status; + break; + } + + if (rc != 0) { + /* Error; abort discovery. */ + peer_disc_complete(peer, rc); + } + + return rc; +} + + +int +peer_disc_all(uint16_t conn_handle, peer_disc_fn *disc_cb, void *disc_cb_arg) +{ + struct peer_svc *svc; + struct peer *peer; + int rc; + + peer = peer_find(conn_handle); + if (peer == NULL) { + return BLE_HS_ENOTCONN; + } + + /* Undiscover everything first. */ + while ((svc = SLIST_FIRST(&peer->svcs)) != NULL) { + SLIST_REMOVE_HEAD(&peer->svcs, next); + peer_svc_delete(svc); + } + + peer->disc_prev_chr_val = 1; + peer->disc_cb = disc_cb; + peer->disc_cb_arg = disc_cb_arg; + + rc = ble_gattc_disc_all_svcs(conn_handle, peer_svc_disced, peer); + if (rc != 0) { + return rc; + } + + return 0; +} + +int +peer_delete(uint16_t conn_handle) +{ + struct peer_svc *svc; + struct peer *peer; + int rc; + + peer = peer_find(conn_handle); + if (peer == NULL) { + return BLE_HS_ENOTCONN; + } + + SLIST_REMOVE(&peers, peer, peer, next); + + while ((svc = SLIST_FIRST(&peer->svcs)) != NULL) { + SLIST_REMOVE_HEAD(&peer->svcs, next); + peer_svc_delete(svc); + } + + rc = os_memblock_put(&peer_pool, peer); + if (rc != 0) { + return BLE_HS_EOS; + } + + return 0; +} + +int +peer_add(uint16_t conn_handle) +{ + struct peer *peer; + + /* Make sure the connection handle is unique. */ + peer = peer_find(conn_handle); + if (peer != NULL) { + return BLE_HS_EALREADY; + } + + peer = os_memblock_get(&peer_pool); + if (peer == NULL) { + /* Out of memory. */ + return BLE_HS_ENOMEM; + } + + memset(peer, 0, sizeof * peer); + peer->conn_handle = conn_handle; + + SLIST_INSERT_HEAD(&peers, peer, next); + + return 0; +} + +static void +peer_free_mem(void) +{ + free(peer_mem); + peer_mem = NULL; + + free(peer_svc_mem); + peer_svc_mem = NULL; + + free(peer_chr_mem); + peer_chr_mem = NULL; + + free(peer_dsc_mem); + peer_dsc_mem = NULL; +} + +int +peer_init(int max_peers, int max_svcs, int max_chrs, int max_dscs) +{ + int rc; + + /* Free memory first in case this function gets called more than once. */ + peer_free_mem(); + + peer_mem = malloc( + OS_MEMPOOL_BYTES(max_peers, sizeof (struct peer))); + if (peer_mem == NULL) { + rc = BLE_HS_ENOMEM; + goto err; + } + + rc = os_mempool_init(&peer_pool, max_peers, + sizeof (struct peer), peer_mem, + "peer_pool"); + if (rc != 0) { + rc = BLE_HS_EOS; + goto err; + } + + peer_svc_mem = malloc( + OS_MEMPOOL_BYTES(max_svcs, sizeof (struct peer_svc))); + if (peer_svc_mem == NULL) { + rc = BLE_HS_ENOMEM; + goto err; + } + + rc = os_mempool_init(&peer_svc_pool, max_svcs, + sizeof (struct peer_svc), peer_svc_mem, + "peer_svc_pool"); + if (rc != 0) { + rc = BLE_HS_EOS; + goto err; + } + + peer_chr_mem = malloc( + OS_MEMPOOL_BYTES(max_chrs, sizeof (struct peer_chr))); + if (peer_chr_mem == NULL) { + rc = BLE_HS_ENOMEM; + goto err; + } + + rc = os_mempool_init(&peer_chr_pool, max_chrs, + sizeof (struct peer_chr), peer_chr_mem, + "peer_chr_pool"); + if (rc != 0) { + rc = BLE_HS_EOS; + goto err; + } + + peer_dsc_mem = malloc( + OS_MEMPOOL_BYTES(max_dscs, sizeof (struct peer_dsc))); + if (peer_dsc_mem == NULL) { + rc = BLE_HS_ENOMEM; + goto err; + } + + rc = os_mempool_init(&peer_dsc_pool, max_dscs, + sizeof (struct peer_dsc), peer_dsc_mem, + "peer_dsc_pool"); + if (rc != 0) { + rc = BLE_HS_EOS; + goto err; + } + + return 0; + +err: + peer_free_mem(); + return rc; +} diff --git a/examples/bluetooth/nimble/blecent/sdkconfig.defaults b/examples/bluetooth/nimble/blecent/sdkconfig.defaults new file mode 100644 index 000000000..4fa07777f --- /dev/null +++ b/examples/bluetooth/nimble/blecent/sdkconfig.defaults @@ -0,0 +1,12 @@ +# Override some defaults so BT stack is enabled +# in this example + +# +# BT config +# +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY= +CONFIG_BTDM_CTRL_MODE_BTDM= +CONFIG_BT_BLUEDROID_ENABLED= +CONFIG_BT_NIMBLE_ENABLED=y diff --git a/examples/bluetooth/nimble/blehr/CMakeLists.txt b/examples/bluetooth/nimble/blehr/CMakeLists.txt new file mode 100644 index 000000000..62f79f523 --- /dev/null +++ b/examples/bluetooth/nimble/blehr/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(blehr) diff --git a/examples/bluetooth/nimble/blehr/Makefile b/examples/bluetooth/nimble/blehr/Makefile new file mode 100644 index 000000000..85522df5e --- /dev/null +++ b/examples/bluetooth/nimble/blehr/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := blehr + +include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/nimble/blehr/README.md b/examples/bluetooth/nimble/blehr/README.md new file mode 100644 index 000000000..29a773d96 --- /dev/null +++ b/examples/bluetooth/nimble/blehr/README.md @@ -0,0 +1,61 @@ +# BLE Heart Rate Measurement example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example creates GATT server demonstrating standard Heart Rate measurement service. It simulates Hear rate measurement and notifies to client when the notifications are enabled. + +It uses ESP32's Bluetooth controller and NimBLE stack based BLE host + +This example aims at understanding notification subscriptions and sending notifications. + +To test this demo, any BLE scanner app can be used. + + +## How to use example + +### Configure the project + +``` +make menuconfig +``` + +* Set serial port under Serial Flasher Options. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +make -j4 flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +This console output can be observed when blehr is connected to client and client enables notifications: + +``` +I (91) BTDM_INIT: BT controller compile version [fe7ced0] +I (91) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (181) phy: phy_version: 4100, 6fa5e27, Jan 25 2019, 17:02:06, 0, 0 +I (421) NimBLE_BLE_HeartRate: BLE Host Task Started +GAP procedure initiated: stop advertising. +Device Address: xx:xx:xx:xx:xx:xx +GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=0 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=0 adv_itvl_max=0 +connection established; status=0 +subscribe event; cur_notify=1 + value handle; val_handle=3 +I (21611) BLE_GAP_SUBSCRIBE_EVENT: conn_handle from subscribe=0 +GATT procedure initiated: notify; att_handle=3 +GATT procedure initiated: notify; att_handle=3 +GATT procedure initiated: notify; att_handle=3 +GATT procedure initiated: notify; att_handle=3 +GATT procedure initiated: notify; att_handle=3 +GATT procedure initiated: notify; att_handle=3 +GATT procedure initiated: notify; att_handle=3 + +``` + diff --git a/examples/bluetooth/nimble/blehr/main/CMakeLists.txt b/examples/bluetooth/nimble/blehr/main/CMakeLists.txt new file mode 100644 index 000000000..9c74274ab --- /dev/null +++ b/examples/bluetooth/nimble/blehr/main/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCS "main.c" + "gatt_svr.c") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/bluetooth/nimble/blehr/main/blehr_sens.h b/examples/bluetooth/nimble/blehr/main/blehr_sens.h new file mode 100644 index 000000000..60e72a491 --- /dev/null +++ b/examples/bluetooth/nimble/blehr/main/blehr_sens.h @@ -0,0 +1,50 @@ +/* + * 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_BLEHR_SENSOR_ +#define H_BLEHR_SENSOR_ + +#include "nimble/ble.h" +#include "modlog/modlog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Heart-rate configuration */ +#define GATT_HRS_UUID 0x180D +#define GATT_HRS_MEASUREMENT_UUID 0x2A37 +#define GATT_HRS_BODY_SENSOR_LOC_UUID 0x2A38 +#define GATT_DEVICE_INFO_UUID 0x180A +#define GATT_MANUFACTURER_NAME_UUID 0x2A29 +#define GATT_MODEL_NUMBER_UUID 0x2A24 + +extern uint16_t hrs_hrm_handle; + +struct ble_hs_cfg; +struct ble_gatt_register_ctxt; + +void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); +int gatt_svr_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/bluetooth/nimble/blehr/main/component.mk b/examples/bluetooth/nimble/blehr/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/bluetooth/nimble/blehr/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/bluetooth/nimble/blehr/main/gatt_svr.c b/examples/bluetooth/nimble/blehr/main/gatt_svr.c new file mode 100644 index 000000000..13fcd3698 --- /dev/null +++ b/examples/bluetooth/nimble/blehr/main/gatt_svr.c @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include "host/ble_hs.h" +#include "host/ble_uuid.h" +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" +#include "blehr_sens.h" + +static const char *manuf_name = "Apache Mynewt ESP32 devkitC"; +static const char *model_num = "Mynewt HR Sensor demo"; +uint16_t hrs_hrm_handle; + +static int +gatt_svr_chr_access_heart_rate(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + +static int +gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + +static const struct ble_gatt_svc_def gatt_svr_svcs[] = { + { + /* Service: Heart-rate */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(GATT_HRS_UUID), + .characteristics = (struct ble_gatt_chr_def[]) + { { + /* Characteristic: Heart-rate measurement */ + .uuid = BLE_UUID16_DECLARE(GATT_HRS_MEASUREMENT_UUID), + .access_cb = gatt_svr_chr_access_heart_rate, + .val_handle = &hrs_hrm_handle, + .flags = BLE_GATT_CHR_F_NOTIFY, + }, { + /* Characteristic: Body sensor location */ + .uuid = BLE_UUID16_DECLARE(GATT_HRS_BODY_SENSOR_LOC_UUID), + .access_cb = gatt_svr_chr_access_heart_rate, + .flags = BLE_GATT_CHR_F_READ, + }, { + 0, /* No more characteristics in this service */ + }, + } + }, + + { + /* Service: Device Information */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(GATT_DEVICE_INFO_UUID), + .characteristics = (struct ble_gatt_chr_def[]) + { { + /* Characteristic: * Manufacturer name */ + .uuid = BLE_UUID16_DECLARE(GATT_MANUFACTURER_NAME_UUID), + .access_cb = gatt_svr_chr_access_device_info, + .flags = BLE_GATT_CHR_F_READ, + }, { + /* Characteristic: Model number string */ + .uuid = BLE_UUID16_DECLARE(GATT_MODEL_NUMBER_UUID), + .access_cb = gatt_svr_chr_access_device_info, + .flags = BLE_GATT_CHR_F_READ, + }, { + 0, /* No more characteristics in this service */ + }, + } + }, + + { + 0, /* No more services */ + }, +}; + +static int +gatt_svr_chr_access_heart_rate(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + /* Sensor location, set to "Chest" */ + static uint8_t body_sens_loc = 0x01; + uint16_t uuid; + int rc; + + uuid = ble_uuid_u16(ctxt->chr->uuid); + + if (uuid == GATT_HRS_BODY_SENSOR_LOC_UUID) { + rc = os_mbuf_append(ctxt->om, &body_sens_loc, sizeof(body_sens_loc)); + + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + + assert(0); + return BLE_ATT_ERR_UNLIKELY; +} + +static int +gatt_svr_chr_access_device_info(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) +{ + uint16_t uuid; + int rc; + + uuid = ble_uuid_u16(ctxt->chr->uuid); + + if (uuid == GATT_MODEL_NUMBER_UUID) { + rc = os_mbuf_append(ctxt->om, model_num, strlen(model_num)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + + if (uuid == GATT_MANUFACTURER_NAME_UUID) { + rc = os_mbuf_append(ctxt->om, manuf_name, strlen(manuf_name)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + + assert(0); + return BLE_ATT_ERR_UNLIKELY; +} + +void +gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) +{ + char buf[BLE_UUID_STR_LEN]; + + switch (ctxt->op) { + case BLE_GATT_REGISTER_OP_SVC: + MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n", + ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf), + ctxt->svc.handle); + break; + + case BLE_GATT_REGISTER_OP_CHR: + MODLOG_DFLT(DEBUG, "registering characteristic %s with " + "def_handle=%d val_handle=%d\n", + ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), + ctxt->chr.def_handle, + ctxt->chr.val_handle); + break; + + case BLE_GATT_REGISTER_OP_DSC: + MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n", + ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf), + ctxt->dsc.handle); + break; + + default: + assert(0); + break; + } +} + +int +gatt_svr_init(void) +{ + int rc; + + ble_svc_gap_init(); + ble_svc_gatt_init(); + + rc = ble_gatts_count_cfg(gatt_svr_svcs); + if (rc != 0) { + return rc; + } + + rc = ble_gatts_add_svcs(gatt_svr_svcs); + if (rc != 0) { + return rc; + } + + return 0; +} + diff --git a/examples/bluetooth/nimble/blehr/main/main.c b/examples/bluetooth/nimble/blehr/main/main.c new file mode 100644 index 000000000..ca5b8d4df --- /dev/null +++ b/examples/bluetooth/nimble/blehr/main/main.c @@ -0,0 +1,304 @@ +/* + * 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 "esp_log.h" +#include "nvs_flash.h" +#include "freertos/FreeRTOSConfig.h" +/* BLE */ +#include "esp_nimble_hci.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "console/console.h" +#include "services/gap/ble_svc_gap.h" +#include "blehr_sens.h" + +static const char *tag = "NimBLE_BLE_HeartRate"; + +static xTimerHandle blehr_tx_timer; + +static bool notify_state; + +static uint16_t conn_handle; + +static const char *device_name = "blehr_sensor_1.0"; + +static int blehr_gap_event(struct ble_gap_event *event, void *arg); + +static uint8_t blehr_addr_type; + +/* Variable to simulate heart beats */ +static uint8_t heartrate = 90; + +/** + * Utility function to log an array of bytes. + */ +void +print_bytes(const uint8_t *bytes, int len) +{ + int i; + for (i = 0; i < len; i++) { + MODLOG_DFLT(INFO, "%s0x%02x", i != 0 ? ":" : "", bytes[i]); + } +} + +void +print_addr(const void *addr) +{ + const uint8_t *u8p; + + u8p = addr; + MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x", + u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]); +} + + +/* + * Enables advertising with parameters: + * o General discoverable mode + * o Undirected connectable mode + */ +static void +blehr_advertise(void) +{ + struct ble_gap_adv_params adv_params; + struct ble_hs_adv_fields fields; + int rc; + + /* + * Set the advertisement data included in our advertisements: + * o Flags (indicates advertisement type and other general info) + * o Advertising tx power + * o Device name + */ + memset(&fields, 0, sizeof(fields)); + + /* + * Advertise two flags: + * o Discoverability in forthcoming advertisement (general) + * o BLE-only (BR/EDR unsupported) + */ + fields.flags = BLE_HS_ADV_F_DISC_GEN | + BLE_HS_ADV_F_BREDR_UNSUP; + + /* + * Indicate that the TX power level field should be included; have the + * stack fill this value automatically. This is done by assigning the + * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. + */ + fields.tx_pwr_lvl_is_present = 1; + fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + + fields.name = (uint8_t *)device_name; + fields.name_len = strlen(device_name); + fields.name_is_complete = 1; + + rc = ble_gap_adv_set_fields(&fields); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc); + return; + } + + /* Begin advertising */ + memset(&adv_params, 0, sizeof(adv_params)); + adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; + adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; + rc = ble_gap_adv_start(blehr_addr_type, NULL, BLE_HS_FOREVER, + &adv_params, blehr_gap_event, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc); + return; + } +} + +static void +blehr_tx_hrate_stop(void) +{ + xTimerStop( blehr_tx_timer, 1000 / portTICK_PERIOD_MS ); +} + +/* Reset heartrate measurment */ +static void +blehr_tx_hrate_reset(void) +{ + int rc; + + if (xTimerReset(blehr_tx_timer, 1000 / portTICK_PERIOD_MS ) == pdPASS) { + rc = 0; + } else { + rc = 1; + } + + assert(rc == 0); + +} + +/* This function simulates heart beat and notifies it to the client */ +static void +blehr_tx_hrate(xTimerHandle ev) +{ + static uint8_t hrm[2]; + int rc; + struct os_mbuf *om; + + if (!notify_state) { + blehr_tx_hrate_stop(); + heartrate = 90; + return; + } + + hrm[0] = 0x06; /* contact of a sensor */ + hrm[1] = heartrate; /* storing dummy data */ + + /* Simulation of heart beats */ + heartrate++; + if (heartrate == 160) { + heartrate = 90; + } + + om = ble_hs_mbuf_from_flat(hrm, sizeof(hrm)); + rc = ble_gattc_notify_custom(conn_handle, hrs_hrm_handle, om); + + assert(rc == 0); + + blehr_tx_hrate_reset(); +} + +static int +blehr_gap_event(struct ble_gap_event *event, void *arg) +{ + switch (event->type) { + case BLE_GAP_EVENT_CONNECT: + /* A new connection was established or a connection attempt failed */ + MODLOG_DFLT(INFO, "connection %s; status=%d\n", + event->connect.status == 0 ? "established" : "failed", + event->connect.status); + + if (event->connect.status != 0) { + /* Connection failed; resume advertising */ + blehr_advertise(); + } + conn_handle = event->connect.conn_handle; + break; + + case BLE_GAP_EVENT_DISCONNECT: + MODLOG_DFLT(INFO, "disconnect; reason=%d\n", event->disconnect.reason); + + /* Connection terminated; resume advertising */ + blehr_advertise(); + break; + + case BLE_GAP_EVENT_ADV_COMPLETE: + MODLOG_DFLT(INFO, "adv complete\n"); + blehr_advertise(); + break; + + case BLE_GAP_EVENT_SUBSCRIBE: + MODLOG_DFLT(INFO, "subscribe event; cur_notify=%d\n value handle; " + "val_handle=%d\n", + event->subscribe.cur_notify, hrs_hrm_handle); + if (event->subscribe.attr_handle == hrs_hrm_handle) { + notify_state = event->subscribe.cur_notify; + blehr_tx_hrate_reset(); + } else if (event->subscribe.attr_handle != hrs_hrm_handle) { + notify_state = event->subscribe.cur_notify; + blehr_tx_hrate_stop(); + } + ESP_LOGI("BLE_GAP_SUBSCRIBE_EVENT", "conn_handle from subscribe=%d", conn_handle); + break; + + case BLE_GAP_EVENT_MTU: + MODLOG_DFLT(INFO, "mtu update event; conn_handle=%d mtu=%d\n", + event->mtu.conn_handle, + event->mtu.value); + break; + + } + + return 0; +} + +static void +blehr_on_sync(void) +{ + int rc; + + rc = ble_hs_id_infer_auto(0, &blehr_addr_type); + assert(rc == 0); + + uint8_t addr_val[6] = {0}; + rc = ble_hs_id_copy_addr(blehr_addr_type, addr_val, NULL); + + MODLOG_DFLT(INFO, "Device Address: "); + print_addr(addr_val); + MODLOG_DFLT(INFO, "\n"); + + /* Begin advertising */ + blehr_advertise(); +} + +static void +blehr_on_reset(int reason) +{ + MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason); +} + +void blehr_host_task(void *param) +{ + ESP_LOGI(tag, "BLE Host Task Started"); + /* This function will return only when nimble_port_stop() is executed */ + nimble_port_run(); + + nimble_port_freertos_deinit(); +} + +void app_main(void) +{ + int rc; + + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init()); + + nimble_port_init(); + /* Initialize the NimBLE host configuration */ + ble_hs_cfg.sync_cb = blehr_on_sync; + ble_hs_cfg.reset_cb = blehr_on_reset; + + /* name, period/time, auto reload, timer ID, callback */ + blehr_tx_timer = xTimerCreate("blehr_tx_timer", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, blehr_tx_hrate); + + rc = gatt_svr_init(); + assert(rc == 0); + + /* Set the default device name */ + rc = ble_svc_gap_device_name_set(device_name); + assert(rc == 0); + + /* Start the task */ + nimble_port_freertos_init(blehr_host_task); + +} diff --git a/examples/bluetooth/nimble/blehr/sdkconfig.defaults b/examples/bluetooth/nimble/blehr/sdkconfig.defaults new file mode 100644 index 000000000..4fa07777f --- /dev/null +++ b/examples/bluetooth/nimble/blehr/sdkconfig.defaults @@ -0,0 +1,12 @@ +# Override some defaults so BT stack is enabled +# in this example + +# +# BT config +# +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY= +CONFIG_BTDM_CTRL_MODE_BTDM= +CONFIG_BT_BLUEDROID_ENABLED= +CONFIG_BT_NIMBLE_ENABLED=y diff --git a/examples/bluetooth/nimble/blemesh/CMakeLists.txt b/examples/bluetooth/nimble/blemesh/CMakeLists.txt new file mode 100644 index 000000000..d1341c6ea --- /dev/null +++ b/examples/bluetooth/nimble/blemesh/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ble_mesh) diff --git a/examples/bluetooth/nimble/blemesh/Makefile b/examples/bluetooth/nimble/blemesh/Makefile new file mode 100644 index 000000000..bba3cb615 --- /dev/null +++ b/examples/bluetooth/nimble/blemesh/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := ble_mesh + +include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/nimble/blemesh/README.md b/examples/bluetooth/nimble/blemesh/README.md new file mode 100644 index 000000000..0f991b599 --- /dev/null +++ b/examples/bluetooth/nimble/blemesh/README.md @@ -0,0 +1,89 @@ +# BLE Mesh example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example implements Bluetooth Mesh node that supports On/Off and Level models. + +It has suport for both Advertising Bearer and GATT Bearer. + +For more information on NimBLE MESH, please visit [NimBLE_MESH](https://mynewt.apache.org/latest/network/docs/mesh/index.html#bluetooth-mesh). + +It uses ESP32's Bluetooth controller and NimBLE stack based BLE host. + +This example can be starting step to get basic understanding on how to build BLE MESH node. + +To test this demo, any BLE mesh provisioner app can be used. + + +## How to use example + +### Configure the project + +``` +make menuconfig +``` + +* Set serial port under Serial Flasher Options. + +* Select 'Enable BLE mesh functionality' under 'Component config > Bluetooth > Enable NimBLE host stack'. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +make -j4 flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +There is this console output on successful BLE provisioning: +``` +I (285) BTDM_INIT: BT controller compile version [8e87ec7] +I (285) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (355) phy: phy_version: 4000, b6198fa, Sep 3 2018, 15:11:06, 0, 0 +GAP procedure initiated: stop advertising. +I (625) NimBLE_MESH: Bluetooth initialized + +GAP procedure initiated: discovery; own_addr_type=1 filter_policy=0 passive=1 limited=0 filter_duplicates=0 duration=forever +I (895) NimBLE_MESH: Mesh initialized + +GAP procedure initiated: advertise; disc_mode=0 adv_channel_map=0 own_addr_type=1 adv_filter_policy=0 adv_itvl_min=160 adv_itvl_max=160 +GAP procedure initiated: stop advertising. +GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=0 own_addr_type=1 adv_filter_policy=0 adv_itvl_min=160 adv_itvl_max=240 +proxy_connected: conn_handle 0 +GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=0 own_addr_type=1 adv_filter_policy=0 adv_itvl_min=1600 adv_itvl_max=1920 +proxy_complete_pdu: Mesh Provisioning PDU +prov_invite: Attention Duration: 5 seconds +GATT procedure initiated: notify; att_handle=20 +proxy_complete_pdu: Mesh Provisioning PDU +prov_start: Algorithm: 0x00 +prov_start: Public Key: 0x00 +prov_start: Auth Method: 0x02 +prov_start: Auth Action: 0x00 +prov_start: Auth Size: 0x04 +I (6985) NimBLE_MESH: OOB Number: 5228 + +proxy_complete_pdu: Mesh Provisioning PDU +prov_pub_key: Remote Public Key: f56c5d5396a4d09cf1ea52e8217eba3b881202e73d09e9c4955903d5836d51b2117176fa5887869ddd5a2985dce9f706d3e4c2729dd9d45edeb86bcbebe4721c +GATT procedure initiated: notify; att_handle=20 +proxy_complete_pdu: Mesh Provisioning PDU +prov_confirm: Remote Confirm: ec7a9c169d23408abe051beca357abc1 +GATT procedure initiated: notify; att_handle=20 +proxy_complete_pdu: Mesh Provisioning PDU +prov_random: Remote Random: 05ca403997576097eb430588bf2b8448 +GATT procedure initiated: notify; att_handle=20 +proxy_complete_pdu: Mesh Provisioning PDU +GATT procedure initiated: notify; att_handle=20 +bt_mesh_provision: Primary Element: 0x0002 +GAP procedure initiated: stop advertising. +I (11885) NimBLE_MESH: Local node provisioned, primary address 0x0002 + +GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=0 own_addr_type=1 adv_filter_policy=0 adv_itvl_min=1600 adv_itvl_max=1920 +GAP procedure initiated: stop advertising. + +``` diff --git a/examples/bluetooth/nimble/blemesh/main/CMakeLists.txt b/examples/bluetooth/nimble/blemesh/main/CMakeLists.txt new file mode 100644 index 000000000..aea89ef0e --- /dev/null +++ b/examples/bluetooth/nimble/blemesh/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "app_mesh.c") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/bluetooth/nimble/blemesh/main/app_mesh.c b/examples/bluetooth/nimble/blemesh/main/app_mesh.c new file mode 100644 index 000000000..691019265 --- /dev/null +++ b/examples/bluetooth/nimble/blemesh/main/app_mesh.c @@ -0,0 +1,444 @@ +/* + * 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 "esp_log.h" +#include "nvs_flash.h" +#include "freertos/FreeRTOSConfig.h" +/* BLE */ +#include "esp_nimble_hci.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "console/console.h" +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" +#include "mesh/mesh.h" + +static const char *tag = "NimBLE_MESH"; +void ble_store_ram_init(void); + +#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG)) + +/* Company ID */ +#define CID_VENDOR 0x05C3 +#define STANDARD_TEST_ID 0x00 +#define TEST_ID 0x01 +static int recent_test_id = STANDARD_TEST_ID; + +#define FAULT_ARR_SIZE 2 + +static bool has_reg_fault = true; + + +static struct bt_mesh_cfg_srv cfg_srv = { + .relay = BT_MESH_RELAY_DISABLED, + .beacon = BT_MESH_BEACON_ENABLED, +#if MYNEWT_VAL(BLE_MESH_FRIEND) + .frnd = BT_MESH_FRIEND_ENABLED, +#endif +#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) + .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED, +#else + .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED, +#endif + .default_ttl = 7, + + /* 3 transmissions with 20ms interval */ + .net_transmit = BT_MESH_TRANSMIT(2, 20), + .relay_retransmit = BT_MESH_TRANSMIT(2, 20), +}; + +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) +{ + uint8_t reg_faults[FAULT_ARR_SIZE] = { [0 ... FAULT_ARR_SIZE - 1] = 0xff }; + + ESP_LOGI(tag, "fault_get_cur() has_reg_fault %u\n", has_reg_fault); + + *test_id = recent_test_id; + *company_id = CID_VENDOR; + + *fault_count = min(*fault_count, sizeof(reg_faults)); + memcpy(faults, reg_faults, *fault_count); + + return 0; +} + +static int +fault_get_reg(struct bt_mesh_model *model, + uint16_t company_id, + uint8_t *test_id, + uint8_t *faults, + uint8_t *fault_count) +{ + if (company_id != CID_VENDOR) { + return -BLE_HS_EINVAL; + } + + ESP_LOGI(tag, "fault_get_reg() has_reg_fault %u\n", has_reg_fault); + + *test_id = recent_test_id; + + if (has_reg_fault) { + uint8_t reg_faults[FAULT_ARR_SIZE] = { [0 ... FAULT_ARR_SIZE - 1] = 0xff }; + + *fault_count = min(*fault_count, sizeof(reg_faults)); + memcpy(faults, reg_faults, *fault_count); + } else { + *fault_count = 0; + } + + return 0; +} + +static int +fault_clear(struct bt_mesh_model *model, uint16_t company_id) +{ + if (company_id != CID_VENDOR) { + return -BLE_HS_EINVAL; + } + + has_reg_fault = false; + + return 0; +} + +static int +fault_test(struct bt_mesh_model *model, uint8_t test_id, uint16_t company_id) +{ + if (company_id != CID_VENDOR) { + return -BLE_HS_EINVAL; + } + + if (test_id != STANDARD_TEST_ID && test_id != TEST_ID) { + return -BLE_HS_EINVAL; + } + + recent_test_id = test_id; + has_reg_fault = true; + bt_mesh_fault_update(bt_mesh_model_elem(model)); + + 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(0); +} + +static struct bt_mesh_model_pub gen_level_pub; +static struct bt_mesh_model_pub gen_onoff_pub; + +static uint8_t gen_on_off_state; +static int16_t gen_level_state; + +static void gen_onoff_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx) +{ + struct os_mbuf *msg = NET_BUF_SIMPLE(3); + uint8_t *status; + + ESP_LOGI(tag, "#mesh-onoff STATUS\n"); + + bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x04)); + status = net_buf_simple_add(msg, 1); + *status = gen_on_off_state; + + if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + ESP_LOGI(tag, "#mesh-onoff STATUS: send status failed\n"); + } + + os_mbuf_free_chain(msg); +} + +static void gen_onoff_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + ESP_LOGI(tag, "#mesh-onoff GET\n"); + + gen_onoff_status(model, ctx); +} + +static void gen_onoff_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + ESP_LOGI(tag, "#mesh-onoff SET\n"); + + gen_on_off_state = buf->om_data[0]; + + gen_onoff_status(model, ctx); +} + +static void gen_onoff_set_unack(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + ESP_LOGI(tag, "#mesh-onoff SET-UNACK\n"); + + gen_on_off_state = buf->om_data[0]; +} + +static const struct bt_mesh_model_op gen_onoff_op[] = { + { BT_MESH_MODEL_OP_2(0x82, 0x01), 0, gen_onoff_get }, + { BT_MESH_MODEL_OP_2(0x82, 0x02), 2, gen_onoff_set }, + { BT_MESH_MODEL_OP_2(0x82, 0x03), 2, gen_onoff_set_unack }, + BT_MESH_MODEL_OP_END, +}; + +static void gen_level_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx) +{ + struct os_mbuf *msg = NET_BUF_SIMPLE(4); + + ESP_LOGI(tag, "#mesh-level STATUS\n"); + + bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_2(0x82, 0x08)); + net_buf_simple_add_le16(msg, gen_level_state); + + if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + ESP_LOGI(tag, "#mesh-level STATUS: send status failed\n"); + } + + os_mbuf_free_chain(msg); +} + +static void gen_level_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + ESP_LOGI(tag, "#mesh-level GET\n"); + + gen_level_status(model, ctx); +} + +static void gen_level_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + int16_t level; + + level = (int16_t) net_buf_simple_pull_le16(buf); + ESP_LOGI(tag, "#mesh-level SET: level=%d\n", level); + + gen_level_status(model, ctx); + + gen_level_state = level; + ESP_LOGI(tag, "#mesh-level: level=%d\n", gen_level_state); +} + +static void gen_level_set_unack(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + int16_t level; + + level = (int16_t) net_buf_simple_pull_le16(buf); + ESP_LOGI(tag, "#mesh-level SET-UNACK: level=%d\n", level); + + gen_level_state = level; + ESP_LOGI(tag, "#mesh-level: level=%d\n", gen_level_state); +} + +static void gen_delta_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + int16_t delta_level; + + delta_level = (int16_t) net_buf_simple_pull_le16(buf); + ESP_LOGI(tag, "#mesh-level DELTA-SET: delta_level=%d\n", delta_level); + + gen_level_status(model, ctx); + + gen_level_state += delta_level; + ESP_LOGI(tag, "#mesh-level: level=%d\n", gen_level_state); +} + +static void gen_delta_set_unack(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + int16_t delta_level; + + delta_level = (int16_t) net_buf_simple_pull_le16(buf); + ESP_LOGI(tag, "#mesh-level DELTA-SET: delta_level=%d\n", delta_level); + + gen_level_state += delta_level; + ESP_LOGI(tag, "#mesh-level: level=%d\n", gen_level_state); +} + +static void gen_move_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ +} + +static void gen_move_set_unack(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ +} + +static const struct bt_mesh_model_op gen_level_op[] = { + { BT_MESH_MODEL_OP_2(0x82, 0x05), 0, gen_level_get }, + { BT_MESH_MODEL_OP_2(0x82, 0x06), 3, gen_level_set }, + { BT_MESH_MODEL_OP_2(0x82, 0x07), 3, gen_level_set_unack }, + { BT_MESH_MODEL_OP_2(0x82, 0x09), 5, gen_delta_set }, + { BT_MESH_MODEL_OP_2(0x82, 0x0a), 5, gen_delta_set_unack }, + { BT_MESH_MODEL_OP_2(0x82, 0x0b), 3, gen_move_set }, + { BT_MESH_MODEL_OP_2(0x82, 0x0c), 3, gen_move_set_unack }, + BT_MESH_MODEL_OP_END, +}; + +static struct bt_mesh_model root_models[] = { + BT_MESH_MODEL_CFG_SRV(&cfg_srv), + BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_op, + &gen_onoff_pub, NULL), + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_LEVEL_SRV, gen_level_op, + &gen_level_pub, NULL), +}; + +static struct bt_mesh_model vnd_models[] = { + BT_MESH_MODEL_VND(CID_VENDOR, BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_op, + &gen_onoff_pub, 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 int output_number(bt_mesh_output_action_t action, uint32_t number) +{ + ESP_LOGI(tag, "OOB Number: %u\n", number); + + return 0; +} + +static void prov_complete(u16_t net_idx, u16_t addr) +{ + ESP_LOGI(tag, "Local node provisioned, primary address 0x%04x\n", addr); +} + +static const uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID); + +static const struct bt_mesh_prov prov = { + .uuid = dev_uuid, + .output_size = 4, + .output_actions = BT_MESH_DISPLAY_NUMBER | BT_MESH_BEEP | BT_MESH_VIBRATE | BT_MESH_BLINK, + .output_number = output_number, + .complete = prov_complete, +}; + +static void +blemesh_on_reset(int reason) +{ + BLE_HS_LOG(ERROR, "Resetting state; reason=%d\n", reason); +} + +static void +blemesh_on_sync(void) +{ + int err; + ble_addr_t addr; + + ESP_LOGI(tag, "Bluetooth initialized\n"); + + /* 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); + if (err) { + ESP_LOGI(tag, "Initializing mesh failed (err %d)\n", err); + return; + } + + ESP_LOGI(tag, "Mesh initialized\n"); + + if (IS_ENABLED(CONFIG_SETTINGS)) { + settings_load(); + } + + if (bt_mesh_is_provisioned()) { + ESP_LOGI(tag, "Mesh network restored from flash\n"); + } +} + +void blemesh_host_task(void *param) +{ + ble_hs_cfg.reset_cb = blemesh_on_reset; + ble_hs_cfg.sync_cb = blemesh_on_sync; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + health_pub_init(); + nimble_port_run(); +} + +void app_main() +{ + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init()); + nimble_port_init(); + + ble_svc_gap_init(); + ble_svc_gatt_init(); + + bt_mesh_register_gatt(); + /* XXX Need to have template for store */ + ble_store_ram_init(); + + nimble_port_freertos_init(blemesh_host_task); +} diff --git a/examples/bluetooth/nimble/blemesh/main/component.mk b/examples/bluetooth/nimble/blemesh/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/bluetooth/nimble/blemesh/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/bluetooth/nimble/blemesh/sdkconfig.defaults b/examples/bluetooth/nimble/blemesh/sdkconfig.defaults new file mode 100644 index 000000000..7c8e90fad --- /dev/null +++ b/examples/bluetooth/nimble/blemesh/sdkconfig.defaults @@ -0,0 +1,13 @@ +# Override some defaults so BT stack is enabled +# in this example + +# +# BT config +# +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY= +CONFIG_BTDM_CTRL_MODE_BTDM= +CONFIG_BT_BLUEDROID_ENABLED= +CONFIG_BT_NIMBLE_ENABLED=y +CONFIG_BT_NIMBLE_MESH=y diff --git a/examples/bluetooth/nimble/bleprph/CMakeLists.txt b/examples/bluetooth/nimble/bleprph/CMakeLists.txt new file mode 100644 index 000000000..6e3fbcae3 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(bleprph) diff --git a/examples/bluetooth/nimble/bleprph/Makefile b/examples/bluetooth/nimble/bleprph/Makefile new file mode 100644 index 000000000..ef6746516 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := bleprph + +include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/nimble/bleprph/README.md b/examples/bluetooth/nimble/bleprph/README.md new file mode 100644 index 000000000..5630bd0ef --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/README.md @@ -0,0 +1,75 @@ +# BLE peripheral example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example creates GATT server and then starts advertising, waiting to be connected to a GATT client. + +It uses ESP32's Bluetooth controller and NimBLE stack based BLE host. + +This example aims at understanding GATT database configuration, advertisement and SMP related NimBLE APIs. + +It also demonstrates security features of NimBLE stack. SMP parameters like I/O capabilities of device, Bonding flag, MITM protection flag and Secure Connection only mode etc., can be configured through menuconfig options. + +To test this demo, any BLE scanner app can be used. + + +## How to use example + +### Configure the project + +``` +make menuconfig +``` + +* Set serial port under Serial Flasher Options. + +* Select I/O capabilities of device from 'Example Configuration > I/O Capability', default is 'Just_works'. + +* Enable/Disable other security related parameters 'Bonding, MITM option, secure connection(SM SC)' from 'Example Configuration'. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +make -j4 flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +There is this console output when bleprph is connected and characteristic is read: + +``` + +I (118) BTDM_INIT: BT controller compile version [fe7ced0] +I (118) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +W (128) phy_init: failed to load RF calibration data (0xffffffff), falling back to full calibration +I (268) phy: phy_version: 4100, 6fa5e27, Jan 25 2019, 17:02:06, 0, 2 +I (508) NimBLE_BLE_PRPH: BLE Host Task Started +I (508) uart: queue free spaces: 8 +GAP procedure initiated: stop advertising. +Device Address: xx:xx:xx:xx:xx:xx +GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=0 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=0 adv_itvl_max=0 +connection established; status=0 handle=0 our_ota_addr_type=0 our_ota_addr=xx:xx:xx:xx:xx:xx our_id_addr_type=0 our_id_addr=xx:xx:xx:xx:xx:xx peer_ota_addr_type=1 peer_ota_addr=xx:xx:xx:xx:xx:xx peer_id_addr_type=1 peer_id_addr=xx:xx:xx:xx:xx:xx conn_itvl=39 conn_latency=0 supervision_timeout=500 encrypted=0 authenticated=0 bonded=0 + +connection updated; status=0 handle=0 our_ota_addr_type=0 our_ota_addr=xx:xx:xx:xx:xx:xx our_id_addr_type=0 our_id_addr=xx:xx:xx:xx:xx:xx peer_ota_addr_type=1 peer_ota_addr=xx:xx:xx:xx:xx:xx peer_id_addr_type=1 peer_id_addr=xx:xx:xx:xx:xx:xx conn_itvl=6 conn_latency=0 supervision_timeout=500 encrypted=0 authenticated=0 bonded=0 + +I (50888) NimBLE_BLE_PRPH: PASSKEY_ACTION_EVENT started + +I (50888) NimBLE_BLE_PRPH: Passkey on device's display: xxxxxx +I (50888) NimBLE_BLE_PRPH: Accept or reject the passkey through console in this format -> key Y or key N +key Y +I (50898) NimBLE_BLE_PRPH: ble_sm_inject_io result: 0 + +encryption change event; status=0 handle=0 our_ota_addr_type=0 our_ota_addr=xx:xx:xx:xx:xx:xx our_id_addr_type=0 our_id_addr=xx:xx:xx:xx:xx:xx peer_ota_addr_type=1 peer_ota_addr=xx:xx:xx:xx:xx:xx peer_id_addr_type=1 +peer_id_addr=xx:xx:xx:xx:xx:xx conn_itvl=6 conn_latency=0 supervision_timeout=500 encrypted=1 authenticated=1 bonded=1 + +connection updated; status=0 handle=0 our_ota_addr_type=0 our_ota_addr=xx:xx:xx:xx:xx:xx our_id_addr_type=0 our_id_addr=xx:xx:xx:xx:xx:xx +peer_ota_addr_type=1 peer_ota_addr=xx:xx:xx:xx:xx:xx peer_id_addr_type=1 peer_id_addr=xx:xx:xx:xx:xx:xx conn_itvl=39 conn_latency=0 supervision_timeout=500 encrypted=1 authenticated=1 bonded=1 + +``` + diff --git a/examples/bluetooth/nimble/bleprph/main/CMakeLists.txt b/examples/bluetooth/nimble/bleprph/main/CMakeLists.txt new file mode 100644 index 000000000..f57d248b3 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/main/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_SRCS "main.c" + "gatt_svr.c" + "misc.c" + "scli.c") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/bluetooth/nimble/bleprph/main/Kconfig.projbuild b/examples/bluetooth/nimble/bleprph/main/Kconfig.projbuild new file mode 100644 index 000000000..c9e425171 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/main/Kconfig.projbuild @@ -0,0 +1,51 @@ +menu "Example Configuration" + + choice EXAMPLE_USE_IO_TYPE + prompt "I/O Capability" + default BLE_SM_IO_CAP_NO_IO + help + I/O capability of device. + + config BLE_SM_IO_CAP_DISP_ONLY + bool "DISPLAY ONLY" + config BLE_SM_IO_CAP_DISP_YES_NO + bool "DISPLAY YESNO" + config BLE_SM_IO_CAP_KEYBOARD_ONLY + bool "KEYBOARD ONLY" + config BLE_SM_IO_CAP_NO_IO + bool "Just works" + config BLE_SM_IO_CAP_KEYBOARD_DISP + bool "Both KEYBOARD & DISPLAY" + endchoice + + config EXAMPLE_IO_TYPE + int + default 0 if BLE_SM_IO_CAP_DISP_ONLY + default 1 if BLE_SM_IO_CAP_DISP_YES_NO + default 2 if BLE_SM_IO_CAP_KEYBOARD_ONLY + default 3 if BLE_SM_IO_CAP_NO_IO + default 4 if BLE_SM_IO_CAP_KEYBOARD_DISP + + config EXAMPLE_BONDING + bool + default n + prompt "Use Bonding" + help + Use this option to enable/disable bonding. + + config EXAMPLE_MITM + bool + default n + prompt "MITM security" + help + Use this option to enable/disable MITM security. + + config EXAMPLE_USE_SC + bool + depends on BT_NIMBLE_SM_SC + default n + prompt "Use Secure Connection feature" + help + Use this option to enable/disable Security Manager Secure Connection 4.2 feature. + +endmenu diff --git a/examples/bluetooth/nimble/bleprph/main/bleprph.h b/examples/bluetooth/nimble/bleprph/main/bleprph.h new file mode 100644 index 000000000..cf90b9fb6 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/main/bleprph.h @@ -0,0 +1,56 @@ +/* + * 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_BLEPRPH_ +#define H_BLEPRPH_ + +#include +#include "nimble/ble.h" +#include "modlog/modlog.h" +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_cfg; +struct ble_gatt_register_ctxt; + +/** GATT server. */ +#define GATT_SVR_SVC_ALERT_UUID 0x1811 +#define GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID 0x2A47 +#define GATT_SVR_CHR_NEW_ALERT 0x2A46 +#define GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID 0x2A48 +#define GATT_SVR_CHR_UNR_ALERT_STAT_UUID 0x2A45 +#define GATT_SVR_CHR_ALERT_NOT_CTRL_PT 0x2A44 + +void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); +int gatt_svr_init(void); + +/* Console */ +int scli_init(void); +int scli_receive_key(int *key); + +/** Misc. */ +void print_bytes(const uint8_t *bytes, int len); +void print_addr(const void *addr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/examples/bluetooth/nimble/bleprph/main/component.mk b/examples/bluetooth/nimble/bleprph/main/component.mk new file mode 100644 index 000000000..a98f634ea --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/bluetooth/nimble/bleprph/main/gatt_svr.c b/examples/bluetooth/nimble/bleprph/main/gatt_svr.c new file mode 100644 index 000000000..3a279b55e --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/main/gatt_svr.c @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include "host/ble_hs.h" +#include "host/ble_uuid.h" +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" +#include "bleprph.h" + +/** + * The vendor specific security test service consists of two characteristics: + * o random-number-generator: generates a random 32-bit number each time + * it is read. This characteristic can only be read over an encrypted + * connection. + * o static-value: a single-byte characteristic that can always be read, + * but can only be written over an encrypted connection. + */ + +/* 59462f12-9543-9999-12c8-58b459a2712d */ +static const ble_uuid128_t gatt_svr_svc_sec_test_uuid = + BLE_UUID128_INIT(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12, + 0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0x59); + +/* 5c3a659e-897e-45e1-b016-007107c96df6 */ +static const ble_uuid128_t gatt_svr_chr_sec_test_rand_uuid = + BLE_UUID128_INIT(0xf6, 0x6d, 0xc9, 0x07, 0x71, 0x00, 0x16, 0xb0, + 0xe1, 0x45, 0x7e, 0x89, 0x9e, 0x65, 0x3a, 0x5c); + +/* 5c3a659e-897e-45e1-b016-007107c96df7 */ +static const ble_uuid128_t gatt_svr_chr_sec_test_static_uuid = + BLE_UUID128_INIT(0xf7, 0x6d, 0xc9, 0x07, 0x71, 0x00, 0x16, 0xb0, + 0xe1, 0x45, 0x7e, 0x89, 0x9e, 0x65, 0x3a, 0x5c); + +static uint8_t gatt_svr_sec_test_static_val; + +static int +gatt_svr_chr_access_sec_test(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, + void *arg); + +static const struct ble_gatt_svc_def gatt_svr_svcs[] = { + { + /*** Service: Security test. */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &gatt_svr_svc_sec_test_uuid.u, + .characteristics = (struct ble_gatt_chr_def[]) + { { + /*** Characteristic: Random number generator. */ + .uuid = &gatt_svr_chr_sec_test_rand_uuid.u, + .access_cb = gatt_svr_chr_access_sec_test, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC, + }, { + /*** Characteristic: Static value. */ + .uuid = &gatt_svr_chr_sec_test_static_uuid.u, + .access_cb = gatt_svr_chr_access_sec_test, + .flags = BLE_GATT_CHR_F_READ | + BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC, + }, { + 0, /* No more characteristics in this service. */ + } + }, + }, + + { + 0, /* No more services. */ + }, +}; + +static int +gatt_svr_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len, + void *dst, uint16_t *len) +{ + uint16_t om_len; + int rc; + + om_len = OS_MBUF_PKTLEN(om); + if (om_len < min_len || om_len > max_len) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + + rc = ble_hs_mbuf_to_flat(om, dst, max_len, len); + if (rc != 0) { + return BLE_ATT_ERR_UNLIKELY; + } + + return 0; +} + +static int +gatt_svr_chr_access_sec_test(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, + void *arg) +{ + const ble_uuid_t *uuid; + int rand_num; + int rc; + + uuid = ctxt->chr->uuid; + + /* Determine which characteristic is being accessed by examining its + * 128-bit UUID. + */ + + if (ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_rand_uuid.u) == 0) { + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + + /* Respond with a 32-bit random number. */ + rand_num = rand(); + rc = os_mbuf_append(ctxt->om, &rand_num, sizeof rand_num); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + + if (ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_static_uuid.u) == 0) { + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + rc = os_mbuf_append(ctxt->om, &gatt_svr_sec_test_static_val, + sizeof gatt_svr_sec_test_static_val); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + rc = gatt_svr_chr_write(ctxt->om, + sizeof gatt_svr_sec_test_static_val, + sizeof gatt_svr_sec_test_static_val, + &gatt_svr_sec_test_static_val, NULL); + return rc; + + default: + assert(0); + return BLE_ATT_ERR_UNLIKELY; + } + } + + /* Unknown characteristic; the nimble stack should not have called this + * function. + */ + assert(0); + return BLE_ATT_ERR_UNLIKELY; +} + +void +gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) +{ + char buf[BLE_UUID_STR_LEN]; + + switch (ctxt->op) { + case BLE_GATT_REGISTER_OP_SVC: + MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n", + ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf), + ctxt->svc.handle); + break; + + case BLE_GATT_REGISTER_OP_CHR: + MODLOG_DFLT(DEBUG, "registering characteristic %s with " + "def_handle=%d val_handle=%d\n", + ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), + ctxt->chr.def_handle, + ctxt->chr.val_handle); + break; + + case BLE_GATT_REGISTER_OP_DSC: + MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n", + ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf), + ctxt->dsc.handle); + break; + + default: + assert(0); + break; + } +} + +int +gatt_svr_init(void) +{ + int rc; + + ble_svc_gap_init(); + ble_svc_gatt_init(); + + rc = ble_gatts_count_cfg(gatt_svr_svcs); + if (rc != 0) { + return rc; + } + + rc = ble_gatts_add_svcs(gatt_svr_svcs); + if (rc != 0) { + return rc; + } + + return 0; +} diff --git a/examples/bluetooth/nimble/bleprph/main/main.c b/examples/bluetooth/nimble/bleprph/main/main.c new file mode 100644 index 000000000..58fc39a34 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/main/main.c @@ -0,0 +1,388 @@ +/* + * 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 "esp_log.h" +#include "nvs_flash.h" +/* BLE */ +#include "esp_nimble_hci.h" +#include "nimble/nimble_port.h" +#include "nimble/nimble_port_freertos.h" +#include "host/ble_hs.h" +#include "host/util/util.h" +#include "console/console.h" +#include "services/gap/ble_svc_gap.h" +#include "bleprph.h" + +static const char *tag = "NimBLE_BLE_PRPH"; +static int bleprph_gap_event(struct ble_gap_event *event, void *arg); +static uint8_t own_addr_type; + +void ble_store_config_init(void); + +/** + * Logs information about a connection to the console. + */ +static void +bleprph_print_conn_desc(struct ble_gap_conn_desc *desc) +{ + MODLOG_DFLT(INFO, "handle=%d our_ota_addr_type=%d our_ota_addr=", + desc->conn_handle, desc->our_ota_addr.type); + print_addr(desc->our_ota_addr.val); + MODLOG_DFLT(INFO, " our_id_addr_type=%d our_id_addr=", + desc->our_id_addr.type); + print_addr(desc->our_id_addr.val); + MODLOG_DFLT(INFO, " peer_ota_addr_type=%d peer_ota_addr=", + desc->peer_ota_addr.type); + print_addr(desc->peer_ota_addr.val); + MODLOG_DFLT(INFO, " peer_id_addr_type=%d peer_id_addr=", + desc->peer_id_addr.type); + print_addr(desc->peer_id_addr.val); + MODLOG_DFLT(INFO, " conn_itvl=%d conn_latency=%d supervision_timeout=%d " + "encrypted=%d authenticated=%d bonded=%d\n", + desc->conn_itvl, desc->conn_latency, + desc->supervision_timeout, + desc->sec_state.encrypted, + desc->sec_state.authenticated, + desc->sec_state.bonded); +} + +/** + * Enables advertising with the following parameters: + * o General discoverable mode. + * o Undirected connectable mode. + */ +static void +bleprph_advertise(void) +{ + struct ble_gap_adv_params adv_params; + struct ble_hs_adv_fields fields; + const char *name; + int rc; + + /** + * Set the advertisement data included in our advertisements: + * o Flags (indicates advertisement type and other general info). + * o Advertising tx power. + * o Device name. + * o 16-bit service UUIDs (alert notifications). + */ + + memset(&fields, 0, sizeof fields); + + /* Advertise two flags: + * o Discoverability in forthcoming advertisement (general) + * o BLE-only (BR/EDR unsupported). + */ + fields.flags = BLE_HS_ADV_F_DISC_GEN | + BLE_HS_ADV_F_BREDR_UNSUP; + + /* Indicate that the TX power level field should be included; have the + * stack fill this value automatically. This is done by assiging the + * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. + */ + fields.tx_pwr_lvl_is_present = 1; + fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + + name = ble_svc_gap_device_name(); + fields.name = (uint8_t *)name; + fields.name_len = strlen(name); + fields.name_is_complete = 1; + + fields.uuids16 = (ble_uuid16_t[]) { + BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID) + }; + fields.num_uuids16 = 1; + fields.uuids16_is_complete = 1; + + rc = ble_gap_adv_set_fields(&fields); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc); + return; + } + + /* Begin advertising. */ + memset(&adv_params, 0, sizeof adv_params); + adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; + adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; + rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, + &adv_params, bleprph_gap_event, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc); + return; + } +} + +/** + * The nimble host executes this callback when a GAP event occurs. The + * application associates a GAP event callback with each connection that forms. + * bleprph uses the same callback for all connections. + * + * @param event The type of event being signalled. + * @param ctxt Various information pertaining to the event. + * @param arg Application-specified argument; unuesd by + * bleprph. + * + * @return 0 if the application successfully handled the + * event; nonzero on failure. The semantics + * of the return code is specific to the + * particular GAP event being signalled. + */ +static int +bleprph_gap_event(struct ble_gap_event *event, void *arg) +{ + struct ble_gap_conn_desc desc; + int rc; + + switch (event->type) { + case BLE_GAP_EVENT_CONNECT: + /* A new connection was established or a connection attempt failed. */ + MODLOG_DFLT(INFO, "connection %s; status=%d ", + event->connect.status == 0 ? "established" : "failed", + event->connect.status); + if (event->connect.status == 0) { + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + assert(rc == 0); + bleprph_print_conn_desc(&desc); + } + MODLOG_DFLT(INFO, "\n"); + + if (event->connect.status != 0) { + /* Connection failed; resume advertising. */ + bleprph_advertise(); + } + return 0; + + case BLE_GAP_EVENT_DISCONNECT: + MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason); + bleprph_print_conn_desc(&event->disconnect.conn); + MODLOG_DFLT(INFO, "\n"); + + /* Connection terminated; resume advertising. */ + bleprph_advertise(); + return 0; + + case BLE_GAP_EVENT_CONN_UPDATE: + /* The central has updated the connection parameters. */ + MODLOG_DFLT(INFO, "connection updated; status=%d ", + event->conn_update.status); + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + assert(rc == 0); + bleprph_print_conn_desc(&desc); + MODLOG_DFLT(INFO, "\n"); + return 0; + + case BLE_GAP_EVENT_ADV_COMPLETE: + MODLOG_DFLT(INFO, "advertise complete; reason=%d", + event->adv_complete.reason); + bleprph_advertise(); + return 0; + + case BLE_GAP_EVENT_ENC_CHANGE: + /* Encryption has been enabled or disabled for this connection. */ + MODLOG_DFLT(INFO, "encryption change event; status=%d ", + event->enc_change.status); + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + assert(rc == 0); + bleprph_print_conn_desc(&desc); + MODLOG_DFLT(INFO, "\n"); + return 0; + + case BLE_GAP_EVENT_SUBSCRIBE: + MODLOG_DFLT(INFO, "subscribe event; conn_handle=%d attr_handle=%d " + "reason=%d prevn=%d curn=%d previ=%d curi=%d\n", + event->subscribe.conn_handle, + event->subscribe.attr_handle, + event->subscribe.reason, + event->subscribe.prev_notify, + event->subscribe.cur_notify, + event->subscribe.prev_indicate, + event->subscribe.cur_indicate); + return 0; + + case BLE_GAP_EVENT_MTU: + MODLOG_DFLT(INFO, "mtu update event; conn_handle=%d cid=%d mtu=%d\n", + event->mtu.conn_handle, + event->mtu.channel_id, + event->mtu.value); + return 0; + + case BLE_GAP_EVENT_REPEAT_PAIRING: + /* We already have a bond with the peer, but it is attempting to + * establish a new secure link. This app sacrifices security for + * convenience: just throw away the old bond and accept the new link. + */ + + /* Delete the old bond. */ + rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc); + assert(rc == 0); + ble_store_util_delete_peer(&desc.peer_id_addr); + + /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should + * continue with the pairing operation. + */ + return BLE_GAP_REPEAT_PAIRING_RETRY; + + case BLE_GAP_EVENT_PASSKEY_ACTION: + ESP_LOGI(tag, "PASSKEY_ACTION_EVENT started \n"); + struct ble_sm_io pkey = {0}; + int key = 0; + + if (event->passkey.params.action == BLE_SM_IOACT_DISP) { + pkey.action = event->passkey.params.action; + pkey.passkey = 123456; // This is the passkey to be entered on peer + ESP_LOGI(tag, "Enter passkey %d on the peer side", pkey.passkey); + rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); + ESP_LOGI(tag, "ble_sm_inject_io result: %d\n", rc); + } else if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { + ESP_LOGI(tag, "Passkey on device's display: %d", event->passkey.params.numcmp); + ESP_LOGI(tag, "Accept or reject the passkey through console in this format -> key Y or key N"); + pkey.action = event->passkey.params.action; + if (scli_receive_key(&key)) { + pkey.numcmp_accept = key; + } else { + pkey.numcmp_accept = 0; + ESP_LOGE(tag, "Timeout! Rejecting the key"); + } + rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); + ESP_LOGI(tag, "ble_sm_inject_io result: %d\n", rc); + } else if (event->passkey.params.action == BLE_SM_IOACT_OOB) { + static uint8_t tem_oob[16] = {0}; + pkey.action = event->passkey.params.action; + for (int i = 0; i < 16; i++) { + pkey.oob[i] = tem_oob[i]; + } + rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); + ESP_LOGI(tag, "ble_sm_inject_io result: %d\n", rc); + } else if (event->passkey.params.action == BLE_SM_IOACT_INPUT) { + ESP_LOGI(tag, "Enter the passkey through console in this format-> key 123456"); + pkey.action = event->passkey.params.action; + if (scli_receive_key(&key)) { + pkey.passkey = key; + } else { + pkey.passkey = 0; + ESP_LOGE(tag, "Timeout! Passing 0 as the key"); + } + rc = ble_sm_inject_io(event->passkey.conn_handle, &pkey); + ESP_LOGI(tag, "ble_sm_inject_io result: %d\n", rc); + } + return 0; + } + + return 0; +} + +static void +bleprph_on_reset(int reason) +{ + MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason); +} + +static void +bleprph_on_sync(void) +{ + int rc; + + rc = ble_hs_util_ensure_addr(0); + assert(rc == 0); + + /* Figure out address to use while advertising (no privacy for now) */ + rc = ble_hs_id_infer_auto(0, &own_addr_type); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc); + return; + } + + /* Printing ADDR */ + uint8_t addr_val[6] = {0}; + rc = ble_hs_id_copy_addr(own_addr_type, addr_val, NULL); + + MODLOG_DFLT(INFO, "Device Address: "); + print_addr(addr_val); + MODLOG_DFLT(INFO, "\n"); + /* Begin advertising. */ + bleprph_advertise(); +} + +void bleprph_host_task(void *param) +{ + ESP_LOGI(tag, "BLE Host Task Started"); + /* This function will return only when nimble_port_stop() is executed */ + nimble_port_run(); + + nimble_port_freertos_deinit(); +} + +void +app_main(void) +{ + int rc; + + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_ERROR_CHECK(esp_nimble_hci_and_controller_init()); + + nimble_port_init(); + /* Initialize the NimBLE host configuration. */ + ble_hs_cfg.reset_cb = bleprph_on_reset; + ble_hs_cfg.sync_cb = bleprph_on_sync; + ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + ble_hs_cfg.sm_io_cap = CONFIG_EXAMPLE_IO_TYPE; +#ifdef CONFIG_EXAMPLE_BONDING + ble_hs_cfg.sm_bonding = 1; +#endif +#ifdef CONFIG_EXAMPLE_MITM + ble_hs_cfg.sm_mitm = 1; +#endif +#ifdef CONFIG_EXAMPLE_USE_SC + ble_hs_cfg.sm_sc = 1; +#else + ble_hs_cfg.sm_sc = 0; +#ifdef CONFIG_EXAMPLE_BONDING + ble_hs_cfg.sm_our_key_dist = 1; + ble_hs_cfg.sm_their_key_dist = 1; +#endif +#endif + + + rc = gatt_svr_init(); + assert(rc == 0); + + /* Set the default device name. */ + rc = ble_svc_gap_device_name_set("nimble-bleprph"); + assert(rc == 0); + + /* XXX Need to have template for store */ + ble_store_config_init(); + + nimble_port_freertos_init(bleprph_host_task); + + /* Initialize command line interface to accept input from user */ + rc = scli_init(); + if (rc != ESP_OK) { + ESP_LOGE(tag, "scli_init() failed"); + } +} diff --git a/examples/bluetooth/nimble/bleprph/main/misc.c b/examples/bluetooth/nimble/bleprph/main/misc.c new file mode 100644 index 000000000..640b7ff8b --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/main/misc.c @@ -0,0 +1,43 @@ +/* + * 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 "bleprph.h" + +/** + * Utility function to log an array of bytes. + */ +void +print_bytes(const uint8_t *bytes, int len) +{ + int i; + + for (i = 0; i < len; i++) { + MODLOG_DFLT(INFO, "%s0x%02x", i != 0 ? ":" : "", bytes[i]); + } +} + +void +print_addr(const void *addr) +{ + const uint8_t *u8p; + + u8p = addr; + MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x", + u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]); +} diff --git a/examples/bluetooth/nimble/bleprph/main/scli.c b/examples/bluetooth/nimble/bleprph/main/scli.c new file mode 100644 index 000000000..d5a2fe955 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/main/scli.c @@ -0,0 +1,161 @@ +/* + * Copyright 2019 Espressif Systems (Shanghai) PTE LTD + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "esp_log.h" +#include +#include +#include +#include +#include +#include +#include +#include "bleprph.h" + +#define BLE_RX_TIMEOUT (30000 / portTICK_PERIOD_MS) + +static TaskHandle_t cli_task; +static QueueHandle_t cli_handle; +static int stop; + +static int enter_passkey_handler(int argc, char *argv[]) +{ + int key; + char pkey[8]; + int num; + + if (argc != 2) { + return -1; + } + + sscanf(argv[1], "%s", pkey); + ESP_LOGI("You entered", "%s %s", argv[0], argv[1]); + num = pkey[0]; + + if (isalpha(num)) { + if ((strcasecmp(pkey, "Y") == 0) || (strcasecmp(pkey, "Yes") == 0)) { + key = 1; + xQueueSend(cli_handle, &key, 0); + } else { + key = 0; + xQueueSend(cli_handle, &key, 0); + } + } else { + sscanf(pkey, "%d", &key); + xQueueSend(cli_handle, &key, 0); + } + + return 0; +} + +int scli_receive_key(int *console_key) +{ + return xQueueReceive(cli_handle, console_key, BLE_RX_TIMEOUT); +} + +static esp_console_cmd_t cmds[] = { + { + .command = "key", + .help = "", + .func = enter_passkey_handler, + }, +}; + +static int ble_register_cli() +{ + int cmds_num = sizeof(cmds) / sizeof(esp_console_cmd_t); + int i; + for (i = 0; i < cmds_num; i++) { + esp_console_cmd_register(&cmds[i]); + } + return 0; +} + +static void scli_task(void *arg) +{ + int uart_num = (int) arg; + uint8_t linebuf[256]; + int i, cmd_ret; + esp_err_t ret; + QueueHandle_t uart_queue; + uart_event_t event; + + uart_driver_install(uart_num, 256, 0, 8, &uart_queue, 0); + /* Initialize the console */ + esp_console_config_t console_config = { + .max_cmdline_args = 8, + .max_cmdline_length = 256, + }; + + esp_console_init(&console_config); + + while (!stop) { + i = 0; + memset(linebuf, 0, sizeof(linebuf)); + do { + ret = xQueueReceive(uart_queue, (void * )&event, (portTickType)portMAX_DELAY); + if (ret != pdPASS) { + if (stop == 1) { + break; + } else { + continue; + } + } + if (event.type == UART_DATA) { + while (uart_read_bytes(uart_num, (uint8_t *) &linebuf[i], 1, 0)) { + if (linebuf[i] == '\r') { + uart_write_bytes(uart_num, "\r\n", 2); + } else { + uart_write_bytes(uart_num, (char *) &linebuf[i], 1); + } + i++; + } + } + } while ((i < 255) && linebuf[i - 1] != '\r'); + if (stop) { + break; + } + /* Remove the truncating \r\n */ + linebuf[strlen((char *)linebuf) - 1] = '\0'; + ret = esp_console_run((char *) linebuf, &cmd_ret); + if (ret < 0) { + break; + } + } + vTaskDelete(NULL); +} + +int scli_init() +{ + /* Register CLI "key " to accept input from user during pairing */ + ble_register_cli(); + + xTaskCreate(scli_task, "scli_cli", 4096, (void *) 0, 3, &cli_task); + if (cli_task == NULL) { + return ESP_FAIL; + } + cli_handle = xQueueCreate( 1, sizeof(int) ); + if (cli_handle == NULL) { + return ESP_FAIL; + } + return ESP_OK; +} diff --git a/examples/bluetooth/nimble/bleprph/sdkconfig.defaults b/examples/bluetooth/nimble/bleprph/sdkconfig.defaults new file mode 100644 index 000000000..4fa07777f --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/sdkconfig.defaults @@ -0,0 +1,12 @@ +# Override some defaults so BT stack is enabled +# in this example + +# +# BT config +# +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY= +CONFIG_BTDM_CTRL_MODE_BTDM= +CONFIG_BT_BLUEDROID_ENABLED= +CONFIG_BT_NIMBLE_ENABLED=y